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, shareLinkPasswordMinLength } from '../../utils/constants'; import { seafileAPI } from '../../utils/seafile-api'; import { Utils } from '../../utils/utils'; import SharedLinkInfo from '../../models/shared-link-info'; import toaster from '../toast'; import Loading from '../loading'; const propTypes = { itemPath: PropTypes.string.isRequired, repoID: PropTypes.string.isRequired, closeShareDialog: PropTypes.func.isRequired, }; class GenerateShareLink extends React.Component { constructor(props) { super(props); this.state = { isValidate: false, isShowPasswordInput: false, isPasswordVisible: false, isExpireChecked: false, password: '', passwdnew: '', expireDays: '', errorInfo: '', sharedLinkInfo: null, isNoticeMessageShow: false, isLoading: true, isShowSendLink: false, sendLinkEmails: '', sendLinkMessage: '', sendLinkErrorMessage: '', }; this.permissions = { 'can_edit': false, 'can_download': true }; this.isExpireDaysNoLimit = (parseInt(shareLinkExpireDaysMin) === 0 && parseInt(shareLinkExpireDaysMax) === 0); } componentDidMount() { let path = this.props.itemPath; let repoID = this.props.repoID; seafileAPI.getShareLink(repoID, path).then((res) => { if (res.data.length !== 0) { let sharedLinkInfo = new SharedLinkInfo(res.data[0]); this.setState({ isLoading: false, sharedLinkInfo: sharedLinkInfo }); } else { this.setState({isLoading: false}); } }); } 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}); } setPermission = (permission) => { if (permission == 'previewAndDownload') { this.permissions = { 'can_edit': false, 'can_download': true }; } else { this.permissions = { 'can_edit': false, 'can_download': false }; } } generateShareLink = () => { let isValid = this.validateParamsInput(); if (isValid) { this.setState({errorInfo: ''}); let { itemPath, repoID } = this.props; let { password, expireDays } = this.state; let permissions = this.permissions; permissions = JSON.stringify(permissions); seafileAPI.createShareLink(repoID, itemPath, password, expireDays, permissions).then((res) => { let sharedLinkInfo = new SharedLinkInfo(res.data); this.setState({sharedLinkInfo: sharedLinkInfo}); }); } } onCopySharedLink = () => { let sharedLink = this.state.sharedLinkInfo.link; copy(sharedLink); toaster.success(gettext('Share link is copied to the clipboard.')); this.props.closeShareDialog(); } onCopyDownloadLink = () => { let downloadLink = this.state.sharedLinkInfo.link + '?dl'; copy(downloadLink); toaster.success(gettext('Direct download link is copied to the clipboard.')); this.props.closeShareDialog(); } deleteShareLink = () => { let sharedLinkInfo = this.state.sharedLinkInfo; seafileAPI.deleteShareLink(sharedLinkInfo.token).then(() => { this.setState({ password: '', passwordnew: '', isShowPasswordInput: false, expireDays: '', isExpireChecked: false, errorInfo: '', sharedLinkInfo: null, isNoticeMessageShow: false, }); this.permissions = { 'can_edit': false, 'can_download': true }; }); } onExpireChecked = (e) => { this.setState({isExpireChecked: e.target.checked}); } onExpireDaysChanged = (e) => { let day = e.target.value.trim(); this.setState({expireDays: day}); } 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; } let flag = reg.test(expireDays); if (!flag) { 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; } let flag = reg.test(expireDays); if (!flag) { 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}); } onSendLinkEmailsChange = (event) => { if (this.state.sendLinkErrorMessage) this.setState({ sendLinkErrorMessage: '' }); this.setState({sendLinkEmails: event.target.value}); } onSendLinkMessageChange = (event) => { if (this.state.sendLinkErrorMessage) this.setState({ sendLinkErrorMessage: '' }); this.setState({sendLinkMessage: event.target.value}); } toggleSendLink = () => { this.setState({ isShowSendLink: !this.state.isShowSendLink }); } sendShareLink = () => { if (!this.state.sendLinkEmails) return; const token = this.state.sharedLinkInfo.token; const emails = this.state.sendLinkEmails.replace(/\s*/g,''); const message = this.state.sendLinkMessage.trim(); this.setState({ isLoading: true }); seafileAPI.sendShareLink(token, emails, message).then((res) => { this.props.closeShareDialog(); if (res.data.failed.length > 0) { res.data.failed.map(failed => { toaster.warning(gettext('Failed sent link to') + ' ' + failed.email + ', ' + failed.error_msg); }); } if (res.data.success.length > 0) { let users = res.data.success.join(','); toaster.success(gettext('Successfully sent link to') + ' ' + users); } }).catch((error) => { if (error.response) { this.setState({ sendLinkErrorMessage: error.response.data.error_msg, isLoading: false, }); } }); } render() { if (this.state.isLoading) { return ; } let passwordLengthTip = gettext('(at least {passwordLength} characters)'); passwordLengthTip = passwordLengthTip.replace('{passwordLength}', shareLinkPasswordMinLength); if (this.state.sharedLinkInfo) { let sharedLinkInfo = this.state.sharedLinkInfo; return (
{gettext('Link:')}
{sharedLinkInfo.link}{' '} {sharedLinkInfo.is_expired ? ({gettext('Expired')}) : }
{!sharedLinkInfo.is_dir && ( //just for file
{gettext('Direct Download Link:')}
{sharedLinkInfo.link}?dl=1{' '} {sharedLinkInfo.is_expired ? ({gettext('Expired')}) : }
)} {sharedLinkInfo.expire_date && (
{gettext('Expiration Date:')}
{moment(sharedLinkInfo.expire_date).format('YYYY-MM-DD hh:mm:ss')}
)}
{!this.state.isShowSendLink ? :

{this.state.sendLinkErrorMessage &&

{this.state.sendLinkErrorMessage}

} {' '} {' '}
} {(!this.state.isShowSendLink && !this.state.isNoticeMessageShow) && } {this.state.isNoticeMessageShow &&

{gettext('Are you sure you want to delete the share link?')}

{gettext('If the share link is deleted, no one will be able to access it any more.')}

{' '}
}
); } else { return (
{this.state.isShowPasswordInput && {/* todo translate */} {' '}{passwordLengthTip} } {this.isExpireDaysNoLimit && ( )} {this.state.isExpireChecked && } {!this.isExpireDaysNoLimit && ( )} {this.state.errorInfo && {gettext(this.state.errorInfo)}}
); } } } GenerateShareLink.propTypes = propTypes; export default GenerateShareLink;