1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-17 14:37:58 +00:00

Share dialog improve (#2760)

This commit is contained in:
杨顺强 2019-01-04 18:11:13 +08:00 committed by Daniel Pan
parent cd82bf2b67
commit 91c9ac8e80
6 changed files with 122 additions and 44 deletions

View File

@ -180,7 +180,7 @@
"dependencies": { "dependencies": {
"reactstrap": { "reactstrap": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "http://registry.npmjs.org/reactstrap/-/reactstrap-5.0.0.tgz", "resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-5.0.0.tgz",
"integrity": "sha512-y0eju/LAK7gbEaTFfq2iW92MF7/5Qh0tc1LgYr2mg92IX8NodGc03a+I+cp7bJ0VXHAiLy0bFL9UP89oSm4cBg==", "integrity": "sha512-y0eju/LAK7gbEaTFfq2iW92MF7/5Qh0tc1LgYr2mg92IX8NodGc03a+I+cp7bJ0VXHAiLy0bFL9UP89oSm4cBg==",
"requires": { "requires": {
"classnames": "^2.2.3", "classnames": "^2.2.3",
@ -640,7 +640,7 @@
}, },
"axios": { "axios": {
"version": "0.18.0", "version": "0.18.0",
"resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
"requires": { "requires": {
"follow-redirects": "^1.3.0", "follow-redirects": "^1.3.0",
@ -2717,6 +2717,14 @@
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
"dev": true "dev": true
}, },
"copy-to-clipboard": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz",
"integrity": "sha512-c3GdeY8qxCHGezVb1EFQfHYK/8NZRemgcTIzPq7PuxjHAf/raKibn2QdhHPb/y6q74PMgH6yizaDZlRmw6QyKw==",
"requires": {
"toggle-selection": "^1.0.3"
}
},
"core-js": { "core-js": {
"version": "1.2.7", "version": "1.2.7",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
@ -9964,7 +9972,7 @@
}, },
"react-popper": { "react-popper": {
"version": "0.8.3", "version": "0.8.3",
"resolved": "http://registry.npmjs.org/react-popper/-/react-popper-0.8.3.tgz", "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-0.8.3.tgz",
"integrity": "sha1-D3MzMTfJ+wr27EB00tBYWgoEYeE=", "integrity": "sha1-D3MzMTfJ+wr27EB00tBYWgoEYeE=",
"requires": { "requires": {
"popper.js": "^1.12.9", "popper.js": "^1.12.9",

View File

@ -9,6 +9,7 @@
"MD5": "^1.3.0", "MD5": "^1.3.0",
"autoprefixer": "7.1.6", "autoprefixer": "7.1.6",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"copy-to-clipboard": "^3.0.8",
"css-loader": "0.28.7", "css-loader": "0.28.7",
"dotenv": "4.0.0", "dotenv": "4.0.0",
"dotenv-expand": "4.2.0", "dotenv-expand": "4.2.0",

View File

@ -1,8 +1,12 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import moment from 'moment';
import copy from 'copy-to-clipboard';
import { Button, Form, FormGroup, Label, Input, InputGroup, InputGroupAddon } from 'reactstrap';
import { gettext, shareLinkExpireDaysMin, shareLinkExpireDaysMax } from '../../utils/constants'; import { gettext, shareLinkExpireDaysMin, shareLinkExpireDaysMax } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { Button, Form, FormGroup, Label, Input, InputGroup, InputGroupAddon } from 'reactstrap'; import SharedLinkInfo from '../../models/shared-link-info';
import toaster from '../toast';
const propTypes = { const propTypes = {
itemPath: PropTypes.string.isRequired, itemPath: PropTypes.string.isRequired,
@ -21,9 +25,9 @@ class GenerateShareLink extends React.Component {
password: '', password: '',
passwdnew: '', passwdnew: '',
expireDays: '', expireDays: '',
token: '', errorInfo: '',
link: '', sharedLinkInfo: null,
errorInfo: '' isNoticeMessageShow: false,
}; };
this.permissions = { this.permissions = {
'can_edit': false, 'can_edit': false,
@ -41,10 +45,8 @@ class GenerateShareLink extends React.Component {
let repoID = this.props.repoID; let repoID = this.props.repoID;
seafileAPI.getShareLink(repoID, path).then((res) => { seafileAPI.getShareLink(repoID, path).then((res) => {
if (res.data.length !== 0) { if (res.data.length !== 0) {
this.setState({ let sharedLinkInfo = new SharedLinkInfo(res.data[0]);
link: res.data[0].link, this.setState({sharedLinkInfo: sharedLinkInfo});
token: res.data[0].token,
});
} }
}); });
} }
@ -105,25 +107,36 @@ class GenerateShareLink extends React.Component {
let permissions = this.permissions; let permissions = this.permissions;
permissions = JSON.stringify(permissions); permissions = JSON.stringify(permissions);
seafileAPI.createShareLink(repoID, itemPath, password, expireDays, permissions).then((res) => { seafileAPI.createShareLink(repoID, itemPath, password, expireDays, permissions).then((res) => {
this.setState({ let sharedLinkInfo = new SharedLinkInfo(res.data);
link: res.data.link, this.setState({sharedLinkInfo: sharedLinkInfo});
token: res.data.token
});
}); });
} }
} }
onCopySharedLink = () => {
let sharedLink = this.state.sharedLinkInfo.link;
copy(sharedLink);
toaster.success(gettext('Share link is copied to the clipboard.'));
}
onCopyDownloadLink = () => {
let downloadLink = this.state.sharedLinkInfo.link + '?dl';
copy(downloadLink);
toaster.success(gettext('Direct download link is copied to the clipboard.'));
}
deleteShareLink = () => { deleteShareLink = () => {
seafileAPI.deleteShareLink(this.state.token).then(() => { let sharedLinkInfo = this.state.sharedLinkInfo;
seafileAPI.deleteShareLink(sharedLinkInfo.token).then(() => {
this.setState({ this.setState({
link: '',
token: '',
password: '', password: '',
passwordnew: '', passwordnew: '',
isShowPasswordInput: false, isShowPasswordInput: false,
expireDays: '', expireDays: '',
isExpireChecked: false, isExpireChecked: false,
errorInfo: '', errorInfo: '',
sharedLinkInfo: null,
isNoticeMessageShow: false,
}); });
this.permissions = { this.permissions = {
'can_edit': false, 'can_edit': false,
@ -216,13 +229,55 @@ class GenerateShareLink extends React.Component {
return true; return true;
} }
onNoticeMessageToggle = () => {
this.setState({isNoticeMessageShow: !this.state.isNoticeMessageShow});
}
render() { render() {
if (this.state.link) { if (this.state.sharedLinkInfo) {
let sharedLinkInfo = this.state.sharedLinkInfo;
return ( return (
<Form> <div>
<p>{this.state.link}</p> <Form className="mb-4">
<Button onClick={this.deleteShareLink}>{gettext('Delete')}</Button> <FormGroup className="mb-0">
</Form> <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}></span>
}
</dd>
</FormGroup>
{!sharedLinkInfo.is_dir && ( //just for file
<FormGroup className="mb-0">
<dt className="text-secondary font-weight-normal">{gettext('Direct Download Link:')}</dt>
<dd className="d-flex">
<span>{sharedLinkInfo.link}?dl</span>{' '}
{sharedLinkInfo.is_expired ?
<span className="err-message">({gettext('Expired')})</span> :
<span className="far fa-copy action-icon" onClick={this.onCopyDownloadLink}></span>
}
</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>
{!this.state.isNoticeMessageShow ?
<Button onClick={this.onNoticeMessageToggle}>{gettext('Delete')}</Button> :
<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 { } else {
return ( return (

View File

@ -1,8 +1,11 @@
import React from 'react'; import React from 'react';
import { gettext } from '../../utils/constants';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { seafileAPI } from '../../utils/seafile-api'; import copy from 'copy-to-clipboard';
import { Button, Form, FormGroup, FormText, Label, Input, InputGroup, InputGroupAddon } from 'reactstrap'; import { Button, Form, FormGroup, FormText, Label, Input, InputGroup, InputGroupAddon } from 'reactstrap';
import { gettext } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api';
import SharedUploadInfo from '../../models/shared-upload-info';
import toaster from '../toast';
const propTypes = { const propTypes = {
itemPath: PropTypes.string.isRequired, itemPath: PropTypes.string.isRequired,
@ -17,8 +20,7 @@ class GenerateUploadLink extends React.Component {
passwordVisible: false, passwordVisible: false,
password: '', password: '',
passwdnew: '', passwdnew: '',
link: '', sharedUploadInfo: null,
token:''
}; };
} }
@ -31,10 +33,8 @@ class GenerateUploadLink extends React.Component {
let repoID = this.props.repoID; let repoID = this.props.repoID;
seafileAPI.getUploadLinks(repoID, path).then((res) => { seafileAPI.getUploadLinks(repoID, path).then((res) => {
if (res.data.length !== 0) { if (res.data.length !== 0) {
this.setState({ let sharedUploadInfo = new SharedUploadInfo(res.data[0]);
link: res.data[0].link, this.setState({sharedUploadInfo: sharedUploadInfo});
token: res.data[0].token,
});
} }
}); });
} }
@ -94,33 +94,46 @@ class GenerateUploadLink extends React.Component {
}); });
} else { } else {
seafileAPI.createUploadLink(repoID, path, this.state.password).then((res) => { seafileAPI.createUploadLink(repoID, path, this.state.password).then((res) => {
this.setState({ let sharedUploadInfo = new SharedUploadInfo(res.data);
link: res.data.link, this.setState({sharedUploadInfo: sharedUploadInfo});
token: res.data.token
});
}); });
} }
} }
onCopyUploadLink = () => {
let uploadLink = this.state.sharedUploadInfo.link;
copy(uploadLink);
toaster.success(gettext('Upload link is copied to the clipboard.'));
}
deleteUploadLink = () => { deleteUploadLink = () => {
seafileAPI.deleteUploadLink(this.state.token).then(() => { let sharedUploadInfo = this.state.sharedUploadInfo
seafileAPI.deleteUploadLink(sharedUploadInfo.token).then(() => {
this.setState({ this.setState({
link: '',
token: '',
showPasswordInput: false, showPasswordInput: false,
password: '', password: '',
passwordnew: '', passwordnew: '',
sharedUploadInfo: null,
}); });
}); });
} }
render() { render() {
if (this.state.link) { if (this.state.sharedUploadInfo) {
let sharedUploadInfo = this.state.sharedUploadInfo;
return ( return (
<Form> <div>
<p>{this.state.link}</p> <Form className="mb-4">
<FormGroup>
<dt className="text-secondary font-weight-normal">{gettext('Upload Link:')}</dt>
<dd className="d-flex">
<span>{sharedUploadInfo.link}</span>
<span className="far fa-copy action-icon" onClick={this.onCopyUploadLink}></span>
</dd>
</FormGroup>
</Form>
<Button onClick={this.deleteUploadLink}>{gettext('Delete')}</Button> <Button onClick={this.deleteUploadLink}>{gettext('Delete')}</Button>
</Form> </div>
); );
} }
return ( return (

View File

@ -11,7 +11,7 @@ const wrapperClass = css({
left: 0, left: 0,
right: 0, right: 0,
position: 'fixed', position: 'fixed',
zIndex: 30 zIndex: 999999,
}); });

View File

@ -67,8 +67,9 @@
input.expire-input { input.expire-input {
display: inline-block; display: inline-block;
width: 5rem; width: 4rem;
height: 1.5rem; height: 1.5rem;
padding: 0.25rem 0.25rem;
margin: 0 0.25rem 0 1.25rem; margin: 0 0.25rem 0 1.25rem;
} }