Home Reference Source

application/components/common/rich-editor/embed.js

  1. import React from 'react';
  2. import Codemirror from 'react-codemirror';
  3. require('codemirror/mode/htmlmixed/htmlmixed');
  4.  
  5. import FlatButton from 'material-ui/FlatButton';
  6. import TextField from 'material-ui/TextField';
  7.  
  8. import {Card, CardActions, CardHeader, CardMedia, CardTitle, CardText} from 'material-ui/Card';
  9.  
  10. import {AtomicBlockUtils, Entity} from 'draft-js';
  11.  
  12. import BaseView from './../../base-view';
  13.  
  14. /**
  15. * Embed component handles random embed data. Mostly javascript stuff
  16. * Includes CodeMirror editor for an extra bit of fancyness
  17. */
  18. class Embed extends BaseView {
  19.  
  20. constructor(props) {
  21. super(props);
  22. this.displayName = 'Embed';
  23.  
  24. this.getValue = this.getValue.bind(this);
  25. this.handleSave = this.handleSave.bind(this);
  26. this.handleCancel = this.handleCancel.bind(this);
  27. this.handleClick = this.handleClick.bind(this);
  28.  
  29. this.onChange = this.onChange.bind(this);
  30.  
  31. this.startEdit = this.startEdit.bind(this);
  32. this.finishEdit = this.finishEdit.bind(this);
  33.  
  34. this.state = {
  35. editMode: false,
  36. code: '',
  37. label: ''
  38. }
  39. }
  40.  
  41. /**
  42. * If there is no code value, start in edit mode.
  43. * @return {[type]} [description]
  44. */
  45. componentWillMount() {
  46.  
  47. const val = this.getValue();
  48. this.setState({code: val['content'], label: val['label']});
  49.  
  50. if (!this.getValue()) {
  51. this.setState({'editMode': true});
  52. this.startEdit();
  53. }
  54. }
  55.  
  56. onChange(code) {
  57. this.setState({code: code});
  58. }
  59. onLabelChange(e) {
  60. this.setState({label: e.target.value});
  61. }
  62.  
  63. /**
  64. * Return only the code string
  65. * @return {String}
  66. */
  67. getValue() {
  68. if (!this.props.block) {
  69. return '';
  70. }
  71. return this.props.contentState
  72. .getEntity(this.props.block.getEntityAt(0))
  73. .getData();
  74. }
  75.  
  76. startEdit() {
  77. if (!this.props.blockProps) {
  78. return;
  79. }
  80.  
  81. this.props.blockProps.onStartEdit(this.props.block.getKey());
  82. }
  83.  
  84. finishEdit() {
  85. if (!this.props.blockProps) {
  86. return;
  87. }
  88.  
  89. this.props.blockProps.onFinishEdit(this.props.block.getKey());
  90. }
  91.  
  92. /**
  93. * Handle start editmode on click
  94. */
  95. handleClick() {
  96. if (this.state.editMode) {
  97. return;
  98. }
  99.  
  100. this.setState({editMode: true}, () => { this.startEdit() });
  101. }
  102.  
  103. handleCancel() {
  104. this.setState({editMode: false}, () => { this.finishEdit() });
  105. }
  106.  
  107. handleSave() {
  108. const newContents = this.state.code
  109. .replace(/“/g, '"')
  110. .replace(/”/g, '"')
  111. .replace(/‘/g, '\'')
  112. .replace(/’/g, '\'');
  113. const newLabel = this.state.label;
  114.  
  115. const key = this.props.block.getEntityAt(0);
  116. this.props.contentState.mergeEntityData(key, {content: newContents, label: newLabel});
  117.  
  118. this.setState({editMode: false}, () => { this.finishEdit() });
  119. }
  120.  
  121. render() {
  122.  
  123. let contents;
  124. let className = 'RichEditor-embed RichEditor-pullQuote';
  125.  
  126. if (this.state.editMode) {
  127.  
  128. const cmOptions = {
  129. lineNumbers: true,
  130. mode: 'htmlmixed'
  131. };
  132. contents = (
  133. <Card>
  134. <CardHeader
  135. title="Embed Code"
  136. />
  137. <CardText>
  138. <Codemirror ref="content" value={this.state.code} onChange={this.onChange} options={cmOptions} />
  139.  
  140. </CardText>
  141. <CardActions>
  142. <FlatButton onClick={this.handleSave} label='Done' />
  143. <FlatButton onClick={this.handleCancel} label='Cancel' />
  144. </CardActions>
  145. </Card>
  146. );
  147.  
  148. className = className + ' active';
  149. } else {
  150. contents = (
  151. <Card>
  152. <CardHeader
  153. title="Embed Code"
  154. />
  155. <CardText>
  156. <div className="richEditor-embed-contentPreview">
  157. {this.getValue()['content'] ? this.getValue()['content'] : 'Click to edit...'}
  158. </div>
  159.  
  160. </CardText>
  161. </Card>
  162. );
  163. }
  164.  
  165. return (
  166. <div onClick={this.handleClick}>
  167. {contents}
  168. </div>
  169. );
  170. }}
  171.  
  172. const insertEmbed = (editorState) => {
  173. const newContentState = editorState.getCurrentContent().createEntity(
  174. 'TOKEN',
  175. 'IMMUTABLE',
  176. {customType: 'embed', content: '', label: ''}
  177. );
  178. const entityKey = newContentState.getLastCreatedEntityKey();
  179.  
  180. return AtomicBlockUtils.insertAtomicBlock(
  181. editorState,
  182. entityKey,
  183. ' '
  184. );
  185. }
  186.  
  187. export {Embed as default, insertEmbed};