<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import reactMixin from 'react-mixin';
import autoBind from 'react-autobind';
import Reflux from 'reflux';
import _ from 'underscore';
import {dataInterface} from '../dataInterface';
import {hashHistory} from 'react-router';
import bem from '../bem';
import stores from '../stores';
import ui from '../ui';
import alertify from 'alertifyjs';
import classNames from 'classnames';

import L from 'leaflet/dist/leaflet';
import 'leaflet/dist/leaflet.css';
import 'leaflet.heat/dist/leaflet-heat';
import 'leaflet.markercluster/dist/leaflet.markercluster';
import 'leaflet.markercluster/dist/MarkerCluster.css';

import {
  assign,
  t,
  log,
  notify,
} from '../utils';

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

    let survey = props.asset.content.survey;
    var hasGeoPoint = false;
    survey.forEach(function(s) {
      if (s.type == 'geopoint')
        hasGeoPoint = true;
    });

    this.state = {
      map: false,
      markers: false,
      heatmap: false,
      markersVisible: true,
      markerMap: false,
      fields: [],
      hasGeoPoint: hasGeoPoint,
      submissions: [],
      error: false,
      showExpandedMap: false,
      showExpandedLegend: true,
      langIndex: 0,
      filteredByMarker: false
    };

    autoBind(this);    
  }

  componentDidMount () {
    if (!this.state.hasGeoPoint)
      return false;

    var fields = [];
    let fieldTypes = ['select_one', 'select_multiple', 'integer', 'decimal', 'text'];
    this.props.asset.content.survey.forEach(function(q){
      if (fieldTypes.includes(q.type)) {
        fields.push(q);
      }
    });

    var map = L.map('data-map', {
      maxZoom: 17,
      scrollWheelZoom: false,
      preferCanvas: true
    });

    var streets = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
        subdomains: ['a', 'b', 'c']
    });
    streets.addTo(map);

    var outdoors = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
        attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
    });

    var satellite = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
        attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
      }
    );

    var humanitarian = L.tileLayer('https://tile-{s}.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
        attribution: 'Tiles &copy; Humanitarian OpenStreetMap Team &mdash; &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
      }
    );

    var baseLayers = {
        "OpenStreetMap": streets,
        "OpenTopoMap": outdoors,
        "ESRI World Imagery": satellite,
        "Humanitarian": humanitarian
    };

    L.control.layers(baseLayers).addTo(map);

    this.setState({
        map: map,
        fields: fields
      }
    );

    if(this.props.asset.deployment__submission_count > 5000) {
      notify(t('This map display is currently limited to 5000 records for performance reasons.'));
    }

    this.requestData(map, this.props.viewby);
  }

  requestData(map, nextViewBy = '') {
    var fq = ['_id', '_geolocation'];
    if (nextViewBy) {
      fq.push(this.nameOfFieldInGroup(nextViewBy));
    }

    const sort = [{id: '_id', desc: true}];

    // TODO: handle forms with over 5000 results
    dataInterface.getSubmissions(this.props.asset.uid, 5000, 0, sort, fq).done((data) => {
      this.setState({submissions: data});
      this.buildMarkers(map);
      this.buildHeatMap(map);
    }).fail((error)=>{
      if (error.responseText)
        this.setState({error: error.responseText, loading: false});
      else if (error.statusText)
        this.setState({error: error.statusText, loading: false});
      else
        this.setState({error: t('Error: could not load data.'), loading: false});
    });
  } 

  calculateClusterRadius(zoom) {
   if(zoom >=12) {return 12;}
   return 20;
  }

  buildMarkers(map) {
    var _this = this;
    var prepPoints = [];
    var icon = L.divIcon({
      className: 'map-marker',
      iconSize: [20, 20],
    });

    var viewby = this.props.viewby || undefined;

    if (viewby) {
      var mapMarkers = this.prepFilteredMarkers(this.state.submissions, this.props.viewby);
      var mM = [];
      let choices = this.props.asset.content.choices;

      Object.keys(mapMarkers).map(function(m, i) {
        var lbl = choices.find(o => o.name === m || o.$autoname == m);
        mM.push({
          count: mapMarkers[m].count,
          id: mapMarkers[m].id,
          labels: lbl ? lbl.label : undefined,
          value: m != "undefined" ? m : undefined
        });
      });

      mM.sort(function(a, b) {
        return a.count - b.count;
      }).reverse();
      this.setState({markerMap: mM});<commit_msg>fix select_one choice labels in map<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import reactMixin from 'react-mixin';
import autoBind from 'react-autobind';
import Reflux from 'reflux';
import _ from 'underscore';
import {dataInterface} from '../dataInterface';
import {hashHistory} from 'react-router';
import bem from '../bem';
import stores from '../stores';
import ui from '../ui';
import alertify from 'alertifyjs';
import classNames from 'classnames';

import L from 'leaflet/dist/leaflet';
import 'leaflet/dist/leaflet.css';
import 'leaflet.heat/dist/leaflet-heat';
import 'leaflet.markercluster/dist/leaflet.markercluster';
import 'leaflet.markercluster/dist/MarkerCluster.css';

import {
  assign,
  t,
  log,
  notify,
} from '../utils';

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

    let survey = props.asset.content.survey;
    var hasGeoPoint = false;
    survey.forEach(function(s) {
      if (s.type == 'geopoint')
        hasGeoPoint = true;
    });

    this.state = {
      map: false,
      markers: false,
      heatmap: false,
      markersVisible: true,
      markerMap: false,
      fields: [],
      hasGeoPoint: hasGeoPoint,
      submissions: [],
      error: false,
      showExpandedMap: false,
      showExpandedLegend: true,
      langIndex: 0,
      filteredByMarker: false
    };

    autoBind(this);    
  }

  componentDidMount () {
    if (!this.state.hasGeoPoint)
      return false;

    var fields = [];
    let fieldTypes = ['select_one', 'select_multiple', 'integer', 'decimal', 'text'];
    this.props.asset.content.survey.forEach(function(q){
      if (fieldTypes.includes(q.type)) {
        fields.push(q);
      }
    });

    var map = L.map('data-map', {
      maxZoom: 17,
      scrollWheelZoom: false,
      preferCanvas: true
    });

    var streets = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
        subdomains: ['a', 'b', 'c']
    });
    streets.addTo(map);

    var outdoors = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
        attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
    });

    var satellite = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
        attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
      }
    );

    var humanitarian = L.tileLayer('https://tile-{s}.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
        attribution: 'Tiles &copy; Humanitarian OpenStreetMap Team &mdash; &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
      }
    );

    var baseLayers = {
        "OpenStreetMap": streets,
        "OpenTopoMap": outdoors,
        "ESRI World Imagery": satellite,
        "Humanitarian": humanitarian
    };

    L.control.layers(baseLayers).addTo(map);

    this.setState({
        map: map,
        fields: fields
      }
    );

    if(this.props.asset.deployment__submission_count > 5000) {
      notify(t('This map display is currently limited to 5000 records for performance reasons.'));
    }

    this.requestData(map, this.props.viewby);
  }

  requestData(map, nextViewBy = '') {
    var fq = ['_id', '_geolocation'];
    if (nextViewBy) {
      fq.push(this.nameOfFieldInGroup(nextViewBy));
    }

    const sort = [{id: '_id', desc: true}];

    // TODO: handle forms with over 5000 results
    dataInterface.getSubmissions(this.props.asset.uid, 5000, 0, sort, fq).done((data) => {
      this.setState({submissions: data});
      this.buildMarkers(map);
      this.buildHeatMap(map);
    }).fail((error)=>{
      if (error.responseText)
        this.setState({error: error.responseText, loading: false});
      else if (error.statusText)
        this.setState({error: error.statusText, loading: false});
      else
        this.setState({error: t('Error: could not load data.'), loading: false});
    });
  } 

  calculateClusterRadius(zoom) {
   if(zoom >=12) {return 12;}
   return 20;
  }

  buildMarkers(map) {
    var _this = this;
    var prepPoints = [];
    var icon = L.divIcon({
      className: 'map-marker',
      iconSize: [20, 20],
    });

    var viewby = this.props.viewby || undefined;

    if (viewby) {
      var mapMarkers = this.prepFilteredMarkers(this.state.submissions, this.props.viewby);
      var mM = [], lbl = undefined;
      let choices = this.props.asset.content.choices,
          survey = this.props.asset.content.survey;

      let q = survey.find(z => z.name === viewby || z.$autoname === viewby);

      Object.keys(mapMarkers).map(function(m, i) {
        if (q && q.type == 'select_one') {
          lbl = choices.find(o => o.list_name === q.select_from_list_name && (o.name === m || o.$autoname === m));
        }
        mM.push({
          count: mapMarkers[m].count,
          id: mapMarkers[m].id,
          labels: lbl ? lbl.label : undefined,
          value: m != "undefined" ? m : undefined
        });
      });

      mM.sort(function(a, b) {
        return a.count - b.count;
      }).reverse();
      this.setState({markerMap: mM});
{'fraction_non_alphanumeric': 0.16060214259327668, 'fraction_numerical': 0.005910602142593277, 'mean_word_length': 2.889727011494253, 'pattern_counts': {'":': 8, '<': 27, '<?xml version=': 0, '>': 38, 'https://': 14, 'lorem ipsum': 0, 'www.': 6, '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': '5154387', 'n_tokens_mistral': 3735, 'n_tokens_neox': 3562, 'n_words': 750}