This repository has been archived on 2022-08-14. You can view files and clone it, but cannot push or open issues or pull requests.
2016-07-24 15:32:31 -07:00

160 lines
4.1 KiB
JavaScript

import React from 'react';
import { observer } from 'mobx-react';
import Codemirror from 'react-codemirror';
import 'codemirror/mode/gfm/gfm';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/addon/edit/continuelist';
import 'codemirror/addon/display/placeholder.js';
import Dropzone from 'react-dropzone';
import ClickablePadding from './components/ClickablePadding';
import styles from './MarkdownEditor.scss';
import './codemirror.scss';
import { client } from 'utils/ApiClient';
@observer
class MarkdownEditor extends React.Component {
static propTypes = {
text: React.PropTypes.string,
onChange: React.PropTypes.func.isRequired,
replaceText: React.PropTypes.func.isRequired,
onSave: React.PropTypes.func.isRequired,
// This is actually not used but it triggers
// re-render to help with CodeMirror focus issues
preview: React.PropTypes.bool,
}
getEditorInstance = () => {
return this.refs.editor.getCodeMirror();
}
onChange = (newText) => {
if (newText !== this.props.text) {
this.props.onChange(newText);
}
}
onDropAccepted = (files) => {
const file = files[0];
const editor = this.getEditorInstance();
const cursorPosition = editor.getCursor();
const insertOnNewLine = cursorPosition.ch !== 0;
let newCursorPositionLine;
// Lets set up the upload text
const pendingUploadTag = `![${file.name}](Uploading...)`;
if (insertOnNewLine) {
editor.replaceSelection('\n' + pendingUploadTag + '\n');
newCursorPositionLine = cursorPosition.line + 3;
} else {
editor.replaceSelection(pendingUploadTag + '\n');
newCursorPositionLine = cursorPosition.line + 2;
}
editor.setCursor(newCursorPositionLine, 0);
client.post('/user.s3Upload', {
kind: file.type,
size: file.size,
filename: file.name,
})
.then(response => {
const data = response.data;
// Upload using FormData API
let formData = new FormData();
for (let key in data.form) {
formData.append(key, data.form[key]);
}
if (file.blob) {
formData.append('file', file.file);
} else {
formData.append('file', file);
}
fetch(data.upload_url, {
method: 'post',
body: formData
})
.then(s3Response => {
this.props.replaceText({
original: pendingUploadTag,
new: `![${file.name}](${data.asset.url})`
});
editor.setCursor(newCursorPositionLine, 0);
})
.catch(err => {
this.props.replaceText({
original: pendingUploadTag,
new: '',
});
editor.setCursor(newCursorPositionLine, 0);
});
});
}
onPaddingTopClick = () => {
const cm = this.getEditorInstance();
cm.setCursor(0, 0);
cm.focus();
}
onPaddingBottomClick = () => {
const cm = this.getEditorInstance();
cm.setCursor(cm.lineCount(), 0);
cm.focus();
}
render = () => {
const options = {
readOnly: false,
lineNumbers: false,
mode: 'gfm',
matchBrackets: true,
lineWrapping: true,
viewportMargin: Infinity,
scrollbarStyle: 'null',
theme: 'atlas',
extraKeys: {
Enter: 'newlineAndIndentContinueMarkdownList',
"Ctrl-Enter": this.props.onSave,
"Cmd-Enter": this.props.onSave,
"Cmd-Esc": this.props.onCancel,
"Ctrl-Esc": this.props.onCancel,
// "Cmd-Shift-p": this.props.togglePreview,
// "Ctrl-Shift-p": this.props.togglePreview,
},
placeholder: "# Start with a title...",
};
return (
<Dropzone
onDropAccepted={this.onDropAccepted}
disableClick={true}
multiple={false}
accept={'image/*'}
className={styles.container}
>
<ClickablePadding onClick={ this.onPaddingTopClick } />
<Codemirror
value={this.props.text}
onChange={this.onChange}
options={options}
ref="editor"
className={styles.codeMirrorContainer}
/>
<ClickablePadding onClick={ this.onPaddingBottomClick } />
</Dropzone>
);
}
}
export default MarkdownEditor;