{"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":""}