<commit_before>import { bindActionCreators } from 'redux';
import { browserHistory } from 'react-router';
import { connect } from 'react-redux';
import { fetchVAFacilities, updateSearchQuery, search } from '../actions';
import { map } from 'lodash';
import { Map, Marker, Popup, TileLayer } from 'react-leaflet';
import { mapboxClient, mapboxToken } from '../components/MapboxClient';
import React, { Component } from 'react';
import ResultsPane from '../components/ResultsPane';
import $ from 'jQuery';

class VAMap extends Component {

  componentDidMount() {
    const { location, currentQuery } = this.props;
    let shouldGeolocate = true;

    if (location.query.address) {
      // populate search bar with address in Url
      this.props.updateSearchQuery({
        searchString: location.query.address,
      });
    }

    if (location.query.location) {
      shouldGeolocate = false;
      const coords = location.query.location.split(',').map(Number);
      this.props.updateSearchQuery({
        position: {
          latitude: coords[0],
          longitude: coords[1],
        }
      });

      if (!location.query.address) {
        this.reverseGeocode({
          latitude: coords[0],
          longitude: coords[1],
        });
      }
    }

    this.props.fetchVAFacilities(currentQuery.position);

    this.mapElement = this.refs.map.leafletElement.getBounds();
    if (navigator.geolocation && shouldGeolocate) {
      navigator.geolocation.getCurrentPosition((currentPosition) => {
        this.props.updateSearchQuery({
          position: currentPosition.coords,
        });
        this.updateUrlParams({
          location: [currentPosition.coords.latitude, currentPosition.coords.longitude].join(','),
        });
        this.reverseGeocode(currentPosition.coords);
      });
    }
  }

  componentWillReceiveProps(nextProps) {
    const { currentQuery } = this.props;
    const newQuery = nextProps.currentQuery;

    if (currentQuery.position !== newQuery.position) {
      this.updateUrlParams({
        location: `${newQuery.position.latitude},${newQuery.position.longitude}`,
      });
      this.props.fetchVAFacilities(newQuery.position);
    }
  }

  // pushes coordinates to URL so that map link is useful for sharing
  // TODO (bshyong): try out existing query-string npm library
  updateUrlParams(params) {
    const { location } = this.props;

    const queryParams = map({
      ...location.query,
      ...params,
    }, (v, k) => {
      return `${k}=${v}`;
    }).join('&');
    browserHistory.push(`${location.pathname}?${queryParams}`);
  }

  // takes obj of form {latitude: 0, longitude: 0}
  reverseGeocode(position) {
    mapboxClient.geocodeReverse(position, {
      types: 'address',
    }, (err, res) => {
      // TODO (bshyong): handle error case
      const placeName = res.features[0].place_name;
      this.props.updateSearchQuery({
        searchString: placeName,
      });
      this.updateUrlParams({
        address: placeName,
      });
    });
  }

  handleSearch = () => {
    const { currentQuery } = this.props;

    this.updateUrlParams({
      address: currentQuery.searchString,
    });
    this.props.search(currentQuery);
  }

  renderFacilityMarkers() {
    const facilities = this.props.facilities;

    return facilities.map(f => {
      return (
        <Marker key={f.id} position={[f.lat, f.long]}>
          <Popup>
            <span>{`Facility ${f.id}: ${f.attributes.name}`}</span>
          </Popup>
        </Marker>
      );
    });
  }

