dnote/web/src/components/Note/ShareModal/index.tsx
Sung Won Cho e2e777db54
Lint JavaScript/TypeScript code (#346)
* Implement lint in all js projects

* Use yarn workspace

* Remove package-lock.json

* Fix

* Extract common dev dep

* Bump
2019-11-23 15:40:33 +08:00

200 lines
5.2 KiB
TypeScript

/* Copyright (C) 2019 Monomax Software Pty Ltd
*
* This file is part of Dnote.
*
* Dnote is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dnote is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Dnote. If not, see <https://www.gnu.org/licenses/>.
*/
import classnames from 'classnames';
import { NoteData } from 'jslib/operations/types';
import React, { useState } from 'react';
import { copyToClipboard, selectTextInputValue } from 'web/libs/dom';
import operations from 'web/libs/operations';
import { getNotePath } from 'web/libs/paths';
import { useDispatch } from '../../../store';
import { receiveNote } from '../../../store/note';
import Button from '../../Common/Button';
import Flash from '../../Common/Flash';
import Modal, { Body, Header } from '../../Common/Modal';
import Toggle from '../../Common/Toggle';
import CopyButton from './CopyButton';
import styles from './ShareModal.scss';
// getNoteURL returns the absolute URL for the note
function getNoteURL(uuid: string): string {
const loc = getNotePath(uuid);
const path = loc.pathname;
// TODO: maybe get these values from the configuration instead of parsing
// current URL.
const { protocol, host } = window.location;
return `${protocol}//${host}${path}`;
}
function getHelpText(isPublic: boolean): string {
if (isPublic) {
return 'Anyone with this URL can view this note.';
}
return 'This note is private only to you.';
}
interface Props {
isOpen: boolean;
onDismiss: () => void;
note: NoteData;
}
const ShareModal: React.FunctionComponent<Props> = ({
isOpen,
onDismiss,
note
}) => {
const [inProgress, setInProgress] = useState(false);
const [errMessage, setErrMessage] = useState('');
const [copyHot, setCopyHot] = useState(false);
const dispatch = useDispatch();
const labelId = 'share-note-modal-label';
const linkValue = getNoteURL(note.uuid);
function handleToggle(val: boolean) {
setInProgress(true);
operations.notes
.update(note.uuid, { public: val })
.then(resp => {
dispatch(receiveNote(resp));
setInProgress(false);
})
.catch(err => {
console.log('Error sharing note', err);
setInProgress(false);
setErrMessage(err.message);
});
}
function handleCopy() {
copyToClipboard(linkValue);
setCopyHot(true);
window.setTimeout(() => {
setCopyHot(false);
}, 1200);
}
return (
<Modal
modalId="T-share-note-modal"
isOpen={isOpen}
onDismiss={onDismiss}
ariaLabelledBy={labelId}
size="regular"
>
<Header
labelId={labelId}
heading="Share this note"
onDismiss={onDismiss}
/>
<Flash
kind="danger"
onDismiss={() => {
setErrMessage('');
}}
hasBorder={false}
when={Boolean(errMessage)}
noMargin
>
{errMessage}
</Flash>
<Body>
<div className={styles['label-row']}>
<label htmlFor="link-value" className={styles.label}>
Link sharing
</label>
<Toggle
id="T-note-public-toggle"
checked={note.public}
onChange={handleToggle}
disabled={inProgress}
label={
<span className={styles.status}>
{note.public ? 'Enabled' : 'Disabled'}
</span>
}
/>
</div>
<input
id="link-value"
type="text"
disabled={!note.public}
value={linkValue}
onChange={e => {
e.preventDefault();
}}
className={classnames(
'form-control text-input text-input-small',
styles['link-input']
)}
onFocus={e => {
const el = e.target;
selectTextInputValue(el);
}}
onKeyDown={e => {
e.preventDefault();
}}
onMouseUp={e => {
e.preventDefault();
const el = e.target as HTMLInputElement;
selectTextInputValue(el);
}}
/>
<p className={styles.help}>{getHelpText(note.public)} </p>
<div className={styles.actions}>
{note.public && (
<CopyButton
kind="third"
size="normal"
onClick={handleCopy}
isHot={copyHot}
className={classnames('button-normal button-second', styles.copy)}
/>
)}
<Button
id="T-share-note-modal-close"
type="button"
size="normal"
kind="second"
onClick={onDismiss}
disabled={inProgress}
>
Cancel
</Button>
</div>
</Body>
</Modal>
);
};
export default ShareModal;