From 29843b2d6a38387935692594d64f5d4b1ca59c41 Mon Sep 17 00:00:00 2001 From: Mikael Vaaltola Date: Wed, 5 Aug 2020 14:50:30 +0300 Subject: [PATCH 1/5] Update eslint config --- .eslintrc.js | 11 +++++++++- package.json | 3 ++- yarn.lock | 58 +++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 23c5467..2c06b78 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,7 +2,16 @@ module.exports = { extends: [ "airbnb-typescript", ], + parser: "@typescript-eslint/parser", parserOptions: { project: './tsconfig.json' + }, + plugins: [ + "@typescript-eslint", + "react", + "react-hooks", + ], + rules: { + "react-hooks/exhaustive-deps": "warn", } -} \ No newline at end of file +} diff --git a/package.json b/package.json index d3fa80d..293e2c2 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,8 @@ ] }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^3.3.0", + "@typescript-eslint/eslint-plugin": "^3.7.1", + "@typescript-eslint/parser": "^3.7.1", "eslint-config-airbnb-typescript": "^8.0.2", "eslint-plugin-import": "^2.21.2", "eslint-plugin-jsx-a11y": "^6.3.1", diff --git a/yarn.lock b/yarn.lock index d89660d..e9497ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1805,12 +1805,12 @@ regexpp "^3.0.0" tsutils "^3.17.1" -"@typescript-eslint/eslint-plugin@^3.3.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.6.0.tgz#ba2b6cae478b8fca3f2e58ff1313e4198eea2d8a" - integrity sha512-ubHlHVt1lsPQB/CZdEov9XuOFhNG9YRC//kuiS1cMQI6Bs1SsqKrEmZnpgRwthGR09/kEDtr9MywlqXyyYd8GA== +"@typescript-eslint/eslint-plugin@^3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.7.1.tgz#d144c49a9a0ffe8dd704bb179c243df76c111bc9" + integrity sha512-3DB9JDYkMrc8Au00rGFiJLK2Ja9CoMP6Ut0sHsXp3ZtSugjNxvSSHTnKLfo4o+QmjYBJqEznDqsG1zj4F2xnsg== dependencies: - "@typescript-eslint/experimental-utils" "3.6.0" + "@typescript-eslint/experimental-utils" "3.7.1" debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" @@ -1838,6 +1838,17 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" +"@typescript-eslint/experimental-utils@3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.7.1.tgz#ab036caaed4c870d22531d41f9352f3147364d61" + integrity sha512-TqE97pv7HrqWcGJbLbZt1v59tcqsSVpWTOf1AqrWK7n8nok2sGgVtYRuGXeNeLw3wXlLEbY1MKP3saB2HsO/Ng== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/types" "3.7.1" + "@typescript-eslint/typescript-estree" "3.7.1" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + "@typescript-eslint/parser@^2.10.0": version "2.34.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.34.0.tgz#50252630ca319685420e9a39ca05fe185a256bc8" @@ -1859,11 +1870,27 @@ "@typescript-eslint/typescript-estree" "3.6.0" eslint-visitor-keys "^1.1.0" +"@typescript-eslint/parser@^3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.7.1.tgz#5d9ccecb116d12d9c6073e9861c57c9b1aa88128" + integrity sha512-W4QV/gXvfIsccN8225784LNOorcm7ch68Fi3V4Wg7gmkWSQRKevO4RrRqWo6N/Z/myK1QAiGgeaXN57m+R/8iQ== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "3.7.1" + "@typescript-eslint/types" "3.7.1" + "@typescript-eslint/typescript-estree" "3.7.1" + eslint-visitor-keys "^1.1.0" + "@typescript-eslint/types@3.6.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.6.0.tgz#4bd6eee55d2f9d35a4b36c4804be1880bf68f7bc" integrity sha512-JwVj74ohUSt0ZPG+LZ7hb95fW8DFOqBuR6gE7qzq55KDI3BepqsCtHfBIoa0+Xi1AI7fq5nCu2VQL8z4eYftqg== +"@typescript-eslint/types@3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.7.1.tgz#90375606b2fd73c1224fe9e397ee151e28fa1e0c" + integrity sha512-PZe8twm5Z4b61jt7GAQDor6KiMhgPgf4XmUb9zdrwTbgtC/Sj29gXP1dws9yEn4+aJeyXrjsD9XN7AWFhmnUfg== + "@typescript-eslint/typescript-estree@2.34.0": version "2.34.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5" @@ -1891,6 +1918,20 @@ semver "^7.3.2" tsutils "^3.17.1" +"@typescript-eslint/typescript-estree@3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.7.1.tgz#ce1ffbd0fa53f34d4ce851a7a364e392432f6eb3" + integrity sha512-m97vNZkI08dunYOr2lVZOHoyfpqRs0KDpd6qkGaIcLGhQ2WPtgHOd/eVbsJZ0VYCQvupKrObAGTOvk3tfpybYA== + dependencies: + "@typescript-eslint/types" "3.7.1" + "@typescript-eslint/visitor-keys" "3.7.1" + debug "^4.1.1" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + "@typescript-eslint/visitor-keys@3.6.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.6.0.tgz#44185eb0cc47651034faa95c5e2e8b314ecebb26" @@ -1898,6 +1939,13 @@ dependencies: eslint-visitor-keys "^1.1.0" +"@typescript-eslint/visitor-keys@3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.7.1.tgz#b90191e74efdee656be8c5a30f428ed16dda46d1" + integrity sha512-xn22sQbEya+Utj2IqJHGLA3i1jDzR43RzWupxojbSWnj3nnPLavaQmWe5utw03CwYao3r00qzXfgJMGNkrzrAA== + dependencies: + eslint-visitor-keys "^1.1.0" + "@webassemblyjs/ast@1.8.5": version "1.8.5" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" From 41000865ac3237cd4f25a405eec87d0c85046be4 Mon Sep 17 00:00:00 2001 From: Mikael Vaaltola Date: Wed, 5 Aug 2020 14:51:01 +0300 Subject: [PATCH 2/5] Add item=true to Grid components --- src/components/layerselector.tsx | 1 + src/components/mainui.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/src/components/layerselector.tsx b/src/components/layerselector.tsx index c9ce7bd..34af016 100644 --- a/src/components/layerselector.tsx +++ b/src/components/layerselector.tsx @@ -33,6 +33,7 @@ export default function LayerSelector() { alignItems="center" className={classes.root} container + item direction="row" justify="space-evenly" spacing={3} diff --git a/src/components/mainui.tsx b/src/components/mainui.tsx index c9a25d6..d5bd78e 100644 --- a/src/components/mainui.tsx +++ b/src/components/mainui.tsx @@ -29,6 +29,7 @@ export default function MainUI() { Date: Wed, 5 Aug 2020 15:03:05 +0300 Subject: [PATCH 3/5] Add basic popup implementation --- src/components/mapcomponent.tsx | 76 +++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/src/components/mapcomponent.tsx b/src/components/mapcomponent.tsx index 5df80b3..28cbc80 100644 --- a/src/components/mapcomponent.tsx +++ b/src/components/mapcomponent.tsx @@ -1,6 +1,10 @@ -import React, { useEffect, useState } from 'react'; +import React, { + useEffect, useRef, useState, +} from 'react'; import 'ol/ol.css'; -import { Map, View } from 'ol'; +import { + Map, MapBrowserEvent, Overlay, View, +} from 'ol'; import TileLayer from 'ol/layer/Tile'; import VectorTileLayer from 'ol/layer/VectorTile'; import VectorTileSource, { Options as VectorTileOptions } from 'ol/source/VectorTile'; @@ -11,6 +15,7 @@ import { Fill, Stroke, Style } from 'ol/style'; import CircleStyle from 'ol/style/Circle'; import MVT from 'ol/format/MVT'; +import OverlayPositioning from 'ol/OverlayPositioning'; import { Basemaps, Tileset } from '../types'; interface MapProps { @@ -50,32 +55,63 @@ const createVectorTileSource = (tileset: Tileset):VectorTileSource => { minZoom: tileset.minzoom, url: tileset.tiles[0], }; - const vt = new VectorTileSource(options); - return vt; + return new VectorTileSource(options); }; function MapComponent({ basemaps, tilesets }: MapProps) { + const [olMap, setOlMap] = useState(); const WMTSLayers = basemaps.WMTS; const [activeTileLayer, setActiveTileLayer] = useState(); const mapContainerStyle = { height: '100%', width: '100%' }; + const [popup, setPopup] = useState(); - const olMap = new Map({ - target: undefined, - controls: [], - view: new View({ - center: [2478699.953232, 8501593.815476], - zoom: 14, - }), - }); + const mapRef = useRef(null); + const popupRef = useRef(null); - // Set the ol map target on initial render + // const olMap = new Map({ useEffect(() => { - olMap.setTarget('map'); - return () => olMap.setTarget(undefined); + setOlMap(new Map({ + target: undefined, + controls: [], + view: new View({ + center: [2478699.953232, 8501593.815476], + zoom: 14, + }), + })); }, []); - // Set initial WMTS basemap and vectortilelayer useEffect(() => { + if (olMap) { + olMap?.setTarget(mapRef.current!); + setPopup(new Overlay({ + element: popupRef.current!, + autoPan: true, + autoPanAnimation: { + duration: 250, + }, + positioning: OverlayPositioning.CENTER_CENTER, + })); + } + return () => olMap?.setTarget(undefined); + }, [olMap]); + + useEffect(() => { + if (!olMap || !popup) return; + if (!olMap.getOverlays().getLength()) olMap.addOverlay(popup); + }, [olMap, popup]); + + useEffect(() => { + if (!olMap || !popup) return; + olMap.on('click', (evt: MapBrowserEvent) => { + popup.setPosition(evt.coordinate); + if (popupRef.current === null) return; + popupRef.current.innerHTML = '

