Home Reference Source

application/components/common/rich-editor/pull-quote.js

  1. import React from 'react';
  2. import {Card, CardActions, CardHeader, CardMedia, CardTitle, CardText} from 'material-ui/Card';
  3. import FlatButton from 'material-ui/FlatButton';
  4. import TextField from 'material-ui/TextField';
  5.  
  6. import {AtomicBlockUtils, Entity} from 'draft-js';
  7.  
  8. import {info} from './../../../util/console';
  9. import BaseView from './../../base-view';
  10.  
  11. /**
  12. * Render a pull quote box. This is one of the few components
  13. * that doesn't really have a set style and requires the
  14. * output client to handle all rendering.
  15. */
  16. class PullQuoteBlock extends BaseView {
  17. constructor(props) {
  18. super(props);
  19.  
  20. this.getValue = this.getValue.bind(this);
  21. this.handleSave = this.handleSave.bind(this);
  22. this.handleCancel = this.handleCancel.bind(this);
  23. this.handleClick = this.handleClick.bind(this);
  24.  
  25. this.startEdit = this.startEdit.bind(this);
  26. this.finishEdit = this.finishEdit.bind(this);
  27.  
  28. this.state = {
  29. editMode: false
  30. };
  31. }
  32.  
  33. /**
  34. * Return quote content
  35. * @return {String}
  36. */
  37. getValue() {
  38. if (!this.props.block) {
  39. return;
  40. }
  41. return this.props.contentState
  42. .getEntity(this.props.block.getEntityAt(0))
  43. .getData()['content'];
  44. }
  45.  
  46. /**
  47. * Return quote credit
  48. * @return {String}
  49. */
  50. getCredit() {
  51. if (!this.props.block) {
  52. return;
  53. }
  54. return this.props.contentState
  55. .getEntity(this.props.block.getEntityAt(0))
  56. .getData()['credit'];
  57. }
  58.  
  59. startEdit() {
  60. if (this.props.blockProps && this.props.blockProps.onStartEdit) {
  61. this.props.blockProps.onStartEdit(this.props.block.getKey());
  62. }
  63. }
  64.  
  65. finishEdit() {
  66. if (this.props.blockProps && this.props.blockProps.onFinishEdit) {
  67. this.props.blockProps.onFinishEdit(this.props.block.getKey());
  68. }
  69. }
  70.  
  71. handleClick() {
  72. if (this.state.editMode) {
  73. return;
  74. }
  75.  
  76. this.setState({
  77. editMode: true,
  78. quote: this.getValue(),
  79. credit: this.getCredit()
  80. }, () => { this.startEdit() });
  81.  
  82. setTimeout(() => {
  83. this.refs.content.focus();
  84. }, 1);
  85. }
  86.  
  87. handleCancel() {
  88. this.setState({editMode: false}, () => { this.finishEdit() });
  89. }
  90.  
  91. handleSave() {
  92. const newContents = this.state.quote;
  93. const newCredit = this.state.credit;
  94.  
  95. if (this.props.block) {
  96. const key = this.props.block.getEntityAt(0);
  97. this.props.contentState.mergeEntityData(key, {content: newContents, credit: newCredit});
  98. } else {
  99. info('No block properties set, cannot save meta data');
  100. }
  101.  
  102. this.setState({editMode: false}, () => { this.finishEdit() });
  103. }
  104.  
  105. handleChange(e) {
  106. if (e.target.name === 'content') {
  107. this.setState({'quote': e.target.value});
  108. } else if (e.target.name === 'credit') {
  109. this.setState({'credit': e.target.value});
  110. }
  111. }
  112.  
  113. render() {
  114.  
  115. let contents;
  116. let className = 'RichEditor-pullQuote';
  117.  
  118. if (this.state.editMode) {
  119. contents = (
  120. <Card>
  121. <CardHeader
  122. title="Pull Quote"
  123. subtitle="Like regular quotes, but bigger!"
  124. />
  125. <CardText>
  126. <TextField
  127. fullWidth={true}
  128. name="content"
  129. ref="content"
  130. value={this.state.quote}
  131. onChange={this.handleChange.bind(this)}
  132. multiLine={true}
  133. floatingLabelText='Quote'
  134. />
  135. <TextField
  136. fullWidth={true}
  137. name="credit"
  138. ref="credit"
  139. value={this.state.credit}
  140. onChange={this.handleChange.bind(this)}
  141. floatingLabelText='Credit'
  142. />
  143.  
  144. </CardText>
  145. <CardActions>
  146. <FlatButton onClick={this.handleSave} label='Done' />
  147. <FlatButton onClick={this.handleCancel} label='Cancel' />
  148. </CardActions>
  149. </Card>
  150. );
  151.  
  152. className = className + ' active';
  153. } else {
  154. contents = (
  155. <Card>
  156. <CardHeader
  157. title="Pull Quote"
  158. subtitle="Like regular quotes, but bigger!"
  159. />
  160. <CardText>
  161. <div className='pullquote-quote'>
  162. {this.getValue()}
  163. </div>
  164. <div className='pullquote-credit'>
  165. <strong>{this.getCredit() ? '- ' + this.getCredit() : ''}</strong>
  166. </div>
  167. </CardText>
  168. </Card>
  169. );
  170. }
  171.  
  172. return (
  173. <div style={{marginRight:'20px'}} onClick={this.handleClick}>
  174. {contents}
  175. </div>
  176. );
  177. }
  178. }
  179.  
  180. /**
  181. * Simple callback to insert the quote wrapper into the editor
  182. */
  183. const insertPullQuote = (editorState, quoteText = null) => {
  184.  
  185. if (!quoteText) {
  186. quoteText = 'In Soviet Russia, quotes pull YOU';
  187. }
  188.  
  189. const newContentState = editorState.getCurrentContent().createEntity(
  190. 'TOKEN',
  191. 'IMMUTABLE',
  192. {customType: 'pull-quote', content: quoteText, credit: ''}
  193. );
  194. const entityKey = newContentState.getLastCreatedEntityKey();
  195.  
  196. return AtomicBlockUtils.insertAtomicBlock(
  197. editorState,
  198. entityKey,
  199. ' '
  200. );
  201. };
  202.  
  203. export {PullQuoteBlock as default, insertPullQuote};