mirror of
https://github.com/dnote/dnote
synced 2026-03-18 00:09:56 +01:00
* Implement lint in all js projects * Use yarn workspace * Remove package-lock.json * Fix * Extract common dev dep * Bump
200 lines
5.2 KiB
TypeScript
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;
|