Home Reference Source

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

import React from 'react';
import {Card, CardActions, CardHeader, CardMedia, CardTitle, CardText} from 'material-ui/Card';
import FlatButton from 'material-ui/FlatButton';
import TextField from 'material-ui/TextField';

import {AtomicBlockUtils, Entity} from 'draft-js';

import {info} from './../../../util/console';
import BaseView from './../../base-view';

/**
 * Render a pull quote box. This is one of the few components
 * that doesn't really have a set style and requires the
 * output client to handle all rendering.
 */
class PullQuoteBlock extends BaseView {
    constructor(props) {
        super(props);

        this.getValue = this.getValue.bind(this);
        this.handleSave = this.handleSave.bind(this);
        this.handleCancel = this.handleCancel.bind(this);
        this.handleClick = this.handleClick.bind(this);

        this.startEdit = this.startEdit.bind(this);
        this.finishEdit = this.finishEdit.bind(this);

        this.state = {
            editMode: false
        };
    }

    /**
     * Return quote content
     * @return {String}
     */
    getValue() {
        if (!this.props.block) {
            return;
        }
        return this.props.contentState
            .getEntity(this.props.block.getEntityAt(0))
            .getData()['content'];
    }

    /**
     * Return quote credit
     * @return {String}
     */
    getCredit() {
        if (!this.props.block) {
            return;
        }
        return this.props.contentState
            .getEntity(this.props.block.getEntityAt(0))
            .getData()['credit'];
    }

    startEdit() {
        if (this.props.blockProps && this.props.blockProps.onStartEdit) {
            this.props.blockProps.onStartEdit(this.props.block.getKey());
        }
    }

    finishEdit() {
        if (this.props.blockProps && this.props.blockProps.onFinishEdit) {
            this.props.blockProps.onFinishEdit(this.props.block.getKey());
        }
    }

    handleClick() {
        if (this.state.editMode) {
            return;
        }

        this.setState({
            editMode: true,
            quote: this.getValue(),
            credit: this.getCredit()
        }, () => { this.startEdit() });

        setTimeout(() => {
            this.refs.content.focus();
        }, 1);
    }

    handleCancel() {
        this.setState({editMode: false}, () => { this.finishEdit() });
    }

    handleSave() {
        const newContents = this.state.quote;
        const newCredit = this.state.credit;

        if (this.props.block) {
            const key = this.props.block.getEntityAt(0);
            this.props.contentState.mergeEntityData(key, {content: newContents, credit: newCredit});
        } else {
            info('No block properties set, cannot save meta data');
        }

        this.setState({editMode: false}, () => { this.finishEdit() });
    }

    handleChange(e) {
        if (e.target.name === 'content') {
            this.setState({'quote': e.target.value});
        } else if (e.target.name === 'credit') {
            this.setState({'credit': e.target.value});
        }
    }

    render() {

        let contents;
        let className = 'RichEditor-pullQuote';

        if (this.state.editMode) {
            contents = (
                <Card>
                    <CardHeader
                        title="Pull Quote"
                        subtitle="Like regular quotes, but bigger!"
                        />
                    <CardText>
                        <TextField
                            fullWidth={true}
                            name="content"
                            ref="content"
                            value={this.state.quote}
                            onChange={this.handleChange.bind(this)}
                            multiLine={true}
                            floatingLabelText='Quote'
                            />
                        <TextField
                            fullWidth={true}
                            name="credit"
                            ref="credit"
                            value={this.state.credit}
                            onChange={this.handleChange.bind(this)}
                            floatingLabelText='Credit'
                            />

                    </CardText>
                    <CardActions>
                        <FlatButton onClick={this.handleSave} label='Done' />
                        <FlatButton onClick={this.handleCancel} label='Cancel' />
                    </CardActions>
                </Card>
            );

            className = className + ' active';
        } else {
            contents = (
                <Card>
                    <CardHeader
                        title="Pull Quote"
                        subtitle="Like regular quotes, but bigger!"
                        />
                    <CardText>
                        <div className='pullquote-quote'>
                            {this.getValue()}
                        </div>
                        <div className='pullquote-credit'>
                            <strong>{this.getCredit() ? '- ' + this.getCredit() : ''}</strong>
                        </div>
                    </CardText>
                </Card>
            );
        }

        return (
            <div style={{marginRight:'20px'}} onClick={this.handleClick}>
                {contents}
            </div>
        );
    }
}

/**
 * Simple callback to insert the quote wrapper into the editor
 */
const insertPullQuote = (editorState, quoteText = null) => {

    if (!quoteText) {
        quoteText = 'In Soviet Russia, quotes pull YOU';
    }

    const newContentState = editorState.getCurrentContent().createEntity(
        'TOKEN',
        'IMMUTABLE',
        {customType: 'pull-quote', content: quoteText, credit: ''}
    );
    const entityKey = newContentState.getLastCreatedEntityKey();

    return AtomicBlockUtils.insertAtomicBlock(
        editorState,
        entityKey,
        ' '
    );
};

export {PullQuoteBlock as default, insertPullQuote};