{"version":3,"file":"js/effort-locations-map-8b11a2f9728f344fc612.chunk.js","mappings":"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","sources":["webpack://agra/./app/javascript/components/maplibre-map.vue","webpack://agra/./app/javascript/components/maplibre-map.vue?c361","webpack://agra/./app/javascript/phoenix/efforts/locations-map.vue","webpack://agra/./app/javascript/phoenix/efforts/locations-map.vue?3b26","webpack://agra/./node_modules/vue-loader/dist/exportHelper.js","webpack://agra/./app/javascript/helpers/super-boundary-box.js"],"sourcesContent":["<template>\n  <div :id=\"mapWrapperId\" class=\"map-wrapper\" dir=\"ltr\">\n    <!-- We are setting the direction to ltr, regardless of the direction of the rest of the content,\n         to ensure that maplibre's CSS around positioning and popups works correctly. -->\n    <slot :map=\"map\" />\n  </div>\n</template>\n\n<script>\nimport { GeolocateControl, Map, NavigationControl, setRTLTextPlugin } from 'maplibre-gl'\nimport 'maplibre-gl/dist/maplibre-gl.css'\n\nconst DEFAULT_GEOAPIFY_STYLE = 'https://api-eu.geoapify.com/v1/styles/klokantech-basic/style.json'\n\nexport default {\n  props: {\n    bounds: {\n      type: Array,\n      required: true\n    },\n    center: {\n      type: Object,\n      required: false,\n      default: () => { return  { lat: 0, lng: 0 } }\n    },\n    initialZoom: {\n      type: Number,\n      required: false\n    },\n    mapWrapperId: {\n      type: String,\n      required: false,\n      default: 'map'\n    },\n    maxZoom: {\n      type: Number,\n      required: false\n    },\n    navigationOptions: {\n      type: Object,\n      required: false,\n      default: () => ({})\n    },\n    showGeolocateControl: {\n      type: Boolean,\n      required: false,\n      default: false\n    },\n    style: {\n      type: String,\n      required: false\n    }\n  },\n\n  emits: ['loaded'],\n\n  data() {\n    return {\n      map: null\n    }\n  },\n\n  computed: {\n    defaultStyle() {\n      switch (this.agraConfiguration.mapTilesProvider.kind) {\n      case 'aws_location_service':\n        return `https://maps.geo.${this.agraConfiguration.awsRegion}.amazonaws.com/maps/v0/maps/esri_navigation/style-descriptor`\n      case 'geoapify':\n        return DEFAULT_GEOAPIFY_STYLE\n      default:\n        return null\n      }\n    },\n\n    mapOptions() {\n      return {\n        bounds: this.bounds,\n        center: this.center,\n        container: 'map',\n        maxZoom: this.maxZoom,\n        style: this.style || this.defaultStyle,\n        transformRequest: this.mapStyleUrlTransformFunction,\n        zoom: this.initialZoom || this.maxZoom || 0\n      }\n    },\n\n    mapStyleUrlTransformFunction() {\n      switch (this.agraConfiguration.mapTilesProvider.kind) {\n      case 'aws_location_service': {\n        const apiKey = this.agraConfiguration.mapTilesProvider.clientApiToken\n        return function(url) {\n          const urlObj = new URL(url)\n          urlObj.searchParams.set('key', apiKey)\n          return { url: urlObj.toString() }\n        }\n      }\n      case 'geoapify': {\n        // Use this method to plug the API key into the style URL\n        const apiKey = this.agraConfiguration.mapTilesProvider.clientApiToken\n        return function(url) {\n          const urlObj = new URL(url)\n          urlObj.searchParams.set('apiKey', apiKey)\n          return { url: urlObj.toString() }\n        }\n      }\n      default:\n        return function(url) {\n          return { url }\n        }\n      }\n    }\n  },\n\n  mounted() {\n    this.map = new Map(this.mapOptions)\n\n    let nav = new NavigationControl(this.navigationOptions)\n    this.map.addControl(nav, 'top-right')\n\n    if (this.showGeolocateControl) {\n      let geolocate = new GeolocateControl()\n      this.map.addControl(geolocate, 'top-right')\n    }\n\n    this.map.on('load', () => {\n      this.setMapLanguage()\n      this.$emit('loaded', {map: this.map})\n    })\n  },\n\n  methods: {\n    setMapLanguage() {\n      if (this.i18n.isRtl()) {\n        // Load the plugin so that RTL text labels on the map are displayed in the right direction.\n        // This is the approach recommended in https://maplibre.org/maplibre-gl-js/docs/examples/mapbox-gl-rtl-text/\n        // Q: Could we install https://github.com/mapbox/mapbox-gl-rtl-text instead of passing a string here?\n        // A: Sadly, it seems setRTLTextPlugin can only handle a URL; there doesn't seem to be any way to hook it up\n        //    to a yarn package.\n        setRTLTextPlugin('https://unpkg.com/@mapbox/mapbox-gl-rtl-text@0.2.3/mapbox-gl-rtl-text.js', false)\n      }\n\n      const desiredLanguage = this.i18n.locale().split('-')[0] // if locale is e.g., de-CH, we ignore '-CH'\n\n      // For both map providers, we're going to set properties on relevant map layers to specify\n      // what language should be used.\n      let layers = this.map.getStyle().layers\n\n      // AWS Location Service and Geoapify have different syntax for specifying the language on a layer.\n      switch (this.agraConfiguration.mapTilesProvider.kind) {\n      case 'aws_location_service': {\n        const layoutLayers = layers.filter((layer) => layer.layout && layer.layout['text-field'] && ['{_name_global}', '{_name}'].includes(layer.layout['text-field']))\n        for (let layer of layoutLayers) {\n          this.map.setLayoutProperty(layer.id, 'text-field', ['case', ['has', `_name_${desiredLanguage}`],\n                                                              ['get', `_name_${desiredLanguage}`],\n                                                              ['get', '_name']])\n        }\n        return\n      }\n      case 'geoapify': {\n        let labelLayers = layers.filter((layer) => layer.type === 'symbol')\n        for (let layer of labelLayers) {\n          // See https://www.geoapify.com/map-language-localize-labels-on-the-map for discussion of this syntax.\n          this.map.setLayoutProperty(layer.id, 'text-field', ['case', ['has', `name:${desiredLanguage}`],\n                                                              ['get', `name:${desiredLanguage}`],\n                                                              ['get', 'name:latin']])\n        }\n        return\n      }\n      }\n    }\n  }\n}\n</script>\n\n<style scoped lang=\"scss\">\n.map-wrapper {\n  height: 100%;\n  width: 100%;\n}\n</style>\n","import { render } from \"./maplibre-map.vue?vue&type=template&id=04adf530&scoped=true\"\nimport script from \"./maplibre-map.vue?vue&type=script&lang=js\"\nexport * from \"./maplibre-map.vue?vue&type=script&lang=js\"\n\nimport \"./maplibre-map.vue?vue&type=style&index=0&id=04adf530&scoped=true&lang=scss\"\n\nimport exportComponent from \"../../../node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__scopeId',\"data-v-04adf530\"]])\n\nexport default __exports__","<template>\n  <div class=\"dynamic-map\">\n    <maplibre-map ref=\"map\" :bounds=\"initialBounds\" :max-zoom=\"15\" :show-geolocate-control=\"true\" @loaded=\"onMapLoaded\" />\n  </div>\n</template>\n\n<script>\nimport ajax from '../../helpers/ajax'\nimport { LngLatBounds } from 'maplibre-gl'\nimport MaplibreMap from '@/components/maplibre-map'\nimport { urlParamsWithNamespace, urlWithParams } from '../../helpers/url-params'\nimport {MIN_LATITUDE_EARTH, MAX_LATITUDE_EARTH, MIN_LONGITUDE_EARTH, MAX_LONGITUDE_EARTH} from '@/helpers/super-boundary-box'\n\nconst LOCATIONS_SOURCE_NAME = 'locations'\nconst MAP_LAYER_NAME_CLUSTERS = 'clusters'\nconst MAP_LAYER_NAME_CLUSTER_COUNTS = 'cluster-counts'\nconst MAP_LAYER_NAME_UNCLUSTERED_POINTS = 'unclustered-points'\n\nexport default {\n  components: { MaplibreMap },\n\n  props: {\n    effortSlug: {\n      type: String,\n      required: true\n    },\n    extraUrlParams: {\n      type: Object,\n      required: false,\n      default: () => {}\n    },\n    initialBounds: {\n      type: Array,\n      required: false,\n      default: () => [{lat: MIN_LATITUDE_EARTH, lng: MIN_LONGITUDE_EARTH}, {lat: MAX_LATITUDE_EARTH, lng: MAX_LONGITUDE_EARTH}]\n    }\n  },\n\n  data() {\n    return {\n      accentColor: null,\n      bounds: null,\n      loaded: false,\n      locations: [],\n      mapGl: null,\n      secondaryAccentColor: null\n    }\n  },\n\n  computed: {\n    geoJsonPoints() {\n      if (!this.locations) {\n        return []\n      }\n\n      return {\n        type: 'FeatureCollection',\n        features: this.locations.map(l => ({\n          type: 'Feature',\n          properties: {\n            name: l.query\n          },\n          geometry: {\n            type: 'Point',\n            coordinates: [l.longitude, l.latitude]\n          }\n        }))\n      }\n    },\n\n    locationsUrl() {\n      return `/efforts/${this.effortSlug}/locations`\n    }\n  },\n\n  created() {\n    const documentComputedStyle = getComputedStyle(document.documentElement)\n    this.accentColor = documentComputedStyle.getPropertyValue('--accent-color')\n    this.secondaryAccentColor = documentComputedStyle.getPropertyValue('--secondary-accent-color')\n    this.clusterTextColor = documentComputedStyle.getPropertyValue('--text-on-secondary-accent-color')\n  },\n\n  mounted() {\n    this.loadLocations()\n  },\n\n  methods: {\n    fitBounds() {\n      if (this.loaded && this.locations.length > 0) {\n        const initialCoordinates = [this.locations[0].longitude, this.locations[0].latitude]\n        const bounds = this.locations.reduce((bounds, location) => {\n          return bounds.extend([location.longitude, location.latitude])\n        }, new LngLatBounds(initialCoordinates, initialCoordinates))\n\n        this.mapGl.fitBounds(bounds, {padding: 30})\n      }\n    },\n\n    goToLocation(loc) {\n      const params = {...urlParamsWithNamespace(loc, 'location'), ...this.extraUrlParams}\n      window.location = urlWithParams(`/efforts/${this.effortSlug}/near`, params)\n    },\n\n    initializeMapPointsLayer() {\n      this.mapGl.addSource(LOCATIONS_SOURCE_NAME, {\n        type: 'geojson',\n        data: this.geoJsonPoints,\n        cluster: true,\n        clusterMaxZoom: 14, // Max zoom to cluster points on\n        clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)\n      })\n\n      // Add a layer showing the places as clusters\n      this.mapGl.addLayer({\n        id: MAP_LAYER_NAME_CLUSTERS,\n        type: 'circle',\n        source: LOCATIONS_SOURCE_NAME,\n        filter: ['has', 'point_count'],\n        paint: {\n          'circle-radius': [\n            'step',\n            ['get', 'point_count'],\n            20,\n            100,\n            30,\n            750,\n            40\n          ],\n          'circle-color': this.secondaryAccentColor,\n          'circle-stroke-color': 'white',\n          'circle-stroke-width': 2,\n          'circle-opacity': 1\n        }\n      })\n\n      // Add a layer showing the counts of the clusters\n      this.mapGl.addLayer({\n        id: MAP_LAYER_NAME_CLUSTER_COUNTS,\n        type: 'symbol',\n        source: LOCATIONS_SOURCE_NAME,\n        filter: ['has', 'point_count'],\n        layout: {\n          'text-field': ['get', 'point_count_abbreviated'],\n          'text-font': ['Noto Sans Regular'],\n          'text-size': 12\n        },\n        paint: {\n          'text-color': this.clusterTextColor\n        }\n      })\n\n      // Add a final layer for showing the unclustered points\n      this.mapGl.addLayer({\n        id: MAP_LAYER_NAME_UNCLUSTERED_POINTS,\n        type: 'circle',\n        source: LOCATIONS_SOURCE_NAME,\n        filter: ['!', ['has', 'point_count']],\n        paint: {\n          'circle-radius': 5,\n          'circle-color': this.accentColor,\n          'circle-stroke-color': 'white',\n          'circle-stroke-width': 2,\n          'circle-opacity': 1\n        }\n      })\n\n      // inspect a cluster on click\n      this.mapGl.on('click', MAP_LAYER_NAME_CLUSTERS, e => {\n        const features = this.mapGl.queryRenderedFeatures(e.point, {\n          layers: [MAP_LAYER_NAME_CLUSTERS]\n        })\n        const clusterId = features[0].properties.cluster_id\n        this.mapGl.getSource(LOCATIONS_SOURCE_NAME).getClusterExpansionZoom(\n          clusterId,\n          (err, zoom) => {\n            if (err) return\n\n            this.mapGl.easeTo({\n              center: features[0].geometry.coordinates,\n              zoom\n            })\n          }\n        )\n      })\n\n      // When a click event occurs on a feature in the unclustered-point layer,\n      // navigate to the petition page for that location\n      this.mapGl.on('click', MAP_LAYER_NAME_UNCLUSTERED_POINTS, e => {\n        const coordinates = e.features[0].geometry.coordinates\n        this.goToLocation({longitude: coordinates[0], latitude: coordinates[1]})\n      })\n\n      // Show a pointer cursor when hovering over clustered / unclustered markers\n      const map = this.mapGl\n      const layers = [MAP_LAYER_NAME_CLUSTERS, MAP_LAYER_NAME_UNCLUSTERED_POINTS]\n      layers.forEach(layerName => {\n        map.on('mousemove', layerName, () => {\n          map.getCanvas().style.cursor = 'pointer'\n        })\n        map.on('mouseleave', layerName, () => {\n          map.getCanvas().style.cursor = ''\n        })\n      })\n    },\n\n    onMapLoaded({map}) {\n      this.loaded = true\n      this.mapGl = map\n      this.initializeMapPointsLayer()\n      this.fitBounds()\n    },\n\n    loadLocations() {\n      ajax.get({\n        url: this.locationsUrl,\n        successHandler: (resp) => {\n          this.locations = resp\n          this.loaded = true\n        }\n      })\n    }\n  }\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.dynamic-map {\n  height: 420px;\n  width: 100%;\n\n  ::v-deep(img) {\n    max-width: none;\n  }\n}\n</style>\n","import { render } from \"./locations-map.vue?vue&type=template&id=108fb0f8&scoped=true\"\nimport script from \"./locations-map.vue?vue&type=script&lang=js\"\nexport * from \"./locations-map.vue?vue&type=script&lang=js\"\n\nimport \"./locations-map.vue?vue&type=style&index=0&id=108fb0f8&lang=scss&scoped=true\"\n\nimport exportComponent from \"../../../../node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__scopeId',\"data-v-108fb0f8\"]])\n\nexport default __exports__","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n// runtime helper for setting properties on components\n// in a tree-shakable way\nexports.default = (sfc, props) => {\n    const target = sfc.__vccOpts || sfc;\n    for (const [key, val] of props) {\n        target[key] = val;\n    }\n    return target;\n};\n","export const MIN_LATITUDE_EARTH = -90\nexport const MAX_LATITUDE_EARTH = 90\nexport const MIN_LONGITUDE_EARTH = -180\nexport const MAX_LONGITUDE_EARTH = 180\n\nexport default function computeSuperBoundaryBox(boxA, boxB) {\n  // Here, given two sets of boundaries, both nullable,\n  // we compute a the smallest superset of boundaries that contains each non-null set.\n  // If both sets are null, we default to a superset that includes the entire map.\n  // Boundary sets are expected to be objects with keys: minLatitude, maxLatitude, minLongitude, maxLongitude\n  if (!boxA && !boxB) {\n    return {\n      minLatitude: MIN_LATITUDE_EARTH,\n      maxLatitude: MAX_LATITUDE_EARTH,\n      minLongitude: MIN_LONGITUDE_EARTH,\n      maxLongitude: MAX_LONGITUDE_EARTH\n    }\n  }\n  if (!boxA) {\n    return boxB\n  }\n  if (!boxB) {\n    return boxA\n  }\n  return {\n    minLatitude: Math.min(boxA.minLatitude, boxB.minLatitude),\n    maxLatitude: Math.max(boxA.maxLatitude, boxB.maxLatitude),\n    minLongitude: Math.min(boxA.minLongitude, boxB.minLongitude),\n    maxLongitude: Math.max(boxA.maxLongitude, boxB.maxLongitude)\n  }\n}\n"],"names":["props","bounds","type","Array","required","center","Object","default","lat","lng","initialZoom","Number","mapWrapperId","String","maxZoom","navigationOptions","showGeolocateControl","Boolean","style","emits","data","map","computed","defaultStyle","this","agraConfiguration","mapTilesProvider","kind","awsRegion","mapOptions","container","transformRequest","mapStyleUrlTransformFunction","zoom","apiKey","clientApiToken","url","urlObj","URL","searchParams","set","toString","mounted","Map","nav","NavigationControl","addControl","geolocate","GeolocateControl","on","setMapLanguage","$emit","methods","i18n","isRtl","setRTLTextPlugin","desiredLanguage","locale","split","layers","getStyle","layoutLayers","filter","layer","layout","includes","setLayoutProperty","id","labelLayers","_createElementBlock","$props","class","dir","_renderSlot","_ctx","$slots","$data","undefined","_hoisted_1","LOCATIONS_SOURCE_NAME","MAP_LAYER_NAME_CLUSTERS","MAP_LAYER_NAME_UNCLUSTERED_POINTS","components","MaplibreMap","effortSlug","extraUrlParams","initialBounds","MIN_LATITUDE_EARTH","MIN_LONGITUDE_EARTH","MAX_LATITUDE_EARTH","MAX_LONGITUDE_EARTH","accentColor","loaded","locations","mapGl","secondaryAccentColor","geoJsonPoints","features","l","properties","name","query","geometry","coordinates","longitude","latitude","locationsUrl","created","documentComputedStyle","getComputedStyle","document","documentElement","getPropertyValue","clusterTextColor","loadLocations","fitBounds","length","initialCoordinates","reduce","location","extend","LngLatBounds","padding","goToLocation","loc","params","urlParamsWithNamespace","window","urlWithParams","initializeMapPointsLayer","addSource","cluster","clusterMaxZoom","clusterRadius","addLayer","source","paint","e","queryRenderedFeatures","point","clusterId","cluster_id","getSource","getClusterExpansionZoom","err","easeTo","forEach","layerName","getCanvas","cursor","onMapLoaded","ajax","get","successHandler","resp","_createVNode","_component_maplibre_map","ref","onLoaded","$options","exports","sfc","target","__vccOpts","key","val","computeSuperBoundaryBox","boxA","boxB","minLatitude","Math","min","maxLatitude","max","minLongitude","maxLongitude"],"sourceRoot":""}