<commit_before>import React, { Component, PropTypes } from 'react';
import queryString from 'query-string';

import AppHeader from './AppHeader';
import LeafletMapConnected from '../containers/LeafletMapConnected';
import StatsLegendConnected from '../containers/StatsLegendConnected';
import OptionsFiltersConnected from '../containers/OptionsFiltersConnected';

class App extends Component {
  constructor() {
    super();
    this.onMapMoved = this.onMapMoved.bind(this);
  }

  onMapMoved(event) {
    // update the url query params with map center & zoom
    if (event && event.target) {
      const query = {};
      query.zoom = event.target.getZoom();
      query.lat = event.target.getCenter().lat;
      query.lng = event.target.getCenter().lng;
      this.updateQueryParams(query);
    }
  }

  updateQueryParams(params) {
    const { lat, lng, zoom } = params;
    const newQueryParams = {};
    newQueryParams.lat = lat || null;
    newQueryParams.lng = lng || null;
    newQueryParams.zoom = zoom || null;
    this.context.router.push(`?${queryString.stringify(newQueryParams)}`);
  }

  render() {
    const { location } = this.props;
    return (
      <div className="App">
        <AppHeader />
        <LeafletMapConnected
          location={location}
          onMapMoved={this.onMapMoved}
        />
        <StatsLegendConnected />
        <OptionsFiltersConnected />
      </div>
    );
  }
}

App.propTypes = {
  location: PropTypes.shape({
    query: PropTypes.object.isRequired
  }).isRequired
};

App.contextTypes = {
  router: React.PropTypes.object.isRequired
};

export default App;<commit_msg>Update location.query params from App when date range filter changes<commit_after>import React, { Component, PropTypes } from 'react';
import queryString from 'query-string';

import AppHeader from './AppHeader';
import LeafletMapConnected from '../containers/LeafletMapConnected';
import StatsLegendConnected from '../containers/StatsLegendConnected';
import OptionsFiltersConnected from '../containers/OptionsFiltersConnected';

class App extends Component {
  constructor() {
    super();
    this.onMapMoved = this.onMapMoved.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    const { startDate, endDate } = nextProps;
    if (startDate !== this.props.startDate || endDate !== this.props.endDate) {
      this.updateQueryParams({ startDate, endDate });
    }
  }

  onMapMoved(event) {
    // update the url query params with map center & zoom
    if (event && event.target) {
      const query = {};
      query.zoom = event.target.getZoom();
      query.lat = event.target.getCenter().lat;
      query.lng = event.target.getCenter().lng;
      this.updateQueryParams(query);
    }
  }

  updateQueryParams(params) {
    // updates the URL location query with app state filters & map zoom & center
    // this allows for "stateful URLs" so that when app loads, it will load
    // with the same filters & map zoom & center last viewed, enabling sharing
    // of unique views of the data via the URL between users
    const { lat, lng, zoom, startDate, endDate } = params;
    const { query } = this.props.location;

    const newQueryParams = {
      lat: lat || query.lat,
      lng: lng || query.lng,
      zoom: zoom || query.zoom,
      startDate: startDate || this.props.startDate,
      endDate: endDate || this.props.endDate,
    };

    this.context.router.push(`?${queryString.stringify(newQueryParams)}`);
  }

  render() {
    const { location } = this.props;
    return (
      <div className="App">
        <AppHeader />
        <LeafletMapConnected
          location={location}
          onMapMoved={this.onMapMoved}
        />
        <StatsLegendConnected />
        <OptionsFiltersConnected />
      </div>
    );
  }
}

App.propTypes = {
  location: PropTypes.shape({
    query: PropTypes.object.isRequired
  }).isRequired,
  startDate: PropTypes.string.isRequired,
  endDate: PropTypes.string.isRequired
};

App.contextTypes = {
  router: React.PropTypes.object.isRequired
};

export default App;
{'fraction_non_alphanumeric': 0.12198127156234598, 'fraction_numerical': 0.0, 'mean_word_length': 3.0835010060362174, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4081652', 'n_tokens_mistral': 1206, 'n_tokens_neox': 1205, 'n_words': 283}