Gen and copy share link from frontend
This commit is contained in:
@ -5,8 +5,8 @@ import copy from 'copy-to-clipboard';
|
|||||||
type Props = {
|
type Props = {
|
||||||
text: string,
|
text: string,
|
||||||
children?: React.Node,
|
children?: React.Node,
|
||||||
onClick?: () => void,
|
onClick?: () => *,
|
||||||
onCopy: () => void,
|
onCopy: () => *,
|
||||||
};
|
};
|
||||||
|
|
||||||
class CopyToClipboard extends React.PureComponent<Props> {
|
class CopyToClipboard extends React.PureComponent<Props> {
|
||||||
|
@ -7,6 +7,7 @@ import CollectionNew from 'scenes/CollectionNew';
|
|||||||
import CollectionEdit from 'scenes/CollectionEdit';
|
import CollectionEdit from 'scenes/CollectionEdit';
|
||||||
import CollectionDelete from 'scenes/CollectionDelete';
|
import CollectionDelete from 'scenes/CollectionDelete';
|
||||||
import DocumentDelete from 'scenes/DocumentDelete';
|
import DocumentDelete from 'scenes/DocumentDelete';
|
||||||
|
import DocumentShare from 'scenes/DocumentShare';
|
||||||
import KeyboardShortcuts from 'scenes/KeyboardShortcuts';
|
import KeyboardShortcuts from 'scenes/KeyboardShortcuts';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -44,6 +45,9 @@ class Modals extends React.Component<Props> {
|
|||||||
<Modal name="collection-delete" title="Delete collection">
|
<Modal name="collection-delete" title="Delete collection">
|
||||||
<CollectionDelete onSubmit={this.handleClose} />
|
<CollectionDelete onSubmit={this.handleClose} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
<Modal name="document-share" title="Share document">
|
||||||
|
<DocumentShare onSubmit={this.handleClose} />
|
||||||
|
</Modal>
|
||||||
<Modal name="document-delete" title="Delete document">
|
<Modal name="document-delete" title="Delete document">
|
||||||
<DocumentDelete onSubmit={this.handleClose} />
|
<DocumentDelete onSubmit={this.handleClose} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -31,10 +31,6 @@ class MainSidebar extends React.Component<Props> {
|
|||||||
this.props.ui.setActiveModal('collection-new');
|
this.props.ui.setActiveModal('collection-new');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleEditCollection = () => {
|
|
||||||
this.props.ui.setActiveModal('collection-edit');
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { auth, documents } = this.props;
|
const { auth, documents } = this.props;
|
||||||
const { user, team } = auth;
|
const { user, team } = auth;
|
||||||
|
@ -56,6 +56,13 @@ class DocumentMenu extends React.Component<Props> {
|
|||||||
this.props.document.download();
|
this.props.document.download();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleShareLink = async (ev: SyntheticEvent<*>) => {
|
||||||
|
const { document } = this.props;
|
||||||
|
if (!document.shareUrl) await document.share();
|
||||||
|
|
||||||
|
this.props.ui.setActiveModal('document-share', { document });
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { document, label, className, showPrint } = this.props;
|
const { document, label, className, showPrint } = this.props;
|
||||||
const isDraft = !document.publishedAt;
|
const isDraft = !document.publishedAt;
|
||||||
@ -80,6 +87,12 @@ class DocumentMenu extends React.Component<Props> {
|
|||||||
Star
|
Star
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={this.handleShareLink}
|
||||||
|
title="Create a public share link"
|
||||||
|
>
|
||||||
|
Share link
|
||||||
|
</DropdownMenuItem>
|
||||||
<hr />
|
<hr />
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={this.handleNewChild}
|
onClick={this.handleNewChild}
|
||||||
|
@ -40,6 +40,7 @@ class Document extends BaseModel {
|
|||||||
parentDocument: ?string;
|
parentDocument: ?string;
|
||||||
publishedAt: ?string;
|
publishedAt: ?string;
|
||||||
url: string;
|
url: string;
|
||||||
|
shareUrl: ?string;
|
||||||
views: number;
|
views: number;
|
||||||
revision: number;
|
revision: number;
|
||||||
|
|
||||||
@ -101,6 +102,18 @@ class Document extends BaseModel {
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
|
@action
|
||||||
|
share = async () => {
|
||||||
|
try {
|
||||||
|
const res = await client.post('/shares.create', { id: this.id });
|
||||||
|
invariant(res && res.data, 'Document API response should be available');
|
||||||
|
|
||||||
|
this.shareUrl = res.data.url;
|
||||||
|
} catch (e) {
|
||||||
|
this.errors.add('Document failed to share');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@action
|
@action
|
||||||
pin = async () => {
|
pin = async () => {
|
||||||
this.pinned = true;
|
this.pinned = true;
|
||||||
|
58
app/scenes/DocumentShare/DocumentShare.js
Normal file
58
app/scenes/DocumentShare/DocumentShare.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// @flow
|
||||||
|
import * as React from 'react';
|
||||||
|
import { observable } from 'mobx';
|
||||||
|
import { observer } from 'mobx-react';
|
||||||
|
import Input from 'components/Input';
|
||||||
|
import Button from 'components/Button';
|
||||||
|
import CopyToClipboard from 'components/CopyToClipboard';
|
||||||
|
import HelpText from 'components/HelpText';
|
||||||
|
import Document from 'models/Document';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
document: Document,
|
||||||
|
};
|
||||||
|
|
||||||
|
@observer
|
||||||
|
class DocumentShare extends React.Component<Props> {
|
||||||
|
@observable isCopied: boolean;
|
||||||
|
timeout: TimeoutID;
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCopied = () => {
|
||||||
|
this.isCopied = true;
|
||||||
|
this.timeout = setTimeout(() => (this.isCopied = false), 3000);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { document } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<HelpText>
|
||||||
|
The link below allows anyone to access a read-only version of the
|
||||||
|
document <strong>{document.title}</strong>. You can revoke this link
|
||||||
|
at any point in the future.
|
||||||
|
</HelpText>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
label="Share link"
|
||||||
|
value={document.shareUrl || 'Loading…'}
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
<CopyToClipboard
|
||||||
|
text={document.shareUrl || ''}
|
||||||
|
onCopy={this.handleCopied}
|
||||||
|
>
|
||||||
|
<Button type="submit" disabled={this.isCopied} primary>
|
||||||
|
{this.isCopied ? 'Copied!' : 'Copy Link'}
|
||||||
|
</Button>
|
||||||
|
</CopyToClipboard>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DocumentShare;
|
3
app/scenes/DocumentShare/index.js
Normal file
3
app/scenes/DocumentShare/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// @flow
|
||||||
|
import DocumentShare from './DocumentShare';
|
||||||
|
export default DocumentShare;
|
@ -7,6 +7,7 @@ function present(ctx: Object, share: Share) {
|
|||||||
id: share.id,
|
id: share.id,
|
||||||
user: presentUser(ctx, share.user),
|
user: presentUser(ctx, share.user),
|
||||||
documentTitle: share.document.title,
|
documentTitle: share.document.title,
|
||||||
|
url: `${process.env.URL}/share/${share.id}`,
|
||||||
createdAt: share.createdAt,
|
createdAt: share.createdAt,
|
||||||
updatedAt: share.updatedAt,
|
updatedAt: share.updatedAt,
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user