feature

'; + }); + }, [olMap, popup]); + + // Set initial WMTS basemap and VectorTileLayer + useEffect(() => { + if (!olMap) return; const baseLayer = WMTSLayers[0]; const parser = new WMTSCapabilities(); fetch(baseLayer.url) @@ -113,7 +149,13 @@ function MapComponent({ basemaps, tilesets }: MapProps) { return (
-
+
+
); } From 5cb1c40d0cfaa935412a1073d424f372d6301f00 Mon Sep 17 00:00:00 2001 From: Mikael Vaaltola Date: Wed, 5 Aug 2020 15:16:24 +0300 Subject: [PATCH 4/5] Display feature information in popup --- src/components/mapcomponent.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/components/mapcomponent.tsx b/src/components/mapcomponent.tsx index 28cbc80..5773547 100644 --- a/src/components/mapcomponent.tsx +++ b/src/components/mapcomponent.tsx @@ -68,7 +68,7 @@ function MapComponent({ basemaps, tilesets }: MapProps) { const mapRef = useRef(null); const popupRef = useRef(null); - // const olMap = new Map({ + // Create Map useEffect(() => { setOlMap(new Map({ target: undefined, @@ -80,6 +80,7 @@ function MapComponent({ basemaps, tilesets }: MapProps) { })); }, []); + // Set olMap target and create popup Overlay useEffect(() => { if (olMap) { olMap?.setTarget(mapRef.current!); @@ -95,17 +96,26 @@ function MapComponent({ basemaps, tilesets }: MapProps) { return () => olMap?.setTarget(undefined); }, [olMap]); + // Add popup Overlay to map useEffect(() => { if (!olMap || !popup) return; if (!olMap.getOverlays().getLength()) olMap.addOverlay(popup); }, [olMap, popup]); + // Create map click event listener useEffect(() => { if (!olMap || !popup) return; olMap.on('click', (evt: MapBrowserEvent) => { + const features = olMap.getFeaturesAtPixel(evt.pixel); + if (features.length === 0) { + popupRef.current!.hidden = true; + return; + } popup.setPosition(evt.coordinate); + popupRef.current!.hidden = false; if (popupRef.current === null) return; - popupRef.current.innerHTML = '

feature

'; + const properties = features[0].getProperties(); + popupRef.current.innerHTML = JSON.stringify(properties, null, 2); }); }, [olMap, popup]); @@ -153,7 +163,7 @@ function MapComponent({ basemaps, tilesets }: MapProps) {
From 1f243774a19da98d5d49c1ff72f84d1de8676c1b Mon Sep 17 00:00:00 2001 From: Mikael Vaaltola Date: Wed, 5 Aug 2020 16:46:45 +0300 Subject: [PATCH 5/5] Improve popup content --- src/components/mapcomponent.tsx | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/components/mapcomponent.tsx b/src/components/mapcomponent.tsx index 5773547..183d5a5 100644 --- a/src/components/mapcomponent.tsx +++ b/src/components/mapcomponent.tsx @@ -58,9 +58,25 @@ const createVectorTileSource = (tileset: Tileset):VectorTileSource => { return new VectorTileSource(options); }; +interface FeatureProperties { + [key: string]: any, +} + +const popupContentFromFeatureProperties = (properties: FeatureProperties) => { + const title = properties.name_fi ? properties.name_fi : properties.name; + const website = properties.website ? properties.website : ''; + let resultHTML = `

${title}

${website}`; + Object.keys(properties).forEach((key) => { + resultHTML += ``; + }); + resultHTML += '
${key}${properties[key]}
'; + return resultHTML; +}; + function MapComponent({ basemaps, tilesets }: MapProps) { const [olMap, setOlMap] = useState(); const WMTSLayers = basemaps.WMTS; + // eslint-disable-next-line const [activeTileLayer, setActiveTileLayer] = useState(); const mapContainerStyle = { height: '100%', width: '100%' }; const [popup, setPopup] = useState(); @@ -106,16 +122,16 @@ function MapComponent({ basemaps, tilesets }: MapProps) { useEffect(() => { if (!olMap || !popup) return; olMap.on('click', (evt: MapBrowserEvent) => { + if (popupRef.current === null) return; const features = olMap.getFeaturesAtPixel(evt.pixel); if (features.length === 0) { - popupRef.current!.hidden = true; + popupRef.current.hidden = true; return; } popup.setPosition(evt.coordinate); - popupRef.current!.hidden = false; - if (popupRef.current === null) return; + popupRef.current.hidden = false; const properties = features[0].getProperties(); - popupRef.current.innerHTML = JSON.stringify(properties, null, 2); + popupRef.current.innerHTML = popupContentFromFeatureProperties(properties); }); }, [olMap, popup]);