Gen and copy share link from frontend

This commit is contained in:
Tom Moor
2018-05-16 23:07:33 -07:00
parent 500d039856
commit 4266020315
8 changed files with 94 additions and 6 deletions

View File

@ -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> {

View File

@ -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>

View File

@ -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;

View File

@ -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}

View File

@ -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;

View 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;

View File

@ -0,0 +1,3 @@
// @flow
import DocumentShare from './DocumentShare';
export default DocumentShare;

View File

@ -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,
}; };