Repository URL to install this package:
|
Version:
1.3.0 ▾
|
'use strict';
import React from 'react';
import moment from 'moment';
import Immutable from 'immutable';
import { default as cx } from 'classnames';
import { render } from 'react-dom';
import {
Entity,
EditorState,
CompositeDecorator,
DefaultDraftBlockRenderMap,
Modifier,
convertFromRaw,
convertToRaw } from 'draft-js';
import isSoftNewlineEvent from 'draft-js/lib/isSoftNewlineEvent';
import JSONPretty from 'react-json-pretty';
import RichTextEditor from './react-rte/src/RichTextEditor';
import EditorValue from './react-rte/src/lib/EditorValue';
import LinkDecorator from './react-rte/src/lib/LinkDecorator';
import InaudibleDecorator from './react-rte/src/lib/InaudibleDecorator';
import { stateToHTML } from 'draft-js-export-html';
const HTMLDiff = require('./HTMLDiff');
const decorator = new CompositeDecorator([LinkDecorator, InaudibleDecorator]);
//import { RichTextEditor, decorator } from './react-rte/src/RichTextEditor';
let toolbarConfig = require('./react-rte/src/lib/EditorToolbarConfig');
//toolbarConfig.INLINE_STYLE_BUTTONS.unshift({label: 'Inaudible', style: 'inaudible'});
//
//
import Media from './components/Media';
import TopsBlock from './components/TopsBlock';
import Tags from './components/Tags';
const extendedBlockRenderMap = DefaultDraftBlockRenderMap; //.merge(blockRenderMap);
import styles from './style/main.css';
const App = React.createClass({
getInitialState() {
return {
value: EditorValue.createEmpty(decorator),
diff: ''
}
},
componentWillMount() {
let editorState;
if(this.props.content && this.props.content !== null) {
const contentState = convertFromRaw(this.props.content);
editorState = EditorState.createWithContent(contentState, decorator);
if(this.props.originalContent && this.props.originalContent !== null) {
this.originalContent = convertFromRaw(this.props.originalContent);
} else this.originalContent = editorState.getCurrentContent();
} else {
editorState = EditorState.createEmpty(decorator);
}
this.props.onChange && this.props.onChange(editorState);
},
onChange(editorState) {
if(!this.props.readOnly) this.addTimestamp(editorState);
else this.props.onChange && this.props.onChange(editorState);
},
addTimestamp(editorState, replace) {
const content = editorState.getCurrentContent();
const selection = editorState.getSelection();
const blockKey = selection.getStartKey();
const block = content.getBlockForKey(blockKey);
const now = this.props.currentTime || 0;
const data = block.getData();
if(replace || (!data.get('timestamp') && data.get('timestamp') !== 0)) {
console.log('update');
const newContentState = Modifier.mergeBlockData(
content,
selection,
{timestamp: now}
);
const newEditorState = EditorState.push(editorState, newContentState, 'change-block-data');
const editorStateUpdate = EditorState.forceSelection(
newEditorState, newContentState.getSelectionAfter()
);
//value = RichTextEditor.EditorValue.createFromState(editorStateUpdate);
this.props.onChange && this.props.onChange(editorStateUpdate);
} else this.props.onChange && this.props.onChange(editorState);
},
setTimestamp() {
this.addTimestamp(this.props.editorState, true)
},
createImmutableEntity(text, _Entity) {
if(this.props.readOnly) return;
const editorState = this.props.editorState;
const content = editorState.getCurrentContent();
const selection = editorState.getSelection();
//@TODO: we need to only add extra space needs leading/trailing space
const newContentState = Modifier.replaceText(
content,
selection,
text,
undefined,
_Entity
);
const newEditorState = EditorState.push(editorState, newContentState, 'insert-fragment');
const editorStateUpdate = EditorState.forceSelection(
newEditorState, newContentState.getSelectionAfter()
);
this.props.onChange && this.props.onChange(editorStateUpdate);
},
inaudible(event) {
this.createImmutableEntity(
'[INAUDIBLE]',
Entity.create(
'TOKEN',
'IMMUTABLE',
{ type: 'inaudible', timestamp: this.props.currentTime || 0 }
)
);
},
crosstalk(event) {
this.createImmutableEntity(
'[CROSSTALK]',
Entity.create(
'TOKEN',
'IMMUTABLE',
{ type: 'crosstalk', timestamp: this.props.currentTime || 0 }
)
);
},
getRaw() {
const raw = convertToRaw(this.props.editorState.getCurrentContent());
return raw;
},
blockStyleFn(block) {
return;
},
blockRendererFn(block) {
const type = block.getType();
if(type === 'unstyled') {
return {
component: TopsBlock,
editable: !this.props.readOnly,
props: {
timestamp: block.getData().get('timestamp')
}
}
}
return '';
},
scribeKeyHandler(event) {
return this.props.scribeKeyHandler && this.props.scribeKeyHandler(event);
},
onAllClick(event) {
// Handle clicking on the tags
if(event.entity && this.props.setCurrentTime) {
this.props.setCurrentTime(event.entity.timestamp);
} else return;
},
componentWillReceiveProps(nextProps) {
if(nextProps.trackChanges && nextProps.editorState !== null) {
const currentContentObj = nextProps.editorState.getCurrentContent();
if(Immutable.is(currentContentObj, this.originalContent)) return;
const originalContent = stateToHTML(this.originalContent);
const rawCurrentContent = convertToRaw(currentContentObj);
const currentContent = stateToHTML(currentContentObj);
let diff = HTMLDiff(originalContent, currentContent);
const tagCheck = /\[INAUDIBLE\]|\[CROSSTALK\]/g;
let tags = [];
Object.keys(rawCurrentContent.entityMap).forEach( (key, index) => {
const entity = rawCurrentContent.entityMap[key];
if(!entity.data.type) return;
const value = entity.data.type.toUpperCase();
const className = styles[entity.data.type];
const element = `<span class="${className}" data-timestamp="${entity.data.timestamp}">${value}</span>`;
tags.push(element);
});
let iter = 0;
const delCheck = /\bdel\b/;
const newdiff = diff.replace(tagCheck, (match, index, source) => {
if(delCheck.test(source.substr(index-5, 5))) return match;
const element = tags[iter];
iter++;
return element;
});
this.setState({diff: newdiff});
}
},
render() {
let rte = null;
let edit = null;
if(this.props.editorState && this.props.editorState !== null) {
rte = (
<RichTextEditor
toolbarConfig={toolbarConfig}
currentTime={this.props.currentTime}
editorState={this.props.editorState}
placeholder={this.props.placeholder}
scribeKeys={this.props.scribeKeys}
scribeKeyHandler={this.scribeKeyHandler}
blockStyleFn={this.blockStyleFn}
blockRendererFn={this.blockRendererFn}
blockRenderMap={extendedBlockRenderMap}
readOnly={this.props.readOnly || false}
spellCheck={this.props.spellCheck || false}
setTimestamp={this.setTimestamp}
onChange={this.onChange} />
);
if(this.props.trackChanges && this.state.diff !== '') {
edit = (
<div className={styles['editor-split']}>
{rte}
<div className={styles['editor-diff-view']}
ref="diff"
dangerouslySetInnerHTML={{__html: this.state.diff}}
/>
</div>
);
} else edit = rte;
}
return (
<div onClick={this.onAllClick}>
<Tags inaudible={this.inaudible}
crosstalk={this.crosstalk}
setTimestamp={this.setTimestamp}
editorState={this.props.editorState}
/>
{edit}
</div>
);
}
});
export default App;