diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..770ad899 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,17 @@ +Implements _Jira issue link_ + +Relates to _maps-app PR_ + +--- + +### Description + +_text_ + +--- + +### TODO + +- [ ] Tests added +- [ ] PRs for Maps app created +- [ ] _todo_ diff --git a/.github/workflows/check-tasklist.yml b/.github/workflows/check-tasklist.yml new file mode 100644 index 00000000..9620c687 --- /dev/null +++ b/.github/workflows/check-tasklist.yml @@ -0,0 +1,14 @@ +name: GitHub Task List Checker +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +jobs: + task-list-checker: + if: ${{ github.actor != 'dependabot[bot]' }} + runs-on: ubuntu-latest + steps: + - name: Check for incomplete task list items + uses: Shopify/task-list-checker@main + with: + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.hooks/commit-msg b/.hooks/commit-msg new file mode 100755 index 00000000..9975a818 --- /dev/null +++ b/.hooks/commit-msg @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +yarn d2-style check commit "$1" diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..dc378dba --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +src/earthengine/ee_api_js_worker.js diff --git a/.prettierrc.js b/.prettierrc.js index 0ea40ae5..4ae21dd3 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -2,20 +2,12 @@ const { config } = require('@dhis2/cli-style') module.exports = { ...require(config.prettier), - printWidth: 80, - tabWidth: 4, - useTabs: false, - semi: false, - singleQuote: true, - trailingComma: 'es5', - bracketSpacing: true, - bracketSameLine: false, - jsxSingleQuote: false, - arrowParens: 'avoid', - rangeStart: 0, - rangeEnd: Infinity, - proseWrap: 'preserve', - requirePragma: false, - insertPragma: false, - endOfLine: 'lf', + overrides: [ + { + files: 'pull_request_template.md', + options: { + tabWidth: 2, + }, + }, + ], } diff --git a/src/Map.js b/src/Map.js index b341bc2b..bac1878c 100644 --- a/src/Map.js +++ b/src/Map.js @@ -1,18 +1,18 @@ import { Evented, Map } from 'maplibre-gl' import 'maplibre-gl/dist/maplibre-gl.css' -import Layer from './layers/Layer' -import layerTypes from './layers/layerTypes' -import controlTypes from './controls/controlTypes' -import controlsLocale from './controls/controlsLocale' -import MultiTouch from './controls/MultiTouch' -import { transformRequest } from './utils/images' -import { mapStyle } from './utils/style' -import { getBoundsFromLayers } from './utils/geometry' -import syncMaps from './utils/sync' -import { getFeaturesString } from './utils/core' -import { OVERLAY_START_POSITION } from './utils/layers' -import Popup from './ui/Popup' -import Label from './ui/Label' +import controlsLocale from './controls/controlsLocale.js' +import controlTypes from './controls/controlTypes.js' +import MultiTouch from './controls/MultiTouch.js' +import Layer from './layers/Layer.js' +import layerTypes from './layers/layerTypes.js' +import Label from './ui/Label.js' +import Popup from './ui/Popup.js' +import { getFeaturesString } from './utils/core.js' +import { getBoundsFromLayers } from './utils/geometry.js' +import { transformRequest } from './utils/images.js' +import { OVERLAY_START_POSITION } from './utils/layers.js' +import { mapStyle } from './utils/style.js' +import syncMaps from './utils/sync.js' import './Map.css' const renderedClass = 'dhis2-map-rendered' @@ -51,7 +51,7 @@ export class MapGL extends Evented { // Translate strings if (locale) { - Object.keys(mapgl._locale).forEach(id => { + Object.keys(mapgl._locale).forEach((id) => { const str = mapgl._locale[id] if (locale[str]) { mapgl._locale[id] = locale[str] @@ -130,7 +130,7 @@ export class MapGL extends Evented { } async removeLayer(layer) { - this._layers = this._layers.filter(l => l !== layer) + this._layers = this._layers.filter((l) => l !== layer) await layer.removeFrom(this) @@ -173,7 +173,7 @@ export class MapGL extends Evented { } hasLayer(layer) { - return !!this._layers.find(l => l === layer) + return !!this._layers.find((l) => l === layer) } addControl(config) { @@ -223,7 +223,7 @@ export class MapGL extends Evented { this.fire('ready', this) } - onClick = evt => { + onClick = (evt) => { const eventObj = this._createClickEvent(evt) const { feature } = eventObj @@ -238,7 +238,7 @@ export class MapGL extends Evented { this.fire('click', eventObj) } - onContextMenu = evt => { + onContextMenu = (evt) => { const eventObj = this._createClickEvent(evt) if (eventObj.feature) { @@ -249,7 +249,7 @@ export class MapGL extends Evented { } } - onMouseMove = evt => { + onMouseMove = (evt) => { const feature = this.getEventFeature(evt) let layer @@ -280,7 +280,7 @@ export class MapGL extends Evented { // Add rendered class if map is idle onIdle = () => { - if (this.getLayers().some(layer => layer._isLoading)) { + if (this.getLayers().some((layer) => layer._isLoading)) { return } @@ -296,7 +296,7 @@ export class MapGL extends Evented { ) { if (this._hoverFeatures) { // Clear state for existing hover features - this._hoverFeatures.forEach(feature => + this._hoverFeatures.forEach((feature) => this.setFeatureState(feature, { hover: false }) ) this._hoverFeatures = null @@ -304,7 +304,7 @@ export class MapGL extends Evented { if (Array.isArray(features)) { this._hoverFeatures = features - features.forEach(feature => + features.forEach((feature) => this.setFeatureState(feature, { hover: true }) ) } @@ -323,7 +323,7 @@ export class MapGL extends Evented { onMouseOut = () => this.hideLabel() - onError = evt => { + onError = (evt) => { // TODO: Use optional chaining when DHIS2 Maps 2.35 is not supported if (evt && evt.error && evt.error.message && console && console.error) { const { message } = evt.error @@ -343,8 +343,8 @@ export class MapGL extends Evented { // TODO: throttle? getEventFeature(evt) { const layers = this.getLayers() - .filter(l => l.isInteractive()) - .map(l => l.getInteractiveIds()) + .filter((l) => l.isInteractive()) + .map((l) => l.getInteractiveIds()) .reduce((out, ids) => [...out, ...ids], []) let feature @@ -358,7 +358,7 @@ export class MapGL extends Evented { } getLayerFromId(id) { - return this._layers.find(layer => layer.hasLayerId(id)) + return this._layers.find((layer) => layer.hasLayerId(id)) } getLayerAtIndex(index) { @@ -396,7 +396,7 @@ export class MapGL extends Evented { return this._beforeId && this.getMapGL() .getStyle() - .layers.find(layer => layer.id === this._beforeId) + .layers.find((layer) => layer.id === this._beforeId) ? this._beforeId : undefined } diff --git a/src/controls/Measure.js b/src/controls/Measure.js index d7a34285..7e8e9811 100644 --- a/src/controls/Measure.js +++ b/src/controls/Measure.js @@ -1,9 +1,9 @@ -import turfLength from '@turf/length' import turfArea from '@turf/area' import bbox from '@turf/bbox' +import turfLength from '@turf/length' import { createElement } from '../utils/dom' -import { numberPrecision, kmToMiles } from '../utils/numbers' import { featureCollection } from '../utils/geometry' +import { numberPrecision, kmToMiles } from '../utils/numbers' import './Measure.css' // Inspired by https://github.com/ljagis/leaflet-measure @@ -235,7 +235,9 @@ class MeasureControl { _finishMeasure = () => { const mapgl = this._map.getMapGL() const geojson = this._geojson - const points = geojson.features.filter(f => f.geometry.type === 'Point') + const points = geojson.features.filter( + (f) => f.geometry.type === 'Point' + ) const locale = this.locale const numFormat = this._numFormat @@ -243,11 +245,11 @@ class MeasureControl { return this._endMeasure() } else if (points.length > 2) { const lineIndex = geojson.features.findIndex( - f => f === this._linestring + (f) => f === this._linestring ) this._linestring.geometry.coordinates = [ - ...points.map(point => point.geometry.coordinates), + ...points.map((point) => point.geometry.coordinates), points[0].geometry.coordinates, ] @@ -328,12 +330,12 @@ class MeasureControl { this._isActive ? this._startMeasure() : this._endMeasure() } - _onMapClick = evt => { + _onMapClick = (evt) => { const mapgl = this._map.getMapGL() const geojson = this._geojson const locale = this.locale const numFormat = this._numFormat - let points = geojson.features.filter(f => f.geometry.type === 'Point') + let points = geojson.features.filter((f) => f.geometry.type === 'Point') const clikedFeature = mapgl.queryRenderedFeatures(evt.point, { layers: ['measure-points'], @@ -342,7 +344,7 @@ class MeasureControl { // If a feature was clicked, remove it from the map if (clikedFeature) { const { id } = clikedFeature.properties - points = points.filter(p => p.properties.id !== id) + points = points.filter((p) => p.properties.id !== id) } else { points = [ ...points, @@ -367,7 +369,7 @@ class MeasureControl { ) } else { this._linestring.geometry.coordinates = points.map( - point => point.geometry.coordinates + (point) => point.geometry.coordinates ) geojson.features.push(this._linestring) @@ -393,7 +395,7 @@ class MeasureControl { if (points.length > 2) { this._polygon.geometry.coordinates = [ [ - ...points.map(point => point.geometry.coordinates), + ...points.map((point) => point.geometry.coordinates), points[0].geometry.coordinates, ], ] @@ -421,7 +423,7 @@ class MeasureControl { mapgl.getSource('measure').setData(geojson) } - _onMouseMove = evt => { + _onMouseMove = (evt) => { const mapgl = this._map.getMapGL() const features = mapgl.queryRenderedFeatures(evt.point, { @@ -438,7 +440,7 @@ class MeasureControl { const mapgl = this._map.getMapGL() const layers = ['measure-points', 'measure-line', 'measure-polygon'] - layers.forEach(layer => { + layers.forEach((layer) => { if (mapgl.getLayer(layer)) { mapgl.moveLayer(layer) } diff --git a/src/controls/MultiTouch.js b/src/controls/MultiTouch.js index 10653db1..37834946 100644 --- a/src/controls/MultiTouch.js +++ b/src/controls/MultiTouch.js @@ -20,7 +20,7 @@ class MultiTouch { let x = 0 let y = 0 - ;[].forEach.call(event.touches, touch => { + ;[].forEach.call(event.touches, (touch) => { x += touch.screenX y += touch.screenY }) @@ -44,7 +44,7 @@ class MultiTouch { let x = 0 let y = 0 - ;[].forEach.call(event.touches, touch => { + ;[].forEach.call(event.touches, (touch) => { x += touch.screenX y += touch.screenY }) diff --git a/src/controls/Search.js b/src/controls/Search.js index fdd1518a..656564d1 100644 --- a/src/controls/Search.js +++ b/src/controls/Search.js @@ -26,9 +26,9 @@ class SearchControl { const urlParams = new URLSearchParams(Object.entries(params)) return fetch(`https://nominatim.openstreetmap.org/search?${urlParams}`) - .then(response => (response.ok ? response.json() : [])) - .then(json => - json.map(result => { + .then((response) => (response.ok ? response.json() : [])) + .then((json) => + json.map((result) => { const { display_name: name, lon: lng, @@ -88,7 +88,7 @@ class SearchControl { filter: false, limit: this.options.limit, }) - this._typeahead.getItemValue = item => item.name + this._typeahead.getItemValue = (item) => item.name this._collapseSearchControl() @@ -102,7 +102,7 @@ class SearchControl { } // Clear search list when input field is changing - _onKeyDown = evt => + _onKeyDown = (evt) => setTimeout(() => { const { selected } = this._typeahead @@ -140,7 +140,7 @@ class SearchControl { this._loadingEl.style.display = 'block' this.geocodeRequest(searchInput, this._map.getBounds(), this.options) - .then(results => { + .then((results) => { let items = results this._loadingEl.style.display = 'none' @@ -162,7 +162,7 @@ class SearchControl { .catch(() => (this._loadingEl.style.display = 'none')) } - _clear = evt => { + _clear = (evt) => { if (evt) { evt.preventDefault() } diff --git a/src/controls/controlTypes.js b/src/controls/controlTypes.js index 16c68b80..0591c95e 100644 --- a/src/controls/controlTypes.js +++ b/src/controls/controlTypes.js @@ -1,10 +1,10 @@ import { ScaleControl } from 'maplibre-gl' import Attribution from './Attribution' -import Navigation from './Navigation' -import Search from './Search' -import Measure from './Measure' import FitBounds from './FitBounds' import Fullscreen from './Fullscreen' +import Measure from './Measure' +import Navigation from './Navigation' +import Search from './Search' import './Controls.css' export default { diff --git a/src/earthengine/__tests__/ee_worker_utils.spec.js b/src/earthengine/__tests__/ee_worker_utils.spec.js index 0f77f06c..cddbce78 100644 --- a/src/earthengine/__tests__/ee_worker_utils.spec.js +++ b/src/earthengine/__tests__/ee_worker_utils.spec.js @@ -56,9 +56,9 @@ const data = { } const sum = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 // Sum of histogram values -const toPercent = v => (v / sum) * 100 -const toHectares = v => Math.round((v * (scale * scale)) / 10000) -const toAcres = v => Math.round((v * (scale * scale)) / 4046.8564224) +const toPercent = (v) => (v / sum) * 100 +const toHectares = (v) => Math.round((v * (scale * scale)) / 10000) +const toAcres = (v) => Math.round((v * (scale * scale)) / 4046.8564224) describe('earthengine', () => { it('Should return true if unit is class based', () => { @@ -70,7 +70,7 @@ describe('earthengine', () => { it('Should calculate percentage', () => { const aggregationType = 'percentage' - const ids = data.features.map(f => f.id) + const ids = data.features.map((f) => f.id) const result = getHistogramStatistics({ data, diff --git a/src/earthengine/ee_worker.js b/src/earthengine/ee_worker.js index ba933f3b..e56b1e02 100644 --- a/src/earthengine/ee_worker.js +++ b/src/earthengine/ee_worker.js @@ -35,14 +35,14 @@ class EarthEngineWorker { } // Set EE API auth token if needed and run ee.initialize - static setAuthToken = getAuthToken => + static setAuthToken = (getAuthToken) => new Promise((resolve, reject) => { if (ee.data.getAuthToken()) { // Already authenticated ee.initialize(null, null, resolve, reject) } else { getAuthToken() - .then(token => { + .then((token) => { const { client_id, tokenType = 'Bearer', @@ -92,7 +92,7 @@ class EarthEngineWorker { const { data, buffer } = this.options if (Array.isArray(data) && !this.eeFeatureCollection) { this.eeFeatureCollection = ee.FeatureCollection( - data.map(feature => ({ + data.map((feature) => ({ ...feature, id: feature.properties.id, // EE requires id to be string, MapLibre integer // Translate points to buffer polygons @@ -199,7 +199,7 @@ class EarthEngineWorker { ) } - dataset.getMap(null, response => + dataset.getMap(null, (response) => resolve(response.urlFormat) ) @@ -221,7 +221,7 @@ class EarthEngineWorker { eeImage .visualize(params) - .getMap(null, response => resolve(response.urlFormat)) + .getMap(null, (response) => resolve(response.urlFormat)) break } @@ -311,7 +311,7 @@ class EarthEngineWorker { dataset = applyFilter(dataset, filter) const aggFeatures = collection - .map(feature => { + .map((feature) => { feature = ee.Feature(feature) const count = dataset .filterBounds(feature.geometry()) @@ -336,7 +336,7 @@ class EarthEngineWorker { tileScale, }) .select(['histogram'], null, false) - ).then(data => + ).then((data) => getHistogramStatistics({ data, scale: scaleValue, @@ -363,8 +363,8 @@ class EarthEngineWorker { tileScale, }) - band.forEach(band => - aggregationType.forEach(type => + band.forEach((band) => + aggregationType.forEach((type) => props.push( aggregationType.length === 1 ? band @@ -389,7 +389,7 @@ class EarthEngineWorker { // Service Worker not supported in Safari if (typeof onconnect !== 'undefined') { // eslint-disable-next-line no-undef - onconnect = evt => expose(EarthEngineWorker, evt.ports[0]) + onconnect = (evt) => expose(EarthEngineWorker, evt.ports[0]) } else { expose(EarthEngineWorker) } diff --git a/src/earthengine/ee_worker_loader.js b/src/earthengine/ee_worker_loader.js index a0d981ac..2ba70169 100644 --- a/src/earthengine/ee_worker_loader.js +++ b/src/earthengine/ee_worker_loader.js @@ -3,7 +3,7 @@ import { wrap, proxy } from 'comlink' let resolvedWorker // Return same worker if already authenticated -const getEarthEngineWorker = getAuthToken => +const getEarthEngineWorker = (getAuthToken) => new Promise((resolve, reject) => { if (resolvedWorker) { resolve(resolvedWorker) diff --git a/src/earthengine/ee_worker_utils.js b/src/earthengine/ee_worker_utils.js index 84fc108a..d5b86e1c 100644 --- a/src/earthengine/ee_worker_utils.js +++ b/src/earthengine/ee_worker_utils.js @@ -1,14 +1,14 @@ -import ee from './ee_api_js_worker' import { squareMetersToHectares, squareMetersToAcres } from '../utils/numbers' +import ee from './ee_api_js_worker' const classAggregation = ['percentage', 'hectares', 'acres'] const DEFAULT_MASK_VALUE = 0 -export const hasClasses = type => classAggregation.includes(type) +export const hasClasses = (type) => classAggregation.includes(type) // Makes evaluate a promise -export const getInfo = instance => +export const getInfo = (instance) => new Promise((resolve, reject) => instance.evaluate((data, error) => { if (error) { @@ -38,7 +38,7 @@ export const combineReducers = (types, unweighted) => ) // Returns the linear scale in meters of the units of this projection -export const getScale = image => image.select(0).projection().nominalScale() +export const getScale = (image) => image.select(0).projection().nominalScale() // Returns histogram data (e.g. landcover) in percentage, hectares or acres export const getHistogramStatistics = ({ @@ -76,7 +76,7 @@ export const getHistogramStatistics = ({ }, {}) // Reduce a feature collection to an object of properties -export const getFeatureCollectionProperties = data => +export const getFeatureCollectionProperties = (data) => data.features.reduce( (obj, f) => ({ ...obj, @@ -102,14 +102,14 @@ export const getClassifiedImage = ( if (Array.isArray(style)) { return { eeImage: eeImage.remap({ - from: style.map(s => s.value), + from: style.map((s) => s.value), to: [...Array(style.length).keys()], bandName: band, }), params: { min: 0, max: style.length - 1, - palette: style.map(l => l.color).join(','), + palette: style.map((l) => l.color).join(','), }, } } else if (style.bands) { @@ -139,7 +139,7 @@ export const getClassifiedImage = ( export const applyFilter = (collection, filter = []) => { let filtered = collection - filter.forEach(f => { + filter.forEach((f) => { if (ee.Filter[f.type]) { filtered = filtered.filter( ee.Filter[f.type].apply(this, f.arguments) @@ -155,14 +155,14 @@ export const applyMethods = (eeImage, methods = []) => { let image = eeImage if (Array.isArray(methods)) { - methods.forEach(m => { + methods.forEach((m) => { if (image[m.name]) { image = image[m.name].apply(image, m.arguments) } }) } else { // Backward compatibility for format used before 2.40 - Object.keys(methods).forEach(m => { + Object.keys(methods).forEach((m) => { if (image[m]) { image = image[m].apply(image, methods[m]) } @@ -178,5 +178,5 @@ export const applyCloudMask = (collection, cloudScore) => { return collection .linkCollection(ee.ImageCollection(datasetId), [band]) - .map(img => img.updateMask(img.select(band).gte(clearThreshold))) + .map((img) => img.updateMask(img.select(band).gte(clearThreshold))) } diff --git a/src/index.js b/src/index.js index f0389a43..e52bf417 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ -import Map from './Map' -import supportedLayers from './layers/layerTypes' import supportedControls from './controls/controlTypes' import getEarthEngineWorker from './earthengine' +import supportedLayers from './layers/layerTypes' +import Map from './Map' import { getLabelPosition } from './utils/labels' /** diff --git a/src/layers/BingLayer.js b/src/layers/BingLayer.js index 7342bce3..9b7fd1fa 100644 --- a/src/layers/BingLayer.js +++ b/src/layers/BingLayer.js @@ -1,6 +1,6 @@ import fetchJsonp from 'fetch-jsonp' -import Layer from './Layer' import { bboxIntersect } from '../utils/geo' +import Layer from './Layer' import './BingLayer.css' // https://docs.microsoft.com/en-us/bingmaps/rest-services/directly-accessing-the-bing-maps-tiles @@ -14,7 +14,7 @@ class BingLayer extends Layer { this.setSource(this.getId(), { type: 'raster', tiles: imageUrlSubdomains.map( - subdomain => imageUrl.replace('{subdomain}', subdomain) // + '&dpi=d2&device=mobile' // TODO + (subdomain) => imageUrl.replace('{subdomain}', subdomain) // + '&dpi=d2&device=mobile' // TODO ), tileSize: 256, // default is 512 }) @@ -79,11 +79,11 @@ class BingLayer extends Layer { const metaDataUrl = `https://dev.virtualearth.net/REST/V1/Imagery/Metadata/${style}?output=json&include=ImageryProviders&culture=${culture}&key=${apiKey}&uriScheme=https` return fetchJsonp(metaDataUrl, { jsonpCallback: 'jsonp' }) - .then(response => response.json()) + .then((response) => response.json()) .then(this.onMetaDataLoad) } - onMetaDataLoad = metaData => { + onMetaDataLoad = (metaData) => { if (metaData.statusCode !== 200) { throw new Error( 'Bing Imagery Metadata error: \n' + @@ -122,7 +122,7 @@ class BingLayer extends Layer { ) ) - return providers.map(p => p.attribution).join(', ') + return providers.map((p) => p.attribution).join(', ') } updateAttribution = () => { diff --git a/src/layers/Boundary.js b/src/layers/Boundary.js index 48aeef70..9945cf42 100644 --- a/src/layers/Boundary.js +++ b/src/layers/Boundary.js @@ -1,5 +1,5 @@ -import Layer from './Layer' import { labelLayer } from '../utils/labels' +import Layer from './Layer' class Boundary extends Layer { constructor(options) { diff --git a/src/layers/Choropleth.js b/src/layers/Choropleth.js index 3a2b4793..5a03c5d6 100644 --- a/src/layers/Choropleth.js +++ b/src/layers/Choropleth.js @@ -1,6 +1,6 @@ -import Layer from './Layer' -import { pointLayer, polygonLayer, outlineLayer } from '../utils/layers' import { labelLayer } from '../utils/labels' +import { pointLayer, polygonLayer, outlineLayer } from '../utils/layers' +import Layer from './Layer' class Choropleth extends Layer { constructor(options) { diff --git a/src/layers/ClientCluster.js b/src/layers/ClientCluster.js index 7c97fc08..40df02ad 100644 --- a/src/layers/ClientCluster.js +++ b/src/layers/ClientCluster.js @@ -1,7 +1,7 @@ -import Cluster from './Cluster' import { featureCollection } from '../utils/geometry' import { clusterLayer, clusterCountLayer } from '../utils/layers' import { eventStrokeColor, clusterCountColor } from '../utils/style' +import Cluster from './Cluster' class ClientCluster extends Cluster { createSource() { @@ -55,7 +55,7 @@ class ClientCluster extends Cluster { } } - onClick = evt => { + onClick = (evt) => { const { feature } = evt if (!feature.properties.cluster) { @@ -79,7 +79,7 @@ class ClientCluster extends Cluster { } } - onSourceData = evt => { + onSourceData = (evt) => { if (evt.sourceId === this.getId() && this.getSourceFeatures().length) { this.getMapGL().off('sourcedata', this.onSourceData) this.updatePolygons() @@ -87,7 +87,7 @@ class ClientCluster extends Cluster { } // Returns all features in a cluster - getClusterFeatures = clusterId => + getClusterFeatures = (clusterId) => new Promise((resolve, reject) => { const mapgl = this.getMapGL() const source = mapgl.getSource(this.getId()) diff --git a/src/layers/Cluster.js b/src/layers/Cluster.js index 0d17114e..b58c8eac 100644 --- a/src/layers/Cluster.js +++ b/src/layers/Cluster.js @@ -1,10 +1,10 @@ import centerOfMass from '@turf/center-of-mass' -import Layer from './Layer' -import Spider from './Spider' -import { pointLayer, polygonLayer, outlineLayer } from '../utils/layers' import { isClusterPoint } from '../utils/filters' import { featureCollection } from '../utils/geometry' +import { pointLayer, polygonLayer, outlineLayer } from '../utils/layers' import { eventStrokeColor } from '../utils/style' +import Layer from './Layer' +import Spider from './Spider' class Cluster extends Layer { constructor(options) { @@ -17,14 +17,14 @@ class Cluster extends Layer { setFeatures(data = []) { super.setFeatures(data) // Assigns id to each feature - this._hasPolygons = data.some(f => f.geometry.type === 'Polygon') + this._hasPolygons = data.some((f) => f.geometry.type === 'Polygon') if (this._hasPolygons) { this._polygons = {} this._polygonsOnMap = [] // Translate from polygon to point before clustering - this._features = this._features.map(f => { + this._features = this._features.map((f) => { if (f.geometry.type === 'Polygon') { this._polygons[f.id] = f @@ -110,7 +110,9 @@ class Cluster extends Layer { const source = mapgl.getSource(this.getId()) source.getClusterExpansionZoom(clusterId, (error, zoom) => { - if (error) return + if (error) { + return + } mapgl.easeTo({ center, zoom: zoom + 1 }) }) } @@ -160,7 +162,7 @@ class Cluster extends Layer { } // Returns all features in a cluster - getClusterFeatures = clusterId => + getClusterFeatures = (clusterId) => new Promise((resolve, reject) => { const mapgl = this.getMapGL() const source = mapgl.getSource(this.getId()) @@ -173,18 +175,18 @@ class Cluster extends Layer { }) // Overrided in DonutCluster - sortClusterFeatures = features => features + sortClusterFeatures = (features) => features updatePolygons = () => { // Returns polygons visible on the map (within the map view and not clustered) const polygons = this.getSourceFeatures().filter( - f => f.properties.isPolygon + (f) => f.properties.isPolygon ) let polygonIds = [] if (polygons.length) { // Using set as features might be returned multipe times due to tiling - polygonIds = [...new Set(polygons.map(f => f.id))].sort() + polygonIds = [...new Set(polygons.map((f) => f.id))].sort() } // Only update source if there is a change @@ -194,7 +196,7 @@ class Cluster extends Layer { ) { this._polygonsOnMap = polygonIds - const features = polygonIds.map(id => this._polygons[id]) + const features = polygonIds.map((id) => this._polygons[id]) const source = this.getMapGL().getSource(`${this.getId()}-polygons`) source.setData(featureCollection(features)) @@ -206,7 +208,7 @@ class Cluster extends Layer { return this.getMapGL().querySourceFeatures(this.getId()) } - onSpiderClose = clusterId => { + onSpiderClose = (clusterId) => { this.setClusterOpacity(clusterId) } diff --git a/src/layers/DonutCluster.js b/src/layers/DonutCluster.js index 2dc90400..fa7e80b3 100644 --- a/src/layers/DonutCluster.js +++ b/src/layers/DonutCluster.js @@ -1,7 +1,7 @@ import throttle from 'lodash.throttle' +import { featureCollection } from '../utils/geometry' import Cluster from './Cluster' import DonutMarker from './DonutMarker' -import { featureCollection } from '../utils/geometry' class DonutCluster extends Cluster { clusters = {} @@ -52,13 +52,13 @@ class DonutCluster extends Cluster { this.clusters = {} } - onSourceData = evt => { + onSourceData = (evt) => { if (evt.sourceId === this.getId() && this.getSourceFeatures().length) { this.updateClusters() } } - onClick = evt => { + onClick = (evt) => { const { feature } = evt if (!feature.properties.cluster) { @@ -116,8 +116,8 @@ class DonutCluster extends Cluster { } // Sort cluster features after legend colors before spiderfy - sortClusterFeatures = features => { - const colors = this.options.groups.map(g => g.color) + sortClusterFeatures = (features) => { + const colors = this.options.groups.map((g) => g.color) return features.sort((f1, f2) => { const a = colors.indexOf(f1.properties.color) const b = colors.indexOf(f2.properties.color) @@ -145,7 +145,7 @@ class DonutCluster extends Cluster { let cluster = this.clusters[cluster_id] if (!cluster) { - const segments = groups.map(group => ({ + const segments = groups.map((group) => ({ ...group, count: properties[group.color], })) diff --git a/src/layers/DonutMarker.js b/src/layers/DonutMarker.js index 877c70b3..fef99dad 100644 --- a/src/layers/DonutMarker.js +++ b/src/layers/DonutMarker.js @@ -21,14 +21,14 @@ class DonutMarker extends Marker { this.getElement().style.display = isVisible ? 'block' : 'none' } - onClick = evt => { + onClick = (evt) => { evt.stopPropagation() this.fire('click') } } // Returns a SVG donut chart -export const donutChart = segments => { +export const donutChart = (segments) => { const total = segments.reduce((total, s) => total + s.count, 0) const fontSize = total >= 1000 ? 22 : total >= 100 ? 20 : total >= 10 ? 18 : 16 @@ -39,7 +39,7 @@ export const donutChart = segments => { let html = `` - segments.forEach(segment => { + segments.forEach((segment) => { html += donutSegment( offset / total, (offset + segment.count) / total, @@ -61,7 +61,9 @@ export const donutChart = segments => { // Returns a SVG donut chart segment export const donutSegment = (start, end, r, r0, color) => { - if (end - start === 1) end -= 0.00001 + if (end - start === 1) { + end -= 0.00001 + } const a0 = 2 * Math.PI * (start - 0.25) const a1 = 2 * Math.PI * (end - 0.25) const x0 = Math.cos(a0) diff --git a/src/layers/EarthEngine.js b/src/layers/EarthEngine.js index c6be2ce1..ac300bca 100644 --- a/src/layers/EarthEngine.js +++ b/src/layers/EarthEngine.js @@ -15,14 +15,14 @@ class EarthEngine extends Layer { }) } - addTo = map => + addTo = (map) => new Promise((resolve, reject) => { this._map = map if (map.styleIsLoaded()) { this._isLoading = true this.getWorkerInstance() - .then(async worker => { + .then(async (worker) => { this.worker = worker if (!this._tileUrl) { @@ -49,7 +49,7 @@ class EarthEngine extends Layer { resolve() }) - .catch(error => { + .catch((error) => { this._isLoading = false reject(error) }) @@ -68,7 +68,7 @@ class EarthEngine extends Layer { if (!this._workerPromise) { this._workerPromise = new Promise((resolve, reject) => getEarthEngineWorker(this.options.getAuthToken) - .then(EarthEngineWorker => { + .then((EarthEngineWorker) => { new EarthEngineWorker( getWorkerOptions(this.options) ).then(resolve) @@ -149,20 +149,21 @@ class EarthEngine extends Layer { } // Returns value at at position - getValue = async lnglat => { + getValue = async (lnglat) => { const { band, style } = this.options const data = await this.worker.getValue(lnglat) const value = data[band] || Object.values(data)[0] // Used for landcover - const item = Array.isArray(style) && style.find(i => i.value === value) + const item = + Array.isArray(style) && style.find((i) => i.value === value) return item ? item.name : value } // TODO: Move popup handling to the maps app showValue = (latlng, precision) => - this.getValue(latlng).then(value => { + this.getValue(latlng).then((value) => { const { lng, lat } = latlng const options = this.options let content @@ -210,7 +211,7 @@ class EarthEngine extends Layer { const ids = this._filteredFeatureIds return Array.isArray(ids) - ? features.filter(f => ids.includes(f.properties.id)) + ? features.filter((f) => ids.includes(f.properties.id)) : features } diff --git a/src/layers/Events.js b/src/layers/Events.js index ef64a7c5..f74eb49a 100644 --- a/src/layers/Events.js +++ b/src/layers/Events.js @@ -1,7 +1,7 @@ -import Layer from './Layer' -import { pointLayer, polygonLayer, outlineLayer } from '../utils/layers' import { bufferLayer, bufferOutlineLayer } from '../utils/buffers' +import { pointLayer, polygonLayer, outlineLayer } from '../utils/layers' import { eventStrokeColor } from '../utils/style' +import Layer from './Layer' class Events extends Layer { constructor(options) { diff --git a/src/layers/GeoJson.js b/src/layers/GeoJson.js index 9da628bc..4cc124c3 100644 --- a/src/layers/GeoJson.js +++ b/src/layers/GeoJson.js @@ -1,4 +1,5 @@ -import Layer from './Layer' +import { bufferLayer, bufferOutlineLayer } from '../utils/buffers' +import { labelLayer } from '../utils/labels' import { pointLayer, lineLayer, @@ -6,8 +7,7 @@ import { outlineLayer, symbolLayer, } from '../utils/layers' -import { bufferLayer, bufferOutlineLayer } from '../utils/buffers' -import { labelLayer } from '../utils/labels' +import Layer from './Layer' class GeoJson extends Layer { constructor(options) { diff --git a/src/layers/Layer.js b/src/layers/Layer.js index 3af6fd43..c94848c1 100644 --- a/src/layers/Layer.js +++ b/src/layers/Layer.js @@ -46,13 +46,13 @@ class Layer extends Evented { } } - Object.keys(source).forEach(id => { + Object.keys(source).forEach((id) => { if (map.styleIsLoaded() && !mapgl.getSource(id)) { mapgl.addSource(id, source[id]) } }) - layers.forEach(layer => { + layers.forEach((layer) => { if (map.styleIsLoaded() && !mapgl.getLayer(layer.id)) { mapgl.addLayer(layer, beforeId) } @@ -86,13 +86,13 @@ class Layer extends Evented { this.onRemove() if (mapgl) { - layers.forEach(layer => { + layers.forEach((layer) => { if (mapgl.getLayer(layer.id)) { mapgl.removeLayer(layer.id) } }) - Object.keys(source).forEach(id => { + Object.keys(source).forEach((id) => { if (mapgl.getSource(id)) { mapgl.removeSource(id) } @@ -139,7 +139,7 @@ class Layer extends Evented { const layers = this.getLayers() if (mapgl && layers) { - layers.forEach(layer => + layers.forEach((layer) => mapgl.setLayoutProperty(layer.id, 'visibility', value) ) } @@ -167,7 +167,7 @@ class Layer extends Evented { return Boolean( map && map.styleIsLoaded() && - this._layers.find(l => mapgl.getLayer(l.id)) + this._layers.find((l) => mapgl.getLayer(l.id)) ) } @@ -212,14 +212,14 @@ class Layer extends Evented { } hasLayerId(id) { - return this.getLayers().some(layer => layer.id === id) + return this.getLayers().some((layer) => layer.id === id) } move() { const mapgl = this.getMapGL() const beforeId = this._map.getBeforeLayerId() - this.getLayers().forEach(layer => { + this.getLayers().forEach((layer) => { mapgl.moveLayer(layer.id, beforeId) }) } @@ -232,10 +232,10 @@ class Layer extends Evented { getFeaturesById(id) { const features = typeof id === 'string' - ? this._features.filter(f => f.properties.id === id) - : this._features.filter(f => f.id === id) + ? this._features.filter((f) => f.properties.id === id) + : this._features.filter((f) => f.id === id) - return features.map(f => ({ ...f, source: this.getId() })) + return features.map((f) => ({ ...f, source: this.getId() })) } // Adds integer id for each feature (required by Feature State) @@ -255,8 +255,8 @@ class Layer extends Evented { this._images = images || [ ...new Set( this.getFeatures() - .filter(f => f.properties.iconUrl) - .map(f => f.properties.iconUrl) + .filter((f) => f.properties.iconUrl) + .map((f) => f.properties.iconUrl) ), ] } @@ -333,7 +333,7 @@ class Layer extends Evented { } // "Normalise" event before passing back to app - onClick = evt => this.fire('click', evt) + onClick = (evt) => this.fire('click', evt) // "Normalise" event before passing back to app onRightClick(evt) {} diff --git a/src/layers/LayerGroup.js b/src/layers/LayerGroup.js index 59430127..09a3979a 100644 --- a/src/layers/LayerGroup.js +++ b/src/layers/LayerGroup.js @@ -12,7 +12,7 @@ class LayerGroup extends Evented { } createLayer() { - this._layerConfigs.forEach(config => + this._layerConfigs.forEach((config) => this._layers.push(this._map.createLayer(config)) ) @@ -28,13 +28,13 @@ class LayerGroup extends Evented { this.createLayer() } - this._layers.forEach(layer => layer.addTo(map)) + this._layers.forEach((layer) => layer.addTo(map)) this.on('contextmenu', this.onContextMenu) } removeFrom(map) { - this._layers.forEach(layer => layer.removeFrom(map)) + this._layers.forEach((layer) => layer.removeFrom(map)) this.off('contextmenu', this.onContextMenu) } @@ -43,16 +43,16 @@ class LayerGroup extends Evented { } isOnMap() { - return this._layers.some(layer => layer.isOnMap()) + return this._layers.some((layer) => layer.isOnMap()) } isInteractive() { - return this._layers.some(layer => layer.isInteractive()) + return this._layers.some((layer) => layer.isInteractive()) } setIndex(index = 0) { this.options.index = index - this._layers.forEach(layer => layer.setIndex(index)) + this._layers.forEach((layer) => layer.setIndex(index)) } getIndex() { @@ -65,20 +65,20 @@ class LayerGroup extends Evented { getInteractiveIds() { return [].concat( - ...this._layers.map(layer => layer.getInteractiveIds()) + ...this._layers.map((layer) => layer.getInteractiveIds()) ) } getFeaturesById(id) { - return this._layers.map(layer => layer.getFeaturesById(id)).flat() + return this._layers.map((layer) => layer.getFeaturesById(id)).flat() } setOpacity(opacity) { - this._layers.forEach(layer => layer.setOpacity(opacity)) + this._layers.forEach((layer) => layer.setOpacity(opacity)) } setVisibility(isVisible) { - this._layers.forEach(layer => layer.setVisibility(isVisible)) + this._layers.forEach((layer) => layer.setVisibility(isVisible)) this._isVisible = isVisible } @@ -87,21 +87,21 @@ class LayerGroup extends Evented { } move() { - this._layers.forEach(layer => layer.move()) + this._layers.forEach((layer) => layer.move()) } hasLayerId(id) { - return this._layers.some(layer => - layer.getLayers().some(layer => layer.id === id) + return this._layers.some((layer) => + layer.getLayers().some((layer) => layer.id === id) ) } - onClick = evt => { + onClick = (evt) => { const { feature } = evt if (feature) { const { id } = feature.layer - const layer = this._layers.find(l => l.hasLayerId(id)) + const layer = this._layers.find((l) => l.hasLayerId(id)) if (layer) { layer.fire('click', evt) @@ -109,12 +109,12 @@ class LayerGroup extends Evented { } } - onContextMenu = evt => { + onContextMenu = (evt) => { const { feature } = evt if (feature) { const { id } = feature.layer - const layer = this._layers.find(l => l.hasLayerId(id)) + const layer = this._layers.find((l) => l.hasLayerId(id)) if (layer) { layer.fire('contextmenu', evt) @@ -125,7 +125,7 @@ class LayerGroup extends Evented { onMouseMove = (evt, feature) => { if (feature) { const { id } = feature.layer - const layer = this._layers.find(l => l.hasLayerId(id)) + const layer = this._layers.find((l) => l.hasLayerId(id)) if (layer) { layer.onMouseMove(evt, feature) diff --git a/src/layers/Markers.js b/src/layers/Markers.js index 76d51953..edda5400 100644 --- a/src/layers/Markers.js +++ b/src/layers/Markers.js @@ -1,7 +1,7 @@ -import Layer from './Layer' -import { symbolLayer } from '../utils/layers' import { bufferLayer, bufferOutlineLayer } from '../utils/buffers' import { labelLayer } from '../utils/labels' +import { symbolLayer } from '../utils/layers' +import Layer from './Layer' class Markers extends Layer { constructor(options) { diff --git a/src/layers/ServerCluster.js b/src/layers/ServerCluster.js index e4beebc8..6e3fd85c 100644 --- a/src/layers/ServerCluster.js +++ b/src/layers/ServerCluster.js @@ -1,6 +1,8 @@ import SphericalMercator from '@mapbox/sphericalmercator' import centroid from '@turf/centroid' -import Cluster from './Cluster' +import { isClusterPoint } from '../utils/filters' +import { earthRadius } from '../utils/geo' +import { featureCollection } from '../utils/geometry' import { pointLayer, polygonLayer, @@ -8,10 +10,8 @@ import { clusterLayer, clusterCountLayer, } from '../utils/layers' -import { isClusterPoint } from '../utils/filters' -import { featureCollection } from '../utils/geometry' import { eventStrokeColor, clusterCountColor } from '../utils/style' -import { earthRadius } from '../utils/geo' +import Cluster from './Cluster' class ServerCluster extends Cluster { currentTiles = [] @@ -82,7 +82,7 @@ class ServerCluster extends Cluster { } // Meters per pixel - getResolution = zoom => + getResolution = (zoom) => (Math.PI * earthRadius * 2) / this.options.tileSize / Math.pow(2, zoom) getTileParams(tileId) { @@ -99,7 +99,7 @@ class ServerCluster extends Cluster { } // Replace clusters within the same tile bounds - updateClusters = tiles => { + updateClusters = (tiles) => { const clusters = tiles.reduce((newClusters, tileId) => { const [z, x, y] = tileId.split('/') const isOutsideBounds = this.isOutsideBounds( @@ -124,7 +124,7 @@ class ServerCluster extends Cluster { } } - onClick = evt => { + onClick = (evt) => { const { geometry, properties } = evt.feature const { cluster, bounds, id, cluster_id } = properties @@ -159,7 +159,7 @@ class ServerCluster extends Cluster { } // Load clusters when new tiles are requested - onSourceData = evt => { + onSourceData = (evt) => { if (evt.sourceId === this.getId() && evt.tile) { const tileId = this.getTileId(evt.tile) @@ -177,7 +177,7 @@ class ServerCluster extends Cluster { if (tiles.join('-') !== this.currentTiles.join('-')) { this.currentTiles = tiles - const cachedTiles = tiles.filter(id => + const cachedTiles = tiles.filter((id) => Array.isArray(this.tileClusters[id]) ) @@ -221,14 +221,14 @@ class ServerCluster extends Cluster { } // Called by parent class - getClusterFeatures = clusterId => { - const cluster = this.currentClusters.find(c => c.id === clusterId) + getClusterFeatures = (clusterId) => { + const cluster = this.currentClusters.find((c) => c.id === clusterId) if (cluster) { return cluster.properties.id .split(',') .slice(0, this.options.maxSpiderSize) - .map(id => ({ + .map((id) => ({ type: 'Feature', id, geometry: cluster.geometry, @@ -241,7 +241,7 @@ class ServerCluster extends Cluster { // Returms true if geometry is outside bounds isOutsideBounds = - bounds => + (bounds) => ({ geometry }) => { const { coordinates } = geometry.type === 'Point' @@ -259,16 +259,16 @@ class ServerCluster extends Cluster { getVisibleTiles = async () => { while (!this.areTilesUpdated()) { - await new Promise(r => setTimeout(r, 100)) + await new Promise((r) => setTimeout(r, 100)) } return this.getSourceCacheTiles().map(this.getTileId).sort() } // Returns sorted array of cluster ids - getClusterIds = clusters => + getClusterIds = (clusters) => clusters - .map(c => c.id) + .map((c) => c.id) .sort((a, b) => a - b) .join() diff --git a/src/layers/Spider.js b/src/layers/Spider.js index c1e9aa37..47a65525 100644 --- a/src/layers/Spider.js +++ b/src/layers/Spider.js @@ -6,7 +6,7 @@ const Spider = function (map, options) { let spider let spiderId - const initializeLeg = leg => { + const initializeLeg = (leg) => { const { feature, elements, param } = leg const { radius, fillColor, opacity } = options const color = feature.properties.color || fillColor @@ -32,9 +32,11 @@ const Spider = function (map, options) { elements.pin.appendChild(marker) } - const setOpacity = opacity => { + const setOpacity = (opacity) => { if (spiderId) { - spider.each(leg => (leg.elements.container.style.opacity = opacity)) + spider.each( + (leg) => (leg.elements.container.style.opacity = opacity) + ) } } @@ -61,7 +63,7 @@ const Spider = function (map, options) { } } - const isExpanded = clusterId => clusterId === spiderId + const isExpanded = (clusterId) => clusterId === spiderId const getId = () => spiderId diff --git a/src/layers/TileLayer.js b/src/layers/TileLayer.js index 52288ac9..d1cbb702 100644 --- a/src/layers/TileLayer.js +++ b/src/layers/TileLayer.js @@ -23,7 +23,7 @@ class TileLayer extends Layer { `${url}?bbox={bbox-epsg-3857}&format=${format}&service=WMS&version=1.1.1&request=GetMap&srs=EPSG:3857&transparent=true&width=256&height=256&layers=${layers}`, ] } else if (url.includes('{s}')) { - tiles = ['a', 'b', 'c'].map(letter => url.replace('{s}', letter)) + tiles = ['a', 'b', 'c'].map((letter) => url.replace('{s}', letter)) } else { tiles = [url] } diff --git a/src/layers/VectorStyle.js b/src/layers/VectorStyle.js index 4c0102bd..b81faebb 100644 --- a/src/layers/VectorStyle.js +++ b/src/layers/VectorStyle.js @@ -1,6 +1,6 @@ import { Evented } from 'maplibre-gl' -import { mapStyle } from '../utils/style' import { BASEMAP_POSITION } from '../utils/layers' +import { mapStyle } from '../utils/style' class VectorStyle extends Evented { constructor(options = {}) { @@ -27,8 +27,8 @@ class VectorStyle extends Evented { this._visibleLayers = this._map .getMapGL() .getStyle() - .layers.filter(l => l.layout?.visibility !== 'none') - .map(l => l.id) + .layers.filter((l) => l.layout?.visibility !== 'none') + .map((l) => l.id) } this._isOnMap = isOnMap @@ -65,7 +65,7 @@ class VectorStyle extends Evented { .getMapGL() .once('idle', resolve) .setStyle(style, { diff: false }) - .once('error', e => { + .once('error', (e) => { let msg if (e.error.message.includes('missing required property')) { msg = 'The vector style is malformed or invalid.' @@ -85,12 +85,12 @@ class VectorStyle extends Evented { getOtherLayers() { return this._map .getLayers() - .filter(layer => !(layer instanceof VectorStyle)) + .filter((layer) => !(layer instanceof VectorStyle)) } // Add other layers to the map after style is changed async addOtherLayers() { - this.getOtherLayers().forEach(async layer => { + this.getOtherLayers().forEach(async (layer) => { if (!layer.isOnMap()) { await layer.addTo(this._map) layer.setVisibility(layer.isVisible()) @@ -100,7 +100,7 @@ class VectorStyle extends Evented { // Remove other layers from the map before style is changed async removeOtherLayers() { - this.getOtherLayers().forEach(async layer => { + this.getOtherLayers().forEach(async (layer) => { if (layer.isOnMap()) { await layer.removeFrom(this._map, true) } @@ -108,7 +108,9 @@ class VectorStyle extends Evented { } mapHasVectorStyle() { - return this._map.getLayers().some(layer => layer instanceof VectorStyle) + return this._map + .getLayers() + .some((layer) => layer instanceof VectorStyle) } setIndex(index = BASEMAP_POSITION) { @@ -125,7 +127,7 @@ class VectorStyle extends Evented { const mapgl = this._map.getMapGL() const value = isVisible ? 'visible' : 'none' - this._visibleLayers.forEach(id => + this._visibleLayers.forEach((id) => mapgl.setLayoutProperty(id, 'visibility', value) ) } diff --git a/src/layers/__tests__/EarthEngine.spec.js b/src/layers/__tests__/EarthEngine.spec.js index 05542fe3..552527e8 100644 --- a/src/layers/__tests__/EarthEngine.spec.js +++ b/src/layers/__tests__/EarthEngine.spec.js @@ -184,6 +184,6 @@ describe('EarthEngine', () => { const layer = new EarthEngine(options) const features = layer.getFeatures() - expect(features.some(f => f.geometry.type === 'Point')).toBe(false) + expect(features.some((f) => f.geometry.type === 'Point')).toBe(false) }) }) diff --git a/src/layers/__tests__/Layer.spec.js b/src/layers/__tests__/Layer.spec.js index a616fbea..d7cd3e98 100644 --- a/src/layers/__tests__/Layer.spec.js +++ b/src/layers/__tests__/Layer.spec.js @@ -59,7 +59,7 @@ describe('Layer', () => { it('Should add an interactive layer', () => { const layer = new Layer() - mockMapGL.getLayer.mockImplementation(x => x === layer.getId()) + mockMapGL.getLayer.mockImplementation((x) => x === layer.getId()) const mockMapLayer = { id: 42 } layer.addTo(mockMap) @@ -75,7 +75,7 @@ describe('Layer', () => { const features = layer.getFeatures() expect(features.length).toBe(data.length) - expect(features.every(f => typeof f.id === 'number')).toBe(true) + expect(features.every((f) => typeof f.id === 'number')).toBe(true) expect(layer.getFeaturesById(2)).toStrictEqual( layer.getFeaturesById('fdc6uOvgoji') ) diff --git a/src/layers/layerTypes.js b/src/layers/layerTypes.js index 871c682d..236d7cf9 100644 --- a/src/layers/layerTypes.js +++ b/src/layers/layerTypes.js @@ -1,16 +1,16 @@ -import VectorStyle from './VectorStyle' -import TileLayer from './TileLayer' -import Choropleth from './Choropleth' +import BingLayer from './BingLayer' import Boundary from './Boundary' -import Markers from './Markers' -import Events from './Events' +import Choropleth from './Choropleth' import ClientCluster from './ClientCluster' import DonutCluster from './DonutCluster' -import ServerCluster from './ServerCluster' import EarthEngine from './EarthEngine' -import BingLayer from './BingLayer' +import Events from './Events' import GeoJson from './GeoJson' import LayerGroup from './LayerGroup' +import Markers from './Markers' +import ServerCluster from './ServerCluster' +import TileLayer from './TileLayer' +import VectorStyle from './VectorStyle' export default { vectorStyle: VectorStyle, //basemap /externalLayer diff --git a/src/ui/Popup.js b/src/ui/Popup.js index 7f553762..79a2f0e5 100644 --- a/src/ui/Popup.js +++ b/src/ui/Popup.js @@ -40,7 +40,7 @@ class Popup extends PopupGL { } // Avoid closing a popup that was just opened - onMapClick = evt => { + onMapClick = (evt) => { if (!this._mapInstance.getEventFeature(evt)) { this.remove() } diff --git a/src/utils/buffers.js b/src/utils/buffers.js index c99e4357..5773cdd1 100644 --- a/src/utils/buffers.js +++ b/src/utils/buffers.js @@ -1,7 +1,7 @@ -import circle from '@turf/circle' import polygonBuffer from '@turf/buffer' -import { featureCollection } from './geometry' +import circle from '@turf/circle' import { colorExpr } from './expressions' +import { featureCollection } from './geometry' const defaults = { color: '#95c8fb', @@ -19,7 +19,7 @@ export const getBufferGeometry = ({ geometry }, buffer) => export const bufferSource = (features, buffer) => ({ type: 'geojson', data: featureCollection( - features.map(feature => ({ + features.map((feature) => ({ ...feature, geometry: getBufferGeometry(feature, buffer), })) diff --git a/src/utils/core.js b/src/utils/core.js index 69aca038..0d90b4b3 100644 --- a/src/utils/core.js +++ b/src/utils/core.js @@ -3,7 +3,7 @@ export const setTemplate = (text, data) => text.replace(/\{ *([\w_-]+) *\}/g, (str, key) => data[key]) // Returns a string representation of an array of features -export const getFeaturesString = features => +export const getFeaturesString = (features) => Array.isArray(features) ? features .sort((a, b) => b.id - a.id) diff --git a/src/utils/earthengine.js b/src/utils/earthengine.js index 8a3006e3..7b9c9bb2 100644 --- a/src/utils/earthengine.js +++ b/src/utils/earthengine.js @@ -27,9 +27,9 @@ const workerOptions = [ ] // Returns the layer options that should be passed to the EE worker -export const getWorkerOptions = opts => { +export const getWorkerOptions = (opts) => { const options = Object.keys(opts) - .filter(option => workerOptions.includes(option)) + .filter((option) => workerOptions.includes(option)) .reduce((obj, key) => { obj[key] = opts[key] return obj @@ -37,7 +37,7 @@ export const getWorkerOptions = opts => { // Exclude point features if no buffer if (options.data && !options.buffer) { - options.data = options.data.filter(d => d.geometry.type !== 'Point') + options.data = options.data.filter((d) => d.geometry.type !== 'Point') } return options diff --git a/src/utils/expressions.js b/src/utils/expressions.js index 230f2fb2..f633b2a1 100644 --- a/src/utils/expressions.js +++ b/src/utils/expressions.js @@ -2,7 +2,7 @@ import { isHover } from './filters' import { strokeWidth, hoverStrokeMultiplier } from './style' // Returns color from feature with fallback -export const colorExpr = color => [ +export const colorExpr = (color) => [ 'case', ['has', 'color'], ['get', 'color'], @@ -17,7 +17,7 @@ export const widthExpr = (width = strokeWidth) => [ ] // Returns radius from feature with fallback -export const radiusExpr = radius => [ +export const radiusExpr = (radius) => [ 'case', ['has', 'radius'], ['get', 'radius'], diff --git a/src/utils/geo.js b/src/utils/geo.js index bc5a7805..bdb2f8df 100644 --- a/src/utils/geo.js +++ b/src/utils/geo.js @@ -8,7 +8,7 @@ const tile2lat = (y, z) => { } // Returns resolution in meters at zoom -export const getZoomResolution = zoom => +export const getZoomResolution = (zoom) => (2 * Math.PI * earthRadius) / 256 / Math.pow(2, zoom) // Returns lng/lat bounds for a tile diff --git a/src/utils/geometry.js b/src/utils/geometry.js index a1f4c5ca..13ce8597 100644 --- a/src/utils/geometry.js +++ b/src/utils/geometry.js @@ -1,6 +1,6 @@ import { LngLatBounds } from 'maplibre-gl' -export const isPoint = feature => feature.geometry.type === 'Point' +export const isPoint = (feature) => feature.geometry.type === 'Point' export const getBoundsFromLayers = (layers = []) => { const bounds = layers.reduce((b, l) => { diff --git a/src/utils/images.js b/src/utils/images.js index 67df34c4..2bec641f 100644 --- a/src/utils/images.js +++ b/src/utils/images.js @@ -12,7 +12,7 @@ const addImage = (map, name, img) => { } // Creates image from SVG data URI -const dataUri2image = dataUri => +const dataUri2image = (dataUri) => new Promise((resolve, reject) => { const img = new Image(svgWidth, svgHeight) img.onload = () => resolve(img) @@ -21,20 +21,21 @@ const dataUri2image = dataUri => }) // Fetch SVG and convert to Base64 data URI -const fetchSvg = url => +const fetchSvg = (url) => fetch(url, { credentials }) - .then(response => response.text()) + .then((response) => response.text()) .then( - svg => `data:image/svg+xml;charset=utf-8;base64,${window.btoa(svg)}` + (svg) => + `data:image/svg+xml;charset=utf-8;base64,${window.btoa(svg)}` ) .then(dataUri2image) // Load and add image to map -const loadImage = map => url => - new Promise(resolve => { +const loadImage = (map) => (url) => + new Promise((resolve) => { if (url.endsWith('.svg')) { fetchSvg(url) - .then(img => { + .then((img) => { addImage(map, url, img) resolve(img) }) diff --git a/src/utils/labels.js b/src/utils/labels.js index 11f32644..41e65730 100644 --- a/src/utils/labels.js +++ b/src/utils/labels.js @@ -80,7 +80,7 @@ export const getLabelPosition = ({ type, coordinates }) => { let polygon = coordinates if (type === 'MultiPolygon') { - const areas = coordinates.map(coords => + const areas = coordinates.map((coords) => area({ type: 'Polygon', coordinates: coords, diff --git a/src/utils/layers.js b/src/utils/layers.js index 02ce77dc..ef804b1f 100644 --- a/src/utils/layers.js +++ b/src/utils/layers.js @@ -1,3 +1,9 @@ +import { + colorExpr, + widthExpr, + radiusExpr, + clusterRadiusExpr, +} from './expressions' import { isPointNoSymbol, isPolygon, @@ -5,12 +11,6 @@ import { isCluster, isSymbol, } from './filters' -import { - colorExpr, - widthExpr, - radiusExpr, - clusterRadiusExpr, -} from './expressions' import defaults from './style' export const BASEMAP_POSITION = 0 diff --git a/src/utils/numbers.js b/src/utils/numbers.js index 0fa4084e..6da5a1fc 100644 --- a/src/utils/numbers.js +++ b/src/utils/numbers.js @@ -1,16 +1,16 @@ // Rounds a number to d decimals -export const numberPrecision = d => { +export const numberPrecision = (d) => { if (d === undefined) { - return n => n + return (n) => n } const m = Math.pow(10, d) - return n => Math.round(n * m) / m + return (n) => Math.round(n * m) / m } // Returns number of decimals based on the value -export const getPrecision = v => (v < 1 ? 3 : v < 10 ? 2 : v < 100 ? 1 : 0) +export const getPrecision = (v) => (v < 1 ? 3 : v < 10 ? 2 : v < 100 ? 1 : 0) // Sets number of decimals based on the value export const setPrecision = (value, precision) => @@ -20,8 +20,8 @@ export const setPrecision = (value, precision) => : getPrecision(Math.abs(value)) )(value) -export const kmToMiles = value => value * 0.621371192 +export const kmToMiles = (value) => value * 0.621371192 -export const squareMetersToHectares = value => value / 10000 +export const squareMetersToHectares = (value) => value / 10000 -export const squareMetersToAcres = value => value / 4046.8564224 +export const squareMetersToAcres = (value) => value / 4046.8564224 diff --git a/src/utils/opacity.js b/src/utils/opacity.js index dabab5ba..453c8db3 100644 --- a/src/utils/opacity.js +++ b/src/utils/opacity.js @@ -20,11 +20,11 @@ const opacityFactor = { const getOpacity = (key, opacity) => opacity * (opacityFactor[key] || 1) export const setLayersOpacity = (mapgl, id, opacity) => { - Object.keys(properties).forEach(key => { + Object.keys(properties).forEach((key) => { const layerId = `${id}-${key}` if (mapgl.getLayer(layerId)) { - properties[key].forEach(property => + properties[key].forEach((property) => mapgl.setPaintProperty( layerId, property, diff --git a/src/utils/spiderifier.js b/src/utils/spiderifier.js index 017fd9c9..987dd9f2 100644 --- a/src/utils/spiderifier.js +++ b/src/utils/spiderifier.js @@ -45,7 +45,7 @@ const util = { }, mapTimes: (count, iterator) => { const result = [] - util.eachTimes(count, i => result.push(iterator(i))) + util.eachTimes(count, (i) => result.push(iterator(i))) return result }, } @@ -107,12 +107,12 @@ const spiderifier = (map, userOptions) => { options.initializeLeg(spiderLeg) - elements.container.onclick = e => options.onClick(e, spiderLeg) + elements.container.onclick = (e) => options.onClick(e, spiderLeg) return spiderLeg }) - util.each(spiderLegs.reverse(), spiderLeg => + util.each(spiderLegs.reverse(), (spiderLeg) => spiderLeg.marker.addTo(map) ) @@ -133,7 +133,7 @@ const spiderifier = (map, userOptions) => { previousSpiderLegs = spiderLegs } - const generateSpiderLegParams = count => { + const generateSpiderLegParams = (count) => { if (count >= options.circleSpiralSwitchover) { return generateSpiralParams(count) } else { @@ -141,11 +141,11 @@ const spiderifier = (map, userOptions) => { } } - const generateSpiralParams = count => { + const generateSpiralParams = (count) => { let legLength = options.spiralLengthStart let angle = 0 - return util.mapTimes(count, index => { + return util.mapTimes(count, (index) => { angle = angle + (options.spiralFootSeparation / legLength + index * 0.0005) @@ -164,12 +164,12 @@ const spiderifier = (map, userOptions) => { }) } - const generateCircleParams = count => { + const generateCircleParams = (count) => { const circumference = options.circleFootSeparation * (2 + count) const legLength = circumference / twoPi // = radius from circumference const angleStep = twoPi / count - return util.mapTimes(count, index => { + return util.mapTimes(count, (index) => { const angle = index * angleStep const x = legLength * Math.cos(angle) const y = legLength * Math.sin(angle) @@ -178,7 +178,7 @@ const spiderifier = (map, userOptions) => { }) } - const createMarkerElements = spiderLegParam => { + const createMarkerElements = (spiderLegParam) => { const containerElem = document.createElement('div') const pinElem = document.createElement('div') const lineElem = document.createElement('div') @@ -207,7 +207,7 @@ const spiderifier = (map, userOptions) => { return { spiderfy, unspiderfy, - each: callback => util.each(previousSpiderLegs, callback), + each: (callback) => util.each(previousSpiderLegs, callback), } } diff --git a/src/utils/sync.js b/src/utils/sync.js index 14ce3b34..3656f63e 100644 --- a/src/utils/sync.js +++ b/src/utils/sync.js @@ -7,7 +7,7 @@ const moveToMapPosition = (master, clones) => { const bearing = master.getBearing() const pitch = master.getPitch() - clones.forEach(clone => + clones.forEach((clone) => clone.jumpTo({ center: center, zoom: zoom, @@ -23,7 +23,7 @@ const syncMaps = (() => { const syncedHandlersById = {} // Creates move handlers for masters and clones - const createHandlers = id => { + const createHandlers = (id) => { const syncedMaps = syncedMapsById[id] const syncedHandlers = (syncedHandlersById[id] = []) @@ -53,7 +53,7 @@ const syncMaps = (() => { if (syncedMaps && syncedMaps.includes(map)) { updateMaps( id, - syncedMaps.filter(m => m !== map) + syncedMaps.filter((m) => m !== map) ) } } @@ -74,10 +74,10 @@ const syncMaps = (() => { } // Enable move handlers (turn on) - const enableMapSync = id => toggleMapSync(id, true) + const enableMapSync = (id) => toggleMapSync(id, true) // Disable move handlers (turn off) - const disableMapSync = id => toggleMapSync(id, false) + const disableMapSync = (id) => toggleMapSync(id, false) // Sync handler between master and clones const sync = (id, master, clones) => {