Skip to content

Instantly share code, notes, and snippets.

@alexandrebodin
Created August 27, 2018 14:55
Show Gist options
  • Select an option

  • Save alexandrebodin/366ef176840f27df62cf599f68f7e636 to your computer and use it in GitHub Desktop.

Select an option

Save alexandrebodin/366ef176840f27df62cf599f68f7e636 to your computer and use it in GitHub Desktop.

Revisions

  1. alexandrebodin created this gist Aug 27, 2018.
    113 changes: 113 additions & 0 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,113 @@
    import React from 'react';
    import ESClient from './modules/elasticsearch';

    const { Provider, Consumer } = React.createContext();

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

    this.client = new ESClient({ index: this.props.index, type: this.props.type });
    }

    setSize = size => this.setState({ size });
    addFacet = ({ field }) => {
    this.setState(
    state => ({
    facets: {
    ...state.facets,
    [field]: []
    }
    }),
    this.search
    );
    };

    search = () => {
    this.client
    .search({
    facets: Object.keys(this.state.facets)
    })
    .then(response => {
    this.setState({
    response
    });
    });
    };

    state = {
    index: this.props.index,
    type: this.props.type,
    hits: [],
    facets: {},
    response: null,

    setSize: this.setSize,
    addFacet: this.addFacet
    };

    render() {
    return <Provider value={this.state}>{this.props.children}</Provider>;
    }
    }

    class FacetCmp extends React.Component {
    componentDidMount() {
    this.props.es.addFacet({
    field: this.props.field
    });
    }

    render() {
    return (
    <div>
    {this.props.es.response && this.props.es.response.facets[this.props.field]
    ? this.props.es.response.facets[this.props.field].map(f => {
    return (
    <label key={f.key}>
    <input type="checkbox" value={f.value} checked={f.checked} />
    {f.key}
    </label>
    );
    })
    : null}
    </div>
    );
    }
    }

    const Facet = props => <Consumer>{es => <FacetCmp es={es} {...props} />}</Consumer>;

    class HitsCmp extends React.Component {
    componentDidMount() {
    this.props.es.setSize(this.props.size);
    }

    componentDidUpdate(prevProps, prevState) {
    if (this.props.size !== prevProps.size) {
    this.props.es.setSize(this.props.size);
    }
    }

    render() {
    if (this.props.es && this.props.es.response && this.props.es.response.hits) {
    return this.props.children(this.props.es.response.hits.hits.map(hit => hit._source));
    }

    return null;
    }
    }

    const Hits = ({ ...props }) => <Consumer>{es => <HitsCmp es={es} {...props} />}</Consumer>;

    export default () => (
    <ES index="index" type="documents">
    <Facet field="source" />
    <Facet field="country" />
    <Hits size={10}>
    {hits => {
    return <ul>{hits.map(hit => <li key={hit.id}>{hit.id}</li>)}</ul>;
    }}
    </Hits>
    </ES>
    );