mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-06 17:33:18 +00:00
[dtable] cleanup: removed related files and code (#4314)
This commit is contained in:
@@ -1,161 +0,0 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Select from 'react-select';
|
||||
import makeAnimated from 'react-select/lib/animated';
|
||||
import { seafileAPI } from '../../utils/seafile-api.js';
|
||||
import { Button, Modal, ModalHeader, Input, ModalBody, ModalFooter, Form, FormGroup, Label, Alert } from 'reactstrap';
|
||||
import { gettext } from '../../utils/constants';
|
||||
|
||||
|
||||
const propTypes = {
|
||||
createDTable: PropTypes.func.isRequired,
|
||||
onAddDTable: PropTypes.func.isRequired,
|
||||
currentWorkspace: PropTypes.object,
|
||||
};
|
||||
|
||||
class CreateTableDialog extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
tableName: '',
|
||||
errMessage: '',
|
||||
isSubmitBtnActive: false,
|
||||
selectedOption: null,
|
||||
options:[],
|
||||
};
|
||||
this.newInput = React.createRef();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.newInput.focus();
|
||||
this.newInput.setSelectionRange(0,0);
|
||||
|
||||
let options = [];
|
||||
seafileAPI.getAccountInfo().then((res) => {
|
||||
let obj = {};
|
||||
obj.value = 'Personal';
|
||||
obj.email = res.data.email;
|
||||
obj.label = 'Personal';
|
||||
options.push(obj);
|
||||
seafileAPI.listGroups().then((res) => {
|
||||
for (let i = 0 ; i < res.data.length; i++) {
|
||||
let obj = {};
|
||||
obj.value = res.data[i].name;
|
||||
obj.email = res.data[i].id + '@seafile_group';
|
||||
obj.label = res.data[i].name;
|
||||
options.push(obj);
|
||||
}
|
||||
this.setState({options: options});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
handleChange = (e) => {
|
||||
if (!e.target.value.trim()) {
|
||||
this.setState({isSubmitBtnActive: false});
|
||||
} else {
|
||||
this.setState({isSubmitBtnActive: true});
|
||||
}
|
||||
|
||||
this.setState({
|
||||
tableName: e.target.value,
|
||||
}) ;
|
||||
}
|
||||
|
||||
handleSelectChange = (option) => {
|
||||
this.setState({selectedOption: option});
|
||||
}
|
||||
|
||||
handleSubmit = () => {
|
||||
if (!this.state.isSubmitBtnActive) return;
|
||||
if (!this.validateInputParams()) return;
|
||||
const space = this.props.currentWorkspace;
|
||||
const options = this.state.options;
|
||||
let email;
|
||||
if (space) {
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
if ((space.owner_type === 'Personal' && options[i].value === 'Personal') || (space.owner_type === 'Group' && options[i].value === space.owner_name)) {
|
||||
email = options[i].email;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
email = this.state.selectedOption.email;
|
||||
}
|
||||
this.props.createDTable(this.state.tableName.trim(), email);
|
||||
}
|
||||
|
||||
handleKeyPress = (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
this.handleSubmit();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
toggle = () => {
|
||||
this.props.onAddDTable();
|
||||
}
|
||||
|
||||
validateInputParams = () => {
|
||||
let errMessage = '';
|
||||
let tableName = this.state.tableName.trim();
|
||||
if (!tableName.length) {
|
||||
errMessage = gettext('Name is required');
|
||||
this.setState({errMessage: errMessage});
|
||||
return false;
|
||||
}
|
||||
if (tableName.indexOf('/') > -1) {
|
||||
errMessage = gettext('Name should not include \'/\'.');
|
||||
this.setState({errMessage: errMessage});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { currentWorkspace } = this.props;
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.toggle}>
|
||||
<ModalHeader toggle={this.toggle}>{gettext('New Table')}</ModalHeader>
|
||||
<ModalBody>
|
||||
<Form>
|
||||
<FormGroup>
|
||||
<Label for="tableName">{gettext('Name')}</Label>
|
||||
<Input
|
||||
id="tableName"
|
||||
onKeyPress={this.handleKeyPress}
|
||||
innerRef={input => {this.newInput = input;}}
|
||||
value={this.state.tableName}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
{this.state.errMessage && <Alert color="danger" className="mt-2">{this.state.errMessage}</Alert>}
|
||||
{!currentWorkspace &&
|
||||
<Fragment>
|
||||
<Label>{gettext('Belong to')}</Label>
|
||||
<Select
|
||||
isClearable
|
||||
isMulti={false}
|
||||
maxMenuHeight={200}
|
||||
hideSelectedOptions={true}
|
||||
components={makeAnimated()}
|
||||
placeholder=''
|
||||
options={this.state.options}
|
||||
onChange={this.handleSelectChange}
|
||||
/>
|
||||
</Fragment>
|
||||
}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button color="secondary" onClick={this.toggle}>{gettext('Cancel')}</Button>
|
||||
<Button color="primary" onClick={this.handleSubmit} disabled={!this.state.isSubmitBtnActive}>{gettext('Submit')}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CreateTableDialog.propTypes = propTypes;
|
||||
|
||||
export default CreateTableDialog;
|
@@ -1,39 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
|
||||
|
||||
const propTypes = {
|
||||
currentTable: PropTypes.object.isRequired,
|
||||
deleteCancel: PropTypes.func.isRequired,
|
||||
handleSubmit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DeleteTableDialog extends React.Component {
|
||||
|
||||
toggle = () => {
|
||||
this.props.deleteCancel();
|
||||
}
|
||||
|
||||
render() {
|
||||
let currentTable = this.props.currentTable;
|
||||
let name = currentTable.name;
|
||||
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.toggle}>
|
||||
<ModalHeader toggle={this.toggle}>{gettext('Delete Table')}</ModalHeader>
|
||||
<ModalBody>
|
||||
<p>{gettext('Are you sure to delete')}{' '}<b>{name}</b> ?</p>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button color="secondary" onClick={this.toggle}>{gettext('Cancel')}</Button>
|
||||
<Button color="primary" onClick={this.props.handleSubmit}>{gettext('Delete')}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteTableDialog.propTypes = propTypes;
|
||||
|
||||
export default DeleteTableDialog;
|
@@ -1,378 +0,0 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import moment from 'moment';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { Button, Form, FormGroup, Label, Input, InputGroup, InputGroupAddon, Alert } from 'reactstrap';
|
||||
import { gettext, shareLinkExpireDaysMin, shareLinkExpireDaysMax, shareLinkExpireDaysDefault, shareLinkPasswordMinLength, canSendShareLinkEmail } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import ShareLink from '../../models/share-link';
|
||||
import toaster from '../toast';
|
||||
import Loading from '../loading';
|
||||
import DTableShareLink from '../../models/dtable-share-link';
|
||||
|
||||
const propTypes = {
|
||||
workspaceID: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
closeShareDialog: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class GenerateDTableShareLink extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.isExpireDaysNoLimit = (parseInt(shareLinkExpireDaysMin) === 0 && parseInt(shareLinkExpireDaysMax) === 0 && shareLinkExpireDaysDefault == 0);
|
||||
this.defaultExpireDays = this.isExpireDaysNoLimit ? '' : shareLinkExpireDaysDefault;
|
||||
|
||||
this.isExpireDaysNoLimit = true;
|
||||
this.defaultExpireDays = '';
|
||||
|
||||
this.permissionOptions = ['read-only', 'read-write'];
|
||||
|
||||
this.state = {
|
||||
isValidate: false,
|
||||
isShowPasswordInput: false,
|
||||
isPasswordVisible: false,
|
||||
isExpireChecked: !this.isExpireDaysNoLimit,
|
||||
password: '',
|
||||
passwdnew: '',
|
||||
expireDays: this.defaultExpireDays,
|
||||
errorInfo: '',
|
||||
sharedLinkInfo: null,
|
||||
isNoticeMessageShow: false,
|
||||
isLoading: true,
|
||||
currentPermission: this.permissionOptions[0],
|
||||
isSendLinkShown: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let workspaceID = this.props.workspaceID;
|
||||
let name = this.props.name;
|
||||
seafileAPI.getDTableShareLink(workspaceID, name).then((res) => {
|
||||
window.res = res;
|
||||
if (res.data.dtable_share_links.length !== 0) {
|
||||
let sharedLinkInfo = new ShareLink(res.data.dtable_share_links[0]);
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
sharedLinkInfo: sharedLinkInfo
|
||||
});
|
||||
} else {
|
||||
this.setState({isLoading: false});
|
||||
}
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
onPasswordInputChecked = () => {
|
||||
this.setState({
|
||||
isShowPasswordInput: !this.state.isShowPasswordInput,
|
||||
password: '',
|
||||
passwdnew: '',
|
||||
errorInfo: ''
|
||||
});
|
||||
}
|
||||
|
||||
togglePasswordVisible = () => {
|
||||
this.setState({
|
||||
isPasswordVisible: !this.state.isPasswordVisible
|
||||
});
|
||||
}
|
||||
|
||||
generatePassword = () => {
|
||||
let val = Utils.generatePassword(shareLinkPasswordMinLength);
|
||||
this.setState({
|
||||
password: val,
|
||||
passwdnew: val
|
||||
});
|
||||
}
|
||||
|
||||
inputPassword = (e) => {
|
||||
let passwd = e.target.value.trim();
|
||||
this.setState({password: passwd});
|
||||
}
|
||||
|
||||
inputPasswordNew = (e) => {
|
||||
let passwd = e.target.value.trim();
|
||||
this.setState({passwdnew: passwd});
|
||||
}
|
||||
|
||||
generateDTableShareLink = () => {
|
||||
let isValid = this.validateParamsInput();
|
||||
if (isValid) {
|
||||
this.setState({errorInfo: ''});
|
||||
let { workspaceID, name } = this.props;
|
||||
let { password, isExpireChecked, expireDays } = this.state;
|
||||
let permission = Utils.getDTableShareLinkPermissionObject(this.state.currentPermission).permission;
|
||||
const expireDaysSent = isExpireChecked ? expireDays : '';
|
||||
seafileAPI.createDTableShareLink(workspaceID, name, password, expireDaysSent, permission).then((res) => {
|
||||
let sharedLinkInfo = new DTableShareLink(res.data);
|
||||
this.setState({sharedLinkInfo: sharedLinkInfo});
|
||||
}).catch((error) => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onCopySharedLink = () => {
|
||||
let sharedLink = this.state.sharedLinkInfo.link;
|
||||
copy(sharedLink);
|
||||
toaster.success(gettext('Share link is copied to the clipboard.'));
|
||||
this.props.closeShareDialog();
|
||||
}
|
||||
|
||||
deleteShareLink = () => {
|
||||
let sharedLinkInfo = this.state.sharedLinkInfo;
|
||||
seafileAPI.deleteDTableShareLink(sharedLinkInfo.token).then(() => {
|
||||
this.setState({
|
||||
password: '',
|
||||
passwordnew: '',
|
||||
isShowPasswordInput: false,
|
||||
expireDays: this.defaultExpireDays,
|
||||
isExpireChecked: !this.isExpireDaysNoLimit,
|
||||
errorInfo: '',
|
||||
sharedLinkInfo: null,
|
||||
isNoticeMessageShow: false,
|
||||
});
|
||||
}).catch((error) => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
onExpireChecked = (e) => {
|
||||
this.setState({isExpireChecked: e.target.checked});
|
||||
}
|
||||
|
||||
onExpireDaysChanged = (e) => {
|
||||
let day = e.target.value.trim();
|
||||
this.setState({expireDays: day});
|
||||
}
|
||||
|
||||
setPermission = (e) => {
|
||||
this.setState({currentPermission: e.target.value});
|
||||
}
|
||||
|
||||
validateParamsInput = () => {
|
||||
let { isShowPasswordInput , password, passwdnew, isExpireChecked, expireDays } = this.state;
|
||||
// validate password
|
||||
if (isShowPasswordInput) {
|
||||
if (password.length === 0) {
|
||||
this.setState({errorInfo: 'Please enter password'});
|
||||
return false;
|
||||
}
|
||||
if (password.length < shareLinkPasswordMinLength) {
|
||||
this.setState({errorInfo: 'Password is too short'});
|
||||
return false;
|
||||
}
|
||||
if (password !== passwdnew) {
|
||||
this.setState({errorInfo: 'Passwords don\'t match'});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// validate days
|
||||
// no limit
|
||||
let reg = /^\d+$/;
|
||||
if (this.isExpireDaysNoLimit) {
|
||||
if (isExpireChecked) {
|
||||
if (!expireDays) {
|
||||
this.setState({errorInfo: 'Please enter days'});
|
||||
return false;
|
||||
}
|
||||
if (!reg.test(expireDays)) {
|
||||
this.setState({errorInfo: 'Please enter a non-negative integer'});
|
||||
return false;
|
||||
}
|
||||
this.setState({expireDays: parseInt(expireDays)});
|
||||
}
|
||||
} else {
|
||||
if (!expireDays) {
|
||||
this.setState({errorInfo: 'Please enter days'});
|
||||
return false;
|
||||
}
|
||||
if (!reg.test(expireDays)) {
|
||||
this.setState({errorInfo: 'Please enter a non-negative integer'});
|
||||
return false;
|
||||
}
|
||||
|
||||
expireDays = parseInt(expireDays);
|
||||
let minDays = parseInt(shareLinkExpireDaysMin);
|
||||
let maxDays = parseInt(shareLinkExpireDaysMax);
|
||||
|
||||
if (minDays !== 0 && maxDays !== maxDays) {
|
||||
if (expireDays < minDays) {
|
||||
this.setState({errorInfo: 'Please enter valid days'});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (minDays === 0 && maxDays !== 0 ) {
|
||||
if (expireDays > maxDays) {
|
||||
this.setState({errorInfo: 'Please enter valid days'});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (minDays !== 0 && maxDays !== 0) {
|
||||
if (expireDays < minDays || expireDays > maxDays) {
|
||||
this.setState({errorInfo: 'Please enter valid days'});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.setState({expireDays: expireDays});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
onNoticeMessageToggle = () => {
|
||||
this.setState({isNoticeMessageShow: !this.state.isNoticeMessageShow});
|
||||
}
|
||||
|
||||
toggleSendLink = () => {
|
||||
this.setState({ isSendLinkShown: !this.state.isSendLinkShown });
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
if (this.state.isLoading) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
let passwordLengthTip = gettext('(at least {passwordLength} characters)');
|
||||
passwordLengthTip = passwordLengthTip.replace('{passwordLength}', shareLinkPasswordMinLength);
|
||||
|
||||
if (this.state.sharedLinkInfo) {
|
||||
let sharedLinkInfo = this.state.sharedLinkInfo;
|
||||
return (
|
||||
<div>
|
||||
<Form className="mb-4">
|
||||
<FormGroup className="mb-0">
|
||||
<dt className="text-secondary font-weight-normal">{gettext('Link:')}</dt>
|
||||
<dd className="d-flex">
|
||||
<span>{sharedLinkInfo.link}</span>{' '}
|
||||
{sharedLinkInfo.is_expired ?
|
||||
<span className="err-message">({gettext('Expired')})</span> :
|
||||
<span className="far fa-copy action-icon" onClick={this.onCopySharedLink}/>
|
||||
}
|
||||
</dd>
|
||||
</FormGroup>
|
||||
{sharedLinkInfo.expire_date && (
|
||||
<FormGroup className="mb-0">
|
||||
<dt className="text-secondary font-weight-normal">{gettext('Expiration Date:')}</dt>
|
||||
<dd>{moment(sharedLinkInfo.expire_date).format('YYYY-MM-DD hh:mm:ss')}</dd>
|
||||
</FormGroup>
|
||||
)}
|
||||
</Form>
|
||||
{(canSendShareLinkEmail && !this.state.isSendLinkShown && !this.state.isNoticeMessageShow) &&
|
||||
<Button onClick={this.toggleSendLink} className='mr-2'>{gettext('Send')}</Button>
|
||||
}
|
||||
{(!this.state.isSendLinkShown && !this.state.isNoticeMessageShow) &&
|
||||
<Button onClick={this.onNoticeMessageToggle}>{gettext('Delete')}</Button>
|
||||
}
|
||||
{this.state.isNoticeMessageShow &&
|
||||
<div className="alert alert-warning">
|
||||
<h4 className="alert-heading">{gettext('Are you sure you want to delete the share link?')}</h4>
|
||||
<p className="mb-4">{gettext('If the share link is deleted, no one will be able to access it any more.')}</p>
|
||||
<button className="btn btn-primary" onClick={this.deleteShareLink}>{gettext('Delete')}</button>{' '}
|
||||
<button className="btn btn-secondary" onClick={this.onNoticeMessageToggle}>{gettext('Cancel')}</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Form className="generate-share-link">
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input type="checkbox" onChange={this.onPasswordInputChecked}/>{' '}{gettext('Add password protection')}
|
||||
</Label>
|
||||
</FormGroup>
|
||||
{this.state.isShowPasswordInput &&
|
||||
<FormGroup className="link-operation-content" check>
|
||||
<Label className="font-weight-bold">{gettext('Password')}</Label>{' '}<span className="tip">{passwordLengthTip}</span>
|
||||
<InputGroup className="passwd">
|
||||
<Input type={this.state.isPasswordVisible ? 'text' : 'password'} value={this.state.password || ''} onChange={this.inputPassword}/>
|
||||
<InputGroupAddon addonType="append">
|
||||
<Button onClick={this.togglePasswordVisible}><i className={`link-operation-icon fas ${this.state.isPasswordVisible ? 'fa-eye': 'fa-eye-slash'}`}></i></Button>
|
||||
<Button onClick={this.generatePassword}><i className="link-operation-icon fas fa-magic"></i></Button>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
<Label className="font-weight-bold">{gettext('Password again')}</Label>
|
||||
<Input className="passwd" type={this.state.isPasswordVisible ? 'text' : 'password'} value={this.state.passwdnew || ''} onChange={this.inputPasswordNew} />
|
||||
</FormGroup>
|
||||
}
|
||||
{this.isExpireDaysNoLimit && (
|
||||
<Fragment>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input className="expire-checkbox" type="checkbox" onChange={this.onExpireChecked} />{' '}{gettext('Add auto expiration')}
|
||||
</Label>
|
||||
</FormGroup>
|
||||
{this.state.isExpireChecked &&
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input className="expire-input expire-input-border" type="text" value={this.state.expireDays} onChange={this.onExpireDaysChanged} readOnly={!this.state.isExpireChecked} /><span className="expir-span">{gettext('days')}</span>
|
||||
</Label>
|
||||
</FormGroup>
|
||||
}
|
||||
</Fragment>
|
||||
)}
|
||||
{!this.isExpireDaysNoLimit && (
|
||||
<Fragment>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input className="expire-checkbox" type="checkbox" onChange={this.onExpireChecked} checked readOnly disabled/>{' '}{gettext('Add auto expiration')}
|
||||
</Label>
|
||||
</FormGroup>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input className="expire-input expire-input-border" type="text" value={this.state.expireDays} onChange={this.onExpireDaysChanged} /><span className="expir-span">{gettext('days')}</span>
|
||||
{(parseInt(shareLinkExpireDaysMin) !== 0 && parseInt(shareLinkExpireDaysMax) !== 0) && (
|
||||
<span className="d-inline-block ml-7">({shareLinkExpireDaysMin} - {shareLinkExpireDaysMax}{' '}{gettext('days')})</span>
|
||||
)}
|
||||
{(parseInt(shareLinkExpireDaysMin) !== 0 && parseInt(shareLinkExpireDaysMax) === 0) && (
|
||||
<span className="d-inline-block ml-7">({gettext('Greater than or equal to')} {shareLinkExpireDaysMin}{' '}{gettext('days')})</span>
|
||||
)}
|
||||
{(parseInt(shareLinkExpireDaysMin) === 0 && parseInt(shareLinkExpireDaysMax) !== 0) && (
|
||||
<span className="d-inline-block ml-7">({gettext('Less than or equal to')} {shareLinkExpireDaysMax}{' '}{gettext('days')})</span>
|
||||
)}
|
||||
</Label>
|
||||
</FormGroup>
|
||||
</Fragment>
|
||||
)}
|
||||
|
||||
<Fragment>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<span>{gettext('Set permission')}</span>
|
||||
</Label>
|
||||
</FormGroup>
|
||||
{this.permissionOptions.map((item, index) => {
|
||||
return (
|
||||
<FormGroup check className="permission" key={index}>
|
||||
<Label className="form-check-label">
|
||||
<Input type="radio" name="permission" value={item} checked={this.state.currentPermission == item} onChange={this.setPermission} className="mr-1" />
|
||||
{Utils.getDTableShareLinkPermissionObject(item).text}
|
||||
</Label>
|
||||
</FormGroup>
|
||||
);
|
||||
})}
|
||||
</Fragment>
|
||||
|
||||
{this.state.errorInfo && <Alert color="danger" className="mt-2">{gettext(this.state.errorInfo)}</Alert>}
|
||||
<Button onClick={this.generateDTableShareLink} className="mt-2">{gettext('Generate')}</Button>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GenerateDTableShareLink.propTypes = propTypes;
|
||||
|
||||
export default GenerateDTableShareLink;
|
@@ -1,93 +0,0 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {gettext} from '../../utils/constants';
|
||||
import {Modal, ModalHeader, ModalBody, Nav, NavItem, NavLink, TabContent, TabPane} from 'reactstrap';
|
||||
import ShareTableToUser from './share-table-to-user';
|
||||
|
||||
import '../../css/share-link-dialog.css';
|
||||
import GenerateDTableShareLink from './generate-dtable-share-link';
|
||||
|
||||
const propTypes = {
|
||||
currentTable: PropTypes.object.isRequired,
|
||||
ShareCancel: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class ShareTableDialog extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
activeTab: 'shareToUser',
|
||||
};
|
||||
}
|
||||
|
||||
toggle = (tab) => {
|
||||
if (this.state.activeTab !== tab) {
|
||||
this.setState({activeTab: tab});
|
||||
}
|
||||
};
|
||||
|
||||
renderContent = () => {
|
||||
let activeTab = this.state.activeTab;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="share-dialog-side">
|
||||
<Nav pills vertical>
|
||||
<Fragment>
|
||||
<NavItem>
|
||||
<NavLink
|
||||
className={activeTab === 'shareToUser' ? 'active' : ''}
|
||||
onClick={this.toggle.bind(this, 'shareToUser')}
|
||||
>{gettext('Share to user')}
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
<NavItem>
|
||||
<NavLink
|
||||
className={activeTab === 'shareLink' ? 'active' : ''}
|
||||
onClick={this.toggle.bind(this, 'shareLink')}
|
||||
>{gettext('Share link')}
|
||||
</NavLink>
|
||||
</NavItem>
|
||||
</Fragment>
|
||||
</Nav>
|
||||
</div>
|
||||
<div className="share-dialog-main">
|
||||
<TabContent activeTab={this.state.activeTab}>
|
||||
<Fragment>
|
||||
<TabPane tabId="shareToUser">
|
||||
<ShareTableToUser
|
||||
currentTable={this.props.currentTable}
|
||||
/>
|
||||
</TabPane>
|
||||
{activeTab === 'shareLink' &&
|
||||
<GenerateDTableShareLink
|
||||
workspaceID={this.props.currentTable.workspace_id}
|
||||
name={this.props.currentTable.name}
|
||||
closeShareDialog={this.props.ShareCancel}
|
||||
/>
|
||||
}
|
||||
</Fragment>
|
||||
</TabContent>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
let currentTable = this.props.currentTable;
|
||||
let name = currentTable.name;
|
||||
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.props.ShareCancel} style={{maxWidth: '720px'}} className="share-dialog" >
|
||||
<ModalHeader toggle={this.props.ShareCancel}>{gettext('Share')} <span className="op-target" title={name}>{name}</span></ModalHeader>
|
||||
<ModalBody className="share-dialog-content">
|
||||
{this.renderContent()}
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ShareTableDialog.propTypes = propTypes;
|
||||
|
||||
export default ShareTableDialog;
|
@@ -1,237 +0,0 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext, canInvitePeople, siteRoot } from '../../utils/constants';
|
||||
import { Button } from 'reactstrap';
|
||||
import { seafileAPI } from '../../utils/seafile-api.js';
|
||||
import UserSelect from '../user-select';
|
||||
import DtableSharePermissionEditor from '../select-editor/dtable-share-permission-editor';
|
||||
import toaster from '../toast';
|
||||
|
||||
import '../../css/invitations.css';
|
||||
|
||||
const userItemPropTypes = {
|
||||
item: PropTypes.object.isRequired,
|
||||
deleteTableShare: PropTypes.func.isRequired,
|
||||
updateTableShare: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class UserItem extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isOperationShow: false
|
||||
};
|
||||
}
|
||||
|
||||
onMouseEnter = () => {
|
||||
this.setState({isOperationShow: true});
|
||||
};
|
||||
|
||||
onMouseLeave = () => {
|
||||
this.setState({isOperationShow: false});
|
||||
};
|
||||
|
||||
deleteTableShare = () => {
|
||||
this.props.deleteTableShare(this.props.item.email);
|
||||
};
|
||||
|
||||
updateTableShare = (permission) => {
|
||||
this.props.updateTableShare(this.props.item.email, permission);
|
||||
};
|
||||
|
||||
render() {
|
||||
let item = this.props.item;
|
||||
let currentPermission = item.permission;
|
||||
return (
|
||||
<tr onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
||||
<td className="name">{item.name}</td>
|
||||
<td>
|
||||
<DtableSharePermissionEditor
|
||||
isTextMode={true}
|
||||
isEditIconShow={this.state.isOperationShow}
|
||||
currentPermission={currentPermission}
|
||||
onPermissionChanged={this.updateTableShare}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<span
|
||||
className={`sf2-icon-x3 action-icon ${this.state.isOperationShow ? '' : 'hide'}`}
|
||||
onClick={this.deleteTableShare}
|
||||
title={gettext('Delete')}
|
||||
>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
UserItem.propTypes = userItemPropTypes;
|
||||
|
||||
const propTypes = {
|
||||
currentTable: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
class ShareTableToUser extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selectedOptions: null,
|
||||
permission: 'rw',
|
||||
userList: []
|
||||
};
|
||||
this.workspaceID = this.props.currentTable.workspace_id;
|
||||
this.tableName = this.props.currentTable.name;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
seafileAPI.listTableShares(this.workspaceID, this.tableName).then((res) => {
|
||||
this.setState({userList: res.data.user_list});
|
||||
});
|
||||
}
|
||||
|
||||
handleSelectChange = (options) => {
|
||||
this.setState({ selectedOptions: options });
|
||||
};
|
||||
|
||||
setPermission = (permission) => {
|
||||
this.setState({permission: permission});
|
||||
};
|
||||
|
||||
handleError = (e) => {
|
||||
if (e.response) {
|
||||
toaster.danger(e.response.data.error_msg || e.response.data.detail || gettext('Error'), {duration: 3});
|
||||
} else {
|
||||
toaster.danger(gettext('Please check the network.'), {duration: 3});
|
||||
}
|
||||
};
|
||||
|
||||
addTableShare = () => {
|
||||
const { selectedOptions, permission, userList } = this.state;
|
||||
if (!selectedOptions || selectedOptions.length === 0) return;
|
||||
for (let i = 0; i < selectedOptions.length; i++) {
|
||||
let name = selectedOptions[i].value;
|
||||
let email = selectedOptions[i].email;
|
||||
seafileAPI.addTableShare(this.workspaceID, this.tableName, email, permission).then((res) => {
|
||||
let userInfo = {
|
||||
name: name,
|
||||
email: email,
|
||||
permission: permission,
|
||||
};
|
||||
userList.push(userInfo);
|
||||
this.setState({ userList: userList });
|
||||
}).catch(error => {
|
||||
this.handleError(error);
|
||||
});
|
||||
}
|
||||
this.setState({ selectedOption: null });
|
||||
this.refs.userSelect.clearSelect();
|
||||
};
|
||||
|
||||
deleteTableShare = (email) => {
|
||||
seafileAPI.deleteTableShare(this.workspaceID, this.tableName, email).then((res) => {
|
||||
let userList = this.state.userList.filter(userInfo => {
|
||||
return userInfo.email !== email;
|
||||
});
|
||||
this.setState({
|
||||
userList: userList,
|
||||
});
|
||||
}).catch(error => {
|
||||
this.handleError(error);
|
||||
});
|
||||
};
|
||||
|
||||
updateTableShare = (email, permission) => {
|
||||
seafileAPI.updateTableShare(this.workspaceID, this.tableName, email, permission).then((res) => {
|
||||
let userList = this.state.userList.filter(userInfo => {
|
||||
if (userInfo.email === email) {
|
||||
userInfo.permission = permission;
|
||||
}
|
||||
return userInfo;
|
||||
});
|
||||
this.setState({
|
||||
userList: userList,
|
||||
});
|
||||
}).catch(error => {
|
||||
this.handleError(error);
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const renderUserList = this.state.userList.map((item, index) => {
|
||||
return (
|
||||
<UserItem
|
||||
key={index}
|
||||
item={item}
|
||||
permissions={['rw', 'r']}
|
||||
deleteTableShare={this.deleteTableShare}
|
||||
updateTableShare={this.updateTableShare}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50%">{gettext('User')}</th>
|
||||
<th width="35%">{gettext('Permission')}</th>
|
||||
<th width="15%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<UserSelect
|
||||
ref="userSelect"
|
||||
isMulti={true}
|
||||
className="reviewer-select"
|
||||
placeholder={gettext('Select users...')}
|
||||
onSelectChange={this.handleSelectChange}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<DtableSharePermissionEditor
|
||||
isTextMode={false}
|
||||
isEditIconShow={false}
|
||||
currentPermission={this.state.permission}
|
||||
onPermissionChanged={this.setPermission}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<Button onClick={this.addTableShare}>{gettext('Submit')}</Button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="share-list-container">
|
||||
<table className="table-thead-hidden">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50%">{gettext('User')}</th>
|
||||
<th width="35%">{gettext('Permission')}</th>
|
||||
<th width="15%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{renderUserList}
|
||||
</tbody>
|
||||
</table>
|
||||
{ canInvitePeople &&
|
||||
<a href={siteRoot + 'invitations/'} className="invite-link-in-popup">
|
||||
<i className="sf2-icon-invite invite-link-icon-in-popup"></i>
|
||||
<span className="invite-link-icon-in-popup">{gettext('Invite People')}</span>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ShareTableToUser.propTypes = propTypes;
|
||||
|
||||
export default ShareTableToUser;
|
@@ -1,310 +0,0 @@
|
||||
import React, {Fragment} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {gettext} from '../../utils/constants';
|
||||
import {Modal, ModalHeader, ModalBody, Button, Input} from 'reactstrap';
|
||||
import DtableSharePermissionEditor from '../select-editor/dtable-share-permission-editor';
|
||||
import {seafileAPI} from '../../utils/seafile-api';
|
||||
import toaster from '../toast';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import Loading from '../loading';
|
||||
|
||||
import '../../css/share-link-dialog.css';
|
||||
|
||||
|
||||
const apiTokenItemPropTypes = {
|
||||
item: PropTypes.object.isRequired,
|
||||
deleteAPIToken: PropTypes.func.isRequired,
|
||||
updateAPIToken: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class APITokenItem extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isOperationShow: false,
|
||||
};
|
||||
}
|
||||
|
||||
onMouseEnter = () => {
|
||||
this.setState({isOperationShow: true});
|
||||
};
|
||||
|
||||
onMouseLeave = () => {
|
||||
this.setState({isOperationShow: false});
|
||||
};
|
||||
|
||||
onDeleteAPIToken = () => {
|
||||
this.props.deleteAPIToken(this.props.item.app_name);
|
||||
};
|
||||
|
||||
onUpdateAPIToken = (permission) => {
|
||||
this.props.updateAPIToken(this.props.item.app_name, permission);
|
||||
};
|
||||
|
||||
onCopyAPIToken = () => {
|
||||
let api_token = this.props.item.api_token;
|
||||
copy(api_token);
|
||||
toaster.success(gettext('API Token is copied to the clipboard.'));
|
||||
};
|
||||
|
||||
render() {
|
||||
let item = this.props.item;
|
||||
|
||||
return (
|
||||
<tr onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
||||
<td className="name">{item.app_name}</td>
|
||||
<td>
|
||||
<DtableSharePermissionEditor
|
||||
isTextMode={true}
|
||||
isEditIconShow={this.state.isOperationShow}
|
||||
currentPermission={item.permission}
|
||||
onPermissionChanged={this.onUpdateAPIToken}
|
||||
/>
|
||||
</td>
|
||||
<td>{item.api_token}</td>
|
||||
<td>
|
||||
<span
|
||||
className="far fa-copy action-icon"
|
||||
onClick={this.onCopyAPIToken}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<span
|
||||
className={`sf2-icon-x3 action-icon ${this.state.isOperationShow ? '' : 'hide'}`}
|
||||
onClick={this.onDeleteAPIToken}
|
||||
title={gettext('Delete')}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
APITokenItem.propTypes = apiTokenItemPropTypes;
|
||||
|
||||
const propTypes = {
|
||||
currentTable: PropTypes.object.isRequired,
|
||||
onTableAPITokenToggle: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class TableAPITokenDialog extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
apiTokenList: [],
|
||||
permission: 'rw',
|
||||
appName: '',
|
||||
errorMsg: '',
|
||||
loading: true,
|
||||
isSubmitBtnActive: true,
|
||||
};
|
||||
this.workspaceID = this.props.currentTable.workspace_id;
|
||||
this.tableName = this.props.currentTable.name;
|
||||
}
|
||||
|
||||
listAPITokens = () => {
|
||||
seafileAPI.listTableAPITokens(this.workspaceID, this.tableName).then((res) => {
|
||||
this.setState({
|
||||
apiTokenList: res.data.api_tokens,
|
||||
loading: false,
|
||||
});
|
||||
}).catch(error => {
|
||||
if (error.response.status === 403) {
|
||||
this.setState({
|
||||
errorMsg: gettext('Permission denied'),
|
||||
});
|
||||
} else {
|
||||
this.handleError(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onInputChange = (e) => {
|
||||
let appName = e.target.value;
|
||||
this.setState({
|
||||
appName: appName,
|
||||
});
|
||||
};
|
||||
|
||||
onKeyDown = (e) => {
|
||||
if (e.keyCode === 13) {
|
||||
e.preventDefault();
|
||||
this.addAPIToken();
|
||||
}
|
||||
};
|
||||
|
||||
setPermission = (permission) => {
|
||||
this.setState({permission: permission});
|
||||
};
|
||||
|
||||
addAPIToken = () => {
|
||||
if (!this.state.appName) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
isSubmitBtnActive: false,
|
||||
});
|
||||
const {appName, permission, apiTokenList} = this.state;
|
||||
|
||||
seafileAPI.addTableAPIToken(this.workspaceID, this.tableName, appName, permission).then((res) => {
|
||||
apiTokenList.push(res.data);
|
||||
this.setState({
|
||||
apiTokenList: apiTokenList,
|
||||
isSubmitBtnActive: true,
|
||||
});
|
||||
}).catch(error => {
|
||||
this.handleError(error);
|
||||
this.setState({
|
||||
isSubmitBtnActive: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
deleteAPIToken = (appName) => {
|
||||
seafileAPI.deleteTableAPIToken(this.workspaceID, this.tableName, appName).then((res) => {
|
||||
const apiTokenList = this.state.apiTokenList.filter(item => {
|
||||
return item.app_name !== appName;
|
||||
});
|
||||
this.setState({
|
||||
apiTokenList: apiTokenList,
|
||||
});
|
||||
}).catch(error => {
|
||||
this.handleError(error);
|
||||
});
|
||||
};
|
||||
|
||||
updateAPIToken = (appName, permission) => {
|
||||
seafileAPI.updateTableAPIToken(this.workspaceID, this.tableName, appName, permission).then((res) => {
|
||||
let userList = this.state.apiTokenList.filter(item => {
|
||||
if (item.app_name === appName) {
|
||||
item.permission = permission;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.setState({
|
||||
userList: userList,
|
||||
});
|
||||
}).catch(error => {
|
||||
this.handleError(error);
|
||||
});
|
||||
};
|
||||
|
||||
handleError = (e) => {
|
||||
if (e.response) {
|
||||
toaster.danger(e.response.data.error_msg || e.response.data.detail || gettext('Error'), {duration: 3});
|
||||
} else {
|
||||
toaster.danger(gettext('Please check the network.'), {duration: 3});
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.listAPITokens();
|
||||
}
|
||||
|
||||
renderContent = () => {
|
||||
const renderAPITokenList = this.state.apiTokenList.map((item, index) => {
|
||||
return (
|
||||
<APITokenItem
|
||||
key={index}
|
||||
item={item}
|
||||
deleteAPIToken={this.deleteAPIToken}
|
||||
updateAPIToken={this.updateAPIToken}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{this.state.errorMsg &&
|
||||
<div className='w-100'>
|
||||
<p className="error text-center">{this.state.errorMsg}</p>
|
||||
</div>
|
||||
}
|
||||
{!this.state.errorMsg &&
|
||||
<div className='mx-5 mb-5' style={{height: 'auto'}}>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="45%">{gettext('App Name')}</th>
|
||||
<th width="40%">{gettext('Permission')}</th>
|
||||
<th width="15%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<Input
|
||||
type="text"
|
||||
id="appName"
|
||||
value={this.state.appName}
|
||||
onChange={this.onInputChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<DtableSharePermissionEditor
|
||||
isTextMode={false}
|
||||
isEditIconShow={false}
|
||||
currentPermission={this.state.permission}
|
||||
onPermissionChanged={this.setPermission}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<Button onClick={this.addAPIToken} disabled={!this.state.isSubmitBtnActive}>{gettext('Submit')}</Button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{this.state.apiTokenList.length !== 0 &&
|
||||
<div className='o-auto' style={{height: 'calc(100% - 91px)'}}>
|
||||
<div className="h-100" style={{maxHeight: '18rem'}}>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="22%">{gettext('App Name')}</th>
|
||||
<th width="15%">{gettext('Permission')}</th>
|
||||
<th width="53%">{gettext('Access Token')}</th>
|
||||
<th width="5%"></th>
|
||||
<th width="5%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{renderAPITokenList}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
{this.state.loading &&
|
||||
<Loading/>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
let currentTable = this.props.currentTable;
|
||||
let name = currentTable.name;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={true} className="share-dialog" style={{maxWidth: '720px'}}
|
||||
toggle={this.props.onTableAPITokenToggle}
|
||||
>
|
||||
<ModalHeader toggle={this.props.onTableAPITokenToggle}>
|
||||
{gettext('API Token')} <span className="op-target" title={name}>{name}</span></ModalHeader>
|
||||
<ModalBody className="share-dialog-content">
|
||||
{this.renderContent()}
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TableAPITokenDialog.propTypes = propTypes;
|
||||
|
||||
export default TableAPITokenDialog;
|
@@ -1,81 +0,0 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Select from 'react-select';
|
||||
import { gettext } from '../../utils/constants';
|
||||
|
||||
const propTypes = {
|
||||
isTextMode: PropTypes.bool.isRequired,
|
||||
isEditIconShow: PropTypes.bool.isRequired,
|
||||
currentPermission: PropTypes.string.isRequired,
|
||||
onPermissionChanged: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DtableSharePermissionEditor extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isEditing: false,
|
||||
};
|
||||
this.options = [
|
||||
{ value: 'rw', label: <div>{gettext('Read-Write')}</div> },
|
||||
{ value: 'r', label: <div>{gettext('Read-Only')}</div> }
|
||||
];
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
document.addEventListener('click', this.onHideSelect);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('click', this.onHideSelect);
|
||||
}
|
||||
|
||||
onHideSelect = () => {
|
||||
this.setState({ isEditing: false });
|
||||
}
|
||||
|
||||
onEditPermission = (e) => {
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
this.setState({ isEditing: true });
|
||||
}
|
||||
|
||||
onPermissionChanged = (e) => {
|
||||
if (e.value !== this.props.currentPermission) {
|
||||
this.props.onPermissionChanged(e.value);
|
||||
}
|
||||
this.setState({ isEditing: false });
|
||||
}
|
||||
|
||||
onSelectHandler = (e) => {
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { currentPermission, isTextMode } = this.props;
|
||||
let optionTranslation = currentPermission === 'r' ? gettext('Read-Only') : gettext('Read-Write');
|
||||
return (
|
||||
<div onClick={this.onSelectHandler}>
|
||||
{(isTextMode && !this.state.isEditing) ?
|
||||
<Fragment>
|
||||
<span>{optionTranslation}</span>
|
||||
{this.props.isEditIconShow &&
|
||||
<span title={gettext('Edit')} className="fa fa-pencil-alt attr-action-icon" onClick={this.onEditPermission}></span>
|
||||
}
|
||||
</Fragment>
|
||||
:
|
||||
<Select
|
||||
options={this.options}
|
||||
placeholder={optionTranslation}
|
||||
onChange={this.onPermissionChanged}
|
||||
captureMenuScroll={false}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DtableSharePermissionEditor.propTypes = propTypes;
|
||||
|
||||
export default DtableSharePermissionEditor;
|
@@ -1,42 +0,0 @@
|
||||
import i18n from 'i18next';
|
||||
import Backend from 'i18next-xhr-backend';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
let mediaUrl = window.app.pageOptions.mediaUrl;
|
||||
const lang = window.app.pageOptions.lang;
|
||||
|
||||
i18n
|
||||
.use(Backend)
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
lng: lang,
|
||||
fallbackLng: 'en',
|
||||
ns: ['dtable', 'translations'],
|
||||
defaultNS: 'dtable',
|
||||
|
||||
whitelist: ['en', 'zh-CN', 'fr', 'de', 'cs', 'es', 'es-AR', 'es-MX', 'ru'],
|
||||
|
||||
backend: {
|
||||
loadPath: mediaUrl + 'assets/frontend/locales/{{ lng }}/{{ ns }}.json',
|
||||
// loadPath: '/media/locales/{{lng}}/{{ns}}.json',
|
||||
// loadPath: function(lng, ns) {
|
||||
},
|
||||
|
||||
debug: true, // console log if debug: true
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react!!
|
||||
},
|
||||
contextSeparator: " ",
|
||||
|
||||
|
||||
load: 'currentOnly',
|
||||
|
||||
react: {
|
||||
wait: true,
|
||||
}
|
||||
});
|
||||
|
||||
export default i18n;
|
@@ -1,16 +0,0 @@
|
||||
class DTableShareLink {
|
||||
|
||||
constructor(object) {
|
||||
this.workspaceID = object.workspace_id;
|
||||
this.permissions = object.permission;
|
||||
this.username = object.username;
|
||||
this.is_expired = object.is_expired;
|
||||
this.expire_date = object.expire_date;
|
||||
this.token = object.token;
|
||||
this.link = object.link;
|
||||
this.ctime = object.ctime;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default DTableShareLink;
|
@@ -627,23 +627,6 @@ export const Utils = {
|
||||
};
|
||||
},
|
||||
|
||||
getDTableShareLinkPermissionObject: function(permission) {
|
||||
switch (permission) {
|
||||
case 'read-only':
|
||||
return {
|
||||
value: permission,
|
||||
text: 'read-only',
|
||||
permission: 'r'
|
||||
};
|
||||
case 'read-write':
|
||||
return {
|
||||
value: permission,
|
||||
text: 'read-write',
|
||||
permission: 'rw'
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
formatSize: function(options) {
|
||||
/*
|
||||
* param: {bytes, precision}
|
||||
|
Reference in New Issue
Block a user