Home Reference Source

application/components/search.js

import React from 'react';
import {connect} from 'react-redux';
import {browserHistory} from 'react-router';

import Paper from 'material-ui/Paper';
import TextField from 'material-ui/TextField';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
import RaisedButton from 'material-ui/RaisedButton';
import Divider from 'material-ui/Divider';

import LoadingIndicator from './common/loading-indicator';

import {Row, Col} from './flexbox';
import Config from './../config';
import CurrentUser from './../current-user';

import Request from './../util/request';

import SearchResultsTable from './search/result-table';
import ReduxPaginator from './common/redux-paginator';

import {ENTER_KEY} from '../util/key-codes';
import {parameterize} from '../util/strings';

import {
    globalSearchFetch
} from './../redux/actions/global-search-actions';

export function buildQuery(query) {
    const req = {
        keywords: query.q
    };
    let filter = {};

    if (query.type && query.type !== 'undefined') {
        req['type'] = query.type;
    }
    if (query.has_attachment && query.has_attachment !== 'undefined') {
        req['has_attachment'] = query.has_attachment;
    }
    if (query.filter_content_type && query.filter_content_type !== 'undefined') {
        filter = Object.assign({}, filter, {
            'content_type': query.filter_content_type
        });
    }
    if (query.author && query.author !== 'undefined') {
        req['author'] = query.author;
    }
    if (query.tag && query.tag !== 'undefined') {
        req['tag'] = query.tag;
    }
    if (query.page && query.page !== 'undefined') {
        req['page'] = query.page;
    }
    if (query.limit && query.limit !== 'undefined') {
        req['limit'] = query.limit;
    }
    if (query.sort && query.sort !== 'undefined') {
        req['sort'] = query.sort;
    }

    if (filter) {
        req['filters'] = filter;
    }

    return req;
}

class Search extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            selectedType: null
        };
    }

    componentDidMount() {
        if (this.props.router.location.query.q ) {
            this.runSearch.call(this);
        }

        if (this.props.router.location.query.filter_content_type) {
            this.setState({
                'selectedType':
                this.props.router.location.query.filter_content_type
            });
        }
    }

    handlePagination(page) {
        // Use setQuery here so we don't replace existing bits
        const url = '/ceo/search?' + Request.setQuery({'page': page});
        browserHistory.push(url);
    }

    runSearch() {
        const {dispatch} = this.props;
        const query = buildQuery(this.props.router.location.query);
        dispatch(globalSearchFetch(query));
    }

    handleTypeChange(e, index, value) {
        this.setState({'selectedType': value});
    }

    handleAdvancedSearch(e) {
        let query = {
            q: this.refs.keywords.input.value,
            author: this.refs.author.input.value,
            tag: this.refs.tag.input.value
        };

        const selectedType = this.state.selectedType;
        if (selectedType) {
            query['filter_content_type'] = selectedType;
        }

        // Use parameterize here because we want to replace everything
        const url = '/ceo/search?' + parameterize(query);
        browserHistory.push(url);
    }

    handleKeyUp(e) {
        if (e.keyCode !== ENTER_KEY) {
            return;
        }
        this.handleAdvancedSearch.call(this);
    }

    render() {
        return (
            <div className='search-root'>
                <Row>
                    <Col xs={12}>
                        <Paper className='padded'>
                            <Row>
                                <Col xs={3}>
                                    <TextField
                                        floatingLabelText='Keywords'
                                        ref='keywords'
                                        defaultValue={this.props.router.location.query.q ? this.props.router.location.query.q : null}
                                        onKeyUp={this.handleKeyUp.bind(this)}
                                        fullWidth={true}
                                        />
                                    <SelectField
                                        floatingLabelText='Type'
                                        ref='type'
                                        value={this.state.selectedType}
                                        onChange={this.handleTypeChange.bind(this)}
                                        fullWidth={true}
                                        >
                                        <MenuItem value={null} />
                                        <MenuItem value='article' primaryText='Article' />
                                        <MenuItem value='media' primaryText='Media' />
                                        <MenuItem value='post' primaryText='Post' />
                                        <MenuItem value='page' primaryText='Page' />
                                    </SelectField>
                                    <TextField
                                        floatingLabelText='Tag'
                                        ref='tag'
                                        defaultValue={this.props.router.location.query.tag ? this.props.router.location.query.tag : null}
                                        onKeyUp={this.handleKeyUp.bind(this)}
                                        fullWidth={true}
                                        />
                                    <TextField
                                        floatingLabelText='Author'
                                        ref='author'
                                        defaultValue={this.props.router.location.query.author ? this.props.router.location.query.author : null}
                                        onKeyUp={this.handleKeyUp.bind(this)}
                                        fullWidth={true}
                                        />

                                    <RaisedButton
                                        className='clear-top'
                                        label='Search'
                                        primary={true}
                                        onClick={this.handleAdvancedSearch.bind(this)}
                                        />
                                </Col>
                                <Col xs={9}>
                                    {
                                        !this.props.globalSearch.didSearch
                                        ? (
                                            <div className='clear-top'>
                                                <p>
                                                    Search all CEO content.
                                                </p>
                                            </div>
                                        )
                                        : (
                                            <div>
                                                <Row bottom='xs'>
                                                    <Col xs={4}>
                                                        Found {parseInt(this.props.globalSearch.pagination.total_items)} result(s)
                                                    </Col>
                                                    <Col xs={8} end='xs'>
                                                        <ReduxPaginator pagination={this.props.globalSearch.pagination} onPaginate={this.handlePagination.bind(this)} />
                                                    </Col>
                                                </Row>
                                                {
                                                    this.props.globalSearch.isFetching
                                                    ? <LoadingIndicator />
                                                    : <SearchResultsTable />
                                                }
                                            </div>
                                        )
                                    }
                                </Col>
                            </Row>
                        </Paper>
                    </Col>
                </Row>
            </div>

        );
    }
}

const mapStateToProps = (state) => {
    return {
        globalSearch: state.globalSearch
    }
}
export default connect(mapStateToProps)(Search);