  render() {
  // defaults to White House coordinates initially
    const coords = this.props.currentQuery.position;
    const position = [coords.latitude, coords.longitude];
    // used for setting a proper map height
    const mapHeight = window.innerHeight - $('.header').height() - 175;

    return (
      <div>
        <div className="columns medium-4">
          <ResultsPane onSearch={this.handleSearch} maxHeight={mapHeight}/>
        </div>
        <div className="medium-8 columns" style={{ minHeight: mapHeight }}>
          <Map ref="map" center={position} zoom={13} style={{ minHeight: mapHeight, width: '100%' }}>
            <TileLayer
                url={`https://api.mapbox.com/styles/v1/mapbox/streets-v9/tiles/256/{z}/{x}/{y}?access_token=${mapboxToken}`}<commit_msg>Calculate map height with plain javascript<commit_after>import { bindActionCreators } from 'redux';
import { browserHistory } from 'react-router';
import { connect } from 'react-redux';
import { fetchVAFacilities, updateSearchQuery, search } from '../actions';
import { map } from 'lodash';
import { Map, Marker, Popup, TileLayer } from 'react-leaflet';
import { mapboxClient, mapboxToken } from '../components/MapboxClient';
import React, { Component } from 'react';
import ResultsPane from '../components/ResultsPane';

class VAMap extends Component {

  componentDidMount() {
    const { location, currentQuery } = this.props;
    let shouldGeolocate = true;

    if (location.query.address) {
      // populate search bar with address in Url
      this.props.updateSearchQuery({
        searchString: location.query.address,
      });
    }

    if (location.query.location) {
      shouldGeolocate = false;
      const coords = location.query.location.split(',').map(Number);
      this.props.updateSearchQuery({
        position: {
          latitude: coords[0],
          longitude: coords[1],
        }
      });

      if (!location.query.address) {
        this.reverseGeocode({
          latitude: coords[0],
          longitude: coords[1],
        });
      }
    }

    this.props.fetchVAFacilities(currentQuery.position);

    this.mapElement = this.refs.map.leafletElement.getBounds();
    if (navigator.geolocation && shouldGeolocate) {
      navigator.geolocation.getCurrentPosition((currentPosition) => {
        this.props.updateSearchQuery({
          position: currentPosition.coords,
        });
        this.updateUrlParams({
          location: [currentPosition.coords.latitude, currentPosition.coords.longitude].join(','),
        });
        this.reverseGeocode(currentPosition.coords);
      });
    }
  }

  componentWillReceiveProps(nextProps) {
    const { currentQuery } = this.props;
    const newQuery = nextProps.currentQuery;

    if (currentQuery.position !== newQuery.position) {
      this.updateUrlParams({
        location: `${newQuery.position.latitude},${newQuery.position.longitude}`,
      });
      this.props.fetchVAFacilities(newQuery.position);
    }
  }

  // pushes coordinates to URL so that map link is useful for sharing
  // TODO (bshyong): try out existing query-string npm library
  updateUrlParams(params) {
    const { location } = this.props;

    const queryParams = map({
      ...location.query,
      ...params,
    }, (v, k) => {
      return `${k}=${v}`;
    }).join('&');
    browserHistory.push(`${location.pathname}?${queryParams}`);
  }

  // takes obj of form {latitude: 0, longitude: 0}
  reverseGeocode(position) {
    mapboxClient.geocodeReverse(position, {
      types: 'address',
    }, (err, res) => {
      // TODO (bshyong): handle error case
      const placeName = res.features[0].place_name;
      this.props.updateSearchQuery({
        searchString: placeName,
      });
      this.updateUrlParams({
        address: placeName,
      });
    });
  }

  handleSearch = () => {
    const { currentQuery } = this.props;

    this.updateUrlParams({
      address: currentQuery.searchString,
    });
    this.props.search(currentQuery);
  }

  renderFacilityMarkers() {
    const facilities = this.props.facilities;

    return facilities.map(f => {
      return (
        <Marker key={f.id} position={[f.lat, f.long]}>
          <Popup>
            <span>{`Facility ${f.id}: ${f.attributes.name}`}</span>
          </Popup>
        </Marker>
      );
    });
  }

  render() {
  // defaults to White House coordinates initially
    const coords = this.props.currentQuery.position;
    const position = [coords.latitude, coords.longitude];
    // used for setting a proper map height
    const mapHeight = window.innerHeight - document.getElementsByClassName('header')[0].clientHeight - 175;

    return (
      <div>
        <div className="columns medium-4">
          <ResultsPane onSearch={this.handleSearch} maxHeight={mapHeight}/>
        </div>
        <div className="medium-8 columns" style={{ minHeight: mapHeight }}>
          <Map ref="map" center={position} zoom={13} style={{ minHeight: mapHeight, width: '100%' }}>
            <TileLayer
                url={`https://api.mapbox.com/styles/v1/mapbox/streets-v9/tiles/256/{z}/{x}/{y}?access_token=${mapboxToken}`}
{'fraction_non_alphanumeric': 0.1413407176647052, 'fraction_numerical': 0.005192107995846314, 'mean_word_length': 2.7654213727193744, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 37, 'https://': 2, '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': '4659933', 'n_tokens_mistral': 2618, 'n_tokens_neox': 2560, 'n_words': 519}