From f7e069dc27559e66b59f4055182a2a942f8a87fe Mon Sep 17 00:00:00 2001 From: esikkala <esko.ikkala@aalto.fi> Date: Thu, 25 Mar 2021 09:30:51 +0200 Subject: [PATCH] LeafletMap: add proper configs for GeoJSON layers --- package-lock.json | 83 ++++++ package.json | 3 +- .../components/facet_results/LeafletMap.js | 252 +++++------------- .../perspectives/sampo/Perspective1.js | 112 +++++++- src/server/index.js | 34 +++ src/server/openapi.yaml | 66 ++++- 6 files changed, 350 insertions(+), 200 deletions(-) diff --git a/package-lock.json b/package-lock.json index b62d35da..d495f20d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5203,6 +5203,69 @@ } } }, + "@turf/bbox": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-6.3.0.tgz", + "integrity": "sha512-N4ue5Xopu1qieSHP2MA/CJGWHPKaTrVXQJjzHRNcY1vtsO126xbSaJhWUrFc5x5vVkXp0dcucGryO0r5m4o/KA==", + "requires": { + "@turf/helpers": "^6.3.0", + "@turf/meta": "^6.3.0" + } + }, + "@turf/buffer": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@turf/buffer/-/buffer-6.3.0.tgz", + "integrity": "sha512-B0GWgJzmTaaw1GvTd+Df+ToKSYphz9d6hPCOwXbE2vS5DdZryoxBfxQ32LSX/hW/vx7TLf7E4M0VJBb+Sn1DKA==", + "requires": { + "@turf/bbox": "^6.3.0", + "@turf/center": "^6.3.0", + "@turf/helpers": "^6.3.0", + "@turf/meta": "^6.3.0", + "@turf/projection": "^6.3.0", + "d3-geo": "1.7.1", + "turf-jsts": "*" + } + }, + "@turf/center": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@turf/center/-/center-6.3.0.tgz", + "integrity": "sha512-41g/ZYwoBs2PK7tpAHhf4D6llHdRvY827HLXCld5D0IOnzsWPqDk7WnV8P5uq4g/gyH1/WfKQYn5SgfSj4sSfw==", + "requires": { + "@turf/bbox": "^6.3.0", + "@turf/helpers": "^6.3.0" + } + }, + "@turf/clone": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-6.3.0.tgz", + "integrity": "sha512-GAgN89/9GCqUKECB1oY2hcTs0K2rZj+a2tY6VfM0ef9wwckuQZCKi+kKGUzhKVrmHee15jKV8n6DY0er8OndKg==", + "requires": { + "@turf/helpers": "^6.3.0" + } + }, + "@turf/helpers": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-6.3.0.tgz", + "integrity": "sha512-kr6KuD4Z0GZ30tblTEvi90rvvVNlKieXuMC8CTzE/rVQb0/f/Cb29zCXxTD7giQTEQY/P2nRW23wEqqyNHulCg==" + }, + "@turf/meta": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-6.3.0.tgz", + "integrity": "sha512-qBJjaAJS9H3ap0HlGXyF/Bzfl0qkA9suafX/jnDsZvWMfVLt+s+o6twKrXOGk5t7nnNON2NFRC8+czxpu104EQ==", + "requires": { + "@turf/helpers": "^6.3.0" + } + }, + "@turf/projection": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@turf/projection/-/projection-6.3.0.tgz", + "integrity": "sha512-IpSs7Q6G6xi47ynVlYYVegPLy6Jc0yo3/DcIm83jaJa4NnzPFXIFZT0v9Fe1N8MraHZqiqaSPbVnJXCGwR12lg==", + "requires": { + "@turf/clone": "^6.3.0", + "@turf/helpers": "^6.3.0", + "@turf/meta": "^6.3.0" + } + }, "@types/anymatch": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", @@ -9661,6 +9724,21 @@ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz", "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==" }, + "d3-geo": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.7.1.tgz", + "integrity": "sha512-O4AempWAr+P5qbk2bC2FuN/sDW4z+dN2wDf9QV3bxQt4M5HfOEeXLgJ/UKQW0+o1Dj8BE+L5kiDbdWUMjsmQpw==", + "requires": { + "d3-array": "1" + }, + "dependencies": { + "d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + } + } + }, "d3-hexbin": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/d3-hexbin/-/d3-hexbin-0.2.2.tgz", @@ -23983,6 +24061,11 @@ "safe-buffer": "^5.0.1" } }, + "turf-jsts": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/turf-jsts/-/turf-jsts-1.2.3.tgz", + "integrity": "sha512-Ja03QIJlPuHt4IQ2FfGex4F4JAr8m3jpaHbFbQrgwr7s7L6U8ocrHiF3J1+wf9jzhGKxvDeaCAnGDot8OjGFyA==" + }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", diff --git a/package.json b/package.json index 342c34da..d4792197 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,8 @@ "@material-ui/icons": "^4.9.1", "@material-ui/pickers": "^3.2.10", "@shakacode/recompose": "^0.30.3", + "@turf/buffer": "^6.3.0", + "Leaflet.extra-markers": "git+https://github.com/SemanticComputing/Leaflet.ExtraMarkers.git", "apexcharts": "^3.26.0", "axios": "^0.21.1", "core-js": "^3.8.1", @@ -49,7 +51,6 @@ "leaflet-fullscreen": "^1.0.2", "leaflet-usermarker": "git+https://github.com/SemanticComputing/leaflet-usermarker.git", "leaflet.control.opacity": "^1.3.0", - "Leaflet.extra-markers": "git+https://github.com/SemanticComputing/Leaflet.ExtraMarkers.git", "leaflet.markercluster": "^1.4.1", "leaflet.zoominfo": "git+https://github.com/SemanticComputing/Leaflet.zoominfo.git", "lodash": "^4.17.20", diff --git a/src/client/components/facet_results/LeafletMap.js b/src/client/components/facet_results/LeafletMap.js index 1b2c00eb..9e68721c 100644 --- a/src/client/components/facet_results/LeafletMap.js +++ b/src/client/components/facet_results/LeafletMap.js @@ -4,7 +4,7 @@ import { withStyles } from '@material-ui/core/styles' import intl from 'react-intl-universal' import L from 'leaflet' import { has, orderBy, isEqual } from 'lodash' -// import buffer from '@turf/buffer' +import buffer from '@turf/buffer' import CircularProgress from '@material-ui/core/CircularProgress' import { purple } from '@material-ui/core/colors' import history from '../../History' @@ -97,7 +97,7 @@ class LeafletMap extends React.Component { constructor (props) { super(props) this.state = { - activeOverlays: props.activeOverlays ? props.activeOverlays : [], + activeLayers: props.activeLayers ? props.activeLayers : [], prevZoomLevel: null, mapMode: props.mapMode } @@ -297,9 +297,9 @@ class LeafletMap extends React.Component { fetchDefaultGeoJSONLayers = () => { this.props.clearGeoJSONLayers() - if (this.state.activeOverlays.length > 0 && this.isSafeToLoadLargeLayers()) { + if (this.state.activeLayers.length > 0 && this.isSafeToLoadLargeLayers()) { this.props.fetchGeoJSONLayers({ - layerIDs: this.state.activeOverlays, + layerIDs: this.state.activeLayers, bounds: this.leafletMap.getBounds() }) } @@ -346,17 +346,18 @@ class LeafletMap extends React.Component { initMapEventListeners = () => { // Fired when an overlay is selected using layer controls this.leafletMap.on('overlayadd', event => { - if (event.layer.options.type === 'geoJSON') { - const layerID = event.layer.options.id - // https://www.robinwieruch.de/react-state-array-add-update-remove - this.setState(state => { - return { - activeOverlays: [...state.activeOverlays, layerID] - } - }) + if (event.layer.options.type === 'GeoJSON') { + this.props.clearGeoJSONLayers() if (this.isSafeToLoadLargeLayers()) { + const layerID = event.layer.options.id + // https://www.robinwieruch.de/react-state-array-add-update-remove + this.setState(state => { + return { + activeLayers: [...state.activeLayers, layerID] + } + }) this.props.fetchGeoJSONLayers({ - layerIDs: this.state.activeOverlays, + layerIDs: this.state.activeLayers, bounds: this.leafletMap.getBounds() }) } else { @@ -369,12 +370,12 @@ class LeafletMap extends React.Component { }) // Fired when an overlay is selected using layer controls this.leafletMap.on('overlayremove', event => { - if (event.layer.options.type === 'geoJSON') { + if (event.layer.options.type === 'GeoJSON') { const layerIDremoved = event.layer.options.id this.clearOverlay(layerIDremoved) this.setState(state => { - const activeOverlays = state.activeOverlays.filter(layerID => layerID !== layerIDremoved) - return { activeOverlays } + const activeLayers = state.activeLayers.filter(layerID => layerID !== layerIDremoved) + return { activeLayers } }) } }) @@ -384,18 +385,18 @@ class LeafletMap extends React.Component { }) // Fired when zooming ends this.leafletMap.on('zoomend', () => { - if (this.state.activeOverlays.length > 0 && this.isSafeToLoadLargeLayersAfterZooming()) { + if (this.state.activeLayers.length > 0 && this.isSafeToLoadLargeLayersAfterZooming()) { this.props.fetchGeoJSONLayers({ - layerIDs: this.state.activeOverlays, + layerIDs: this.state.activeLayers, bounds: this.leafletMap.getBounds() }) } }) // Fired when dragging ends this.leafletMap.on('dragend', () => { - if (this.state.activeOverlays.length > 0 && this.isSafeToLoadLargeLayers()) { + if (this.state.activeLayers.length > 0 && this.isSafeToLoadLargeLayers()) { this.props.fetchGeoJSONLayers({ - layerIDs: this.state.activeOverlays, + layerIDs: this.state.activeLayers, bounds: this.leafletMap.getBounds() }) } @@ -410,118 +411,51 @@ class LeafletMap extends React.Component { isSafeToLoadLargeLayers = () => this.leafletMap.getZoom() >= 13 initOverLays = basemaps => { - const fhaArchaeologicalSiteRegistryAreas = L.layerGroup([], { - id: 'arkeologiset_kohteet_alue', - type: 'geoJSON', - source: 'FHA', - // this layer includes only GeoJSON Polygons, define style for them - geoJSONPolygonOptions: { - color: '#dd2c00', - cursor: 'pointer' - // dashArray: '3, 5' - }, - geoJSONPolygonBoundaryOptions: { - color: '#dd2c00', - // cursor: 'pointer', - dashArray: '3, 5' - } - }) - const fhaArchaeologicalSiteRegistryPoints = L.layerGroup([], { - id: 'arkeologiset_kohteet_piste', - type: 'geoJSON', - source: 'FHA', - // this layer includes only GeoJSON points, define style for them - geoJSONMarkerOptions: { - radius: 8, - fillColor: '#dd2c00', - weight: 1, - opacity: 1, - fillOpacity: 0.8 + this.overlayLayers = {} + const opacityLayers = {} + let showOpacityController = false + this.props.layerConfigs.map(config => { + switch (config.type) { + case 'GeoJSON': + this.overlayLayers[intl.get(`leafletMap.externalLayers.${config.id}`)] = + L.layerGroup([], config) + break + case 'WMS': + this.overlayLayers[intl.get(`leafletMap.externalLayers.${config.id}`)] = + L.tileLayer.wms(config.url, { + layers: config.layers, + version: config.version, + minZoom: config.minZoom, + maxZoom: config.maxZoom, + attribution: config.attribution + }) + break + case 'WMTS': { + const wmtsLayer = L.tileLayer(config.url, { + attribution: config.attribution + }) + const translatedLayerID = intl.get(`leafletMap.externalLayers.${config.id}`) + this.overlayLayers[translatedLayerID] = wmtsLayer + if (config.opacityControl) { + opacityLayers[translatedLayerID] = wmtsLayer + showOpacityController = true + } + break + } } }) - // const fhaLidar = L.tileLayer.wms(`${process.env.API_URL}/fha-wms`, { - // layers: 'NBA:lidar', - // version: '1.3.0', - // attribution: 'FHA', - // minZoom: 12, - // maxZoom: 16 - // }) - // const kotusParishes1938 = L.layerGroup([], { - // id: 'kotus:pitajat', - // type: 'geoJSON', - // source: 'kotus', - // // this layer includes only GeoJSON Polygons, define style for them - // geoJSONPolygonOptions: { - // color: '#dd2c00', - // cursor: 'pointer', - // dashArray: '3, 5' - // } - // }) - // const kotusParishesDialecticalRegions = L.layerGroup([], { - // id: 'kotus:rajat-sms-alueet', - // type: 'geoJSON', - // source: 'kotus', - // // this layer includes only GeoJSON Polygons, define style for them - // geoJSONPolygonOptions: { - // color: '#fca903', - // cursor: 'pointer', - // dashArray: '3, 5' - // } - // }) - // const kotusParishesDialecticalSubRegions = L.layerGroup([], { - // id: 'kotus:rajat-sms-alueosat', - // type: 'geoJSON', - // source: 'kotus', - // // this layer includes only GeoJSON Polygons, define style for them - // geoJSONPolygonOptions: { - // color: '#119100', - // cursor: 'pointer', - // dashArray: '3, 5' - // } - // }) - // const kotusParishesDialecticalBorder = L.layerGroup([], { - // id: 'kotus:rajat-lansi-ita', - // type: 'geoJSON', - // source: 'kotus', - // // this layer includes only GeoJSON Polygons, define style for them - // geoJSONPolygonOptions: { - // color: '#2403fc', - // cursor: 'pointer', - // dashArray: '3, 5' - // } - // }) - const karelianMaps = L.tileLayer('https:///mapwarper.onki.fi/mosaics/tile/4/{z}/{x}/{y}.png', { - type: 'tile', - attribution: 'SeCo' - }) - const senateAtlas = L.tileLayer('https:///mapwarper.onki.fi/mosaics/tile/5/{z}/{x}/{y}.png', { - type: 'tile', - attribution: 'SeCo' - }) - this.overlayLayers = { - [intl.get('leafletMap.externalLayers.arkeologiset_kohteet_alue')]: fhaArchaeologicalSiteRegistryAreas, - [intl.get('leafletMap.externalLayers.arkeologiset_kohteet_piste')]: fhaArchaeologicalSiteRegistryPoints, - // [intl.get('leafletMap.externalLayers.fhaLidar')]: fhaLidar, - [intl.get('leafletMap.externalLayers.karelianMaps')]: karelianMaps, - [intl.get('leafletMap.externalLayers.senateAtlas')]: senateAtlas - // [intl.get('leafletMap.externalLayers.kotus:pitajat')]: kotusParishes1938, - // [intl.get('leafletMap.externalLayers.kotus:rajat-sms-alueet')]: kotusParishesDialecticalRegions, - // [intl.get('leafletMap.externalLayers.kotus:rajat-sms-alueosat')]: kotusParishesDialecticalSubRegions, - // [intl.get('leafletMap.externalLayers.kotus:rajat-lansi-ita')]: kotusParishesDialecticalBorder - } // Add default active overlays directly to the map - this.state.activeOverlays.map(overlay => + this.state.activeLayers.map(overlay => this.leafletMap.addLayer(this.overlayLayers[intl.get(`leafletMap.externalLayers.${overlay}`)])) // Add all basemaps and all overlays via the control to the map L.control.layers(basemaps, this.overlayLayers, { collapsed: !this.props.layerControlExpanded }).addTo(this.leafletMap) - const opacityLayers = { - [intl.get('leafletMap.externalLayers.karelianMaps')]: karelianMaps, - [intl.get('leafletMap.externalLayers.senateAtlas')]: senateAtlas + // Create opacity controller if needed + if (showOpacityController) { + this.createOpacitySlider(opacityLayers) } - this.createOpacitySlider(opacityLayers) } populateOverlay = layerObj => { @@ -530,37 +464,33 @@ class LeafletMap extends React.Component { and Layer objects as values */ - // console.log(layerObj.geoJSON) - // const bufferedGeoJSON = buffer(layerObj.geoJSON, 0.2, { units: 'kilometres' }) - // const bufferedGeoJSON = transformScale(layerObj.geoJSON, 0.3) - // console.log(bufferedGeoJSON) const leafletOverlay = this.overlayLayers[intl.get(`leafletMap.externalLayers.${layerObj.layerID}`)] leafletOverlay.clearLayers() + + // Only the layer that is added last is clickable, so add buffer first + if (leafletOverlay.options.buffer) { + const { distance, units, style } = leafletOverlay.options.buffer + const bufferedGeoJSON = buffer(layerObj.geoJSON, distance, { units }) + const leafletGeoJSONBufferLayer = L.geoJSON(bufferedGeoJSON, { + // style for GeoJSON Polygons + style + }) + leafletGeoJSONBufferLayer.addTo(leafletOverlay).addTo(this.leafletMap) + } + + const { geojsonMarkerOptions, geojsonPolygonOptions, createPopup } = leafletOverlay.options const leafletGeoJSONLayer = L.geoJSON(layerObj.geoJSON, { // style for GeoJSON Points pointToLayer: (feature, latlng) => { - return L.circleMarker(latlng, leafletOverlay.options.geojsonMarkerOptions) + return L.circleMarker(latlng, geojsonMarkerOptions) }, // style for GeoJSON Polygons - style: leafletOverlay.options.geoJSONPolygonOptions, + style: geojsonPolygonOptions, // add popups onEachFeature: (feature, layer) => { - layer.bindPopup(this.createPopUpContentGeoJSON(layerObj.layerID, feature.properties)) + layer.bindPopup(createPopup(feature.properties)) } }) - // const leafletGeoJSONBoundaryLayer = L.geoJSON(bufferedGeoJSON, { - // // style for GeoJSON Points - // pointToLayer: (feature, latlng) => { - // return L.circleMarker(latlng, leafletOverlay.options.geojsonMarkerOptions) - // }, - // // style for GeoJSON Polygons - // style: leafletOverlay.options.geoJSONPolygonBoundaryOptions - // // add popups - // // onEachFeature: (feature, layer) => { - // // layer.bindPopup(this.createPopUpContentGeoJSON(layerObj.layerID, feature.properties)) - // // } - // }) - // leafletGeoJSONBoundaryLayer.addTo(leafletOverlay).addTo(this.leafletMap) leafletGeoJSONLayer.addTo(leafletOverlay).addTo(this.leafletMap) } @@ -954,44 +884,6 @@ class LeafletMap extends React.Component { return p } - createPopUpContentGeoJSON = (layerID, properties) => { - if (layerID === 'arkeologiset_kohteet_alue' || layerID === 'arkeologiset_kohteet_piste') { - return this.createPopUpContentGeoJSONFHA(properties) - } else { - return this.createPopUpContentGeoJSONKotus(properties) - } - } - - createPopUpContentGeoJSONFHA = properties => { - let popupText = '' - const name = properties.kohdenimi - ? `<b>Kohteen nimi:</b> ${properties.kohdenimi}</p>` : '' - const type = properties.laji ? `<b>Kohteen tyyppi:</b> ${properties.laji}</p>` : '' - const municipality = properties.kunta ? `<b>Kunta:</b> ${properties.kunta}</p>` : '' - const link = properties.mjtunnus - ? `<a href="https://www.kyppi.fi/to.aspx?id=112.${properties.mjtunnus}" target="_blank">Avaa kohde Muinaisjäännösrekisterissä</a></p>` : '' - popupText += ` - <div> - ${name} - ${type} - ${municipality} - ${link} - </div> - ` - return popupText - } - - createPopUpContentGeoJSONKotus = properties => { - let popupText = '' - const name = `<b>Pitäjän nimi:</b> ${properties.NIMI}</p>` - popupText += ` - <div> - ${name} - </div> - ` - return popupText - } - createInstanceListing = instances => { let root if (Array.isArray(instances)) { diff --git a/src/client/components/perspectives/sampo/Perspective1.js b/src/client/components/perspectives/sampo/Perspective1.js index 42818680..821f164a 100644 --- a/src/client/components/perspectives/sampo/Perspective1.js +++ b/src/client/components/perspectives/sampo/Perspective1.js @@ -53,7 +53,7 @@ const Perspective1 = props => { zoom={2} // locateUser // center={[60.187, 24.821]} - // zoom={15} + // zoom={13} results={props.placesResults.results} layers={props.leafletMapLayers} pageType='facetResults' @@ -73,10 +73,112 @@ const Perspective1 = props => { showInstanceCountInClusters updateFacetOption={props.updateFacetOption} showExternalLayers - // activeOverlays={[ - // 'arkeologiset_kohteet_alue', - // 'arkeologiset_kohteet_piste' - // ]} + layerConfigs={[ + // { + // id: 'arkeologiset_kohteet_alue', + // type: 'GeoJSON', + // minZoom: 13, + // buffer: { + // distance: 200, + // units: 'metres', + // style: { + // color: '#6E6E6E', + // dashArray: '3, 5' + // } + // }, + // // this layer includes only GeoJSON Polygons, define style for them + // geojsonPolygonOptions: { + // color: '#dd2c00', + // cursor: 'pointer' + // }, + // createPopup: data => { + // let html = '' + // const name = data.kohdenimi + // ? `<b>Kohteen nimi:</b> ${data.kohdenimi}</p>` : '' + // const type = data.laji ? `<b>Kohteen tyyppi:</b> ${data.laji}</p>` : '' + // const municipality = data.kunta ? `<b>Kunta:</b> ${data.kunta}</p>` : '' + // const link = data.mjtunnus + // ? `<a href="https://www.kyppi.fi/to.aspx?id=112.${data.mjtunnus}" target="_blank">Avaa kohde Muinaisjäännösrekisterissä</a></p>` : '' + // html += ` + // <div> + // ${name} + // ${type} + // ${municipality} + // ${link} + // </div> + // ` + // return html + // } + // }, + // { + // id: 'arkeologiset_kohteet_piste', + // type: 'GeoJSON', + // minZoom: 13, + // buffer: { + // distance: 200, + // units: 'metres', + // style: { + // color: '#6E6E6E', + // dashArray: '3, 5' + // } + // }, + // // this layer includes only GeoJSON points, define style for them + // geojsonMarkerOptions: { + // radius: 8, + // fillColor: '#dd2c00', + // color: '#000', + // weight: 1, + // opacity: 1, + // fillOpacity: 0.8 + // }, + // createPopup: data => { + // let html = '' + // const name = data.kohdenimi + // ? `<b>Kohteen nimi:</b> ${data.kohdenimi}</p>` : '' + // const type = data.laji ? `<b>Kohteen tyyppi:</b> ${data.laji}</p>` : '' + // const municipality = data.kunta ? `<b>Kunta:</b> ${data.kunta}</p>` : '' + // const link = data.mjtunnus + // ? `<a href="https://www.kyppi.fi/to.aspx?id=112.${data.mjtunnus}" target="_blank">Avaa kohde Muinaisjäännösrekisterissä</a></p>` : '' + // html += ` + // <div> + // ${name} + // ${type} + // ${municipality} + // ${link} + // </div> + // ` + // return html + // } + // }, + // { + // id: 'fhaLidar', + // type: 'WMS', + // url: `${process.env.API_URL}/fha-wms`, + // layers: 'NBA:lidar', + // version: '1.3.0', + // attribution: 'FHA', + // minZoom: 13, + // maxZoom: 16 + // }, + { + id: 'karelianMaps', + type: 'WMTS', + url: 'https:///mapwarper.onki.fi/mosaics/tile/4/{z}/{x}/{y}.png', + opacityControl: true, + attribution: 'Semantic Computing Research Group' + }, + { + id: 'senateAtlas', + type: 'WMTS', + url: 'https:///mapwarper.onki.fi/mosaics/tile/5/{z}/{x}/{y}.png', + opacityControl: true, + attribution: 'Semantic Computing Research Group' + } + ]} + activeLayers={[ + // 'arkeologiset_kohteet_alue' + // 'arkeologiset_kohteet_piste' + ]} layerControlExpanded showError={props.showError} />} diff --git a/src/server/index.js b/src/server/index.js index b2ed76d3..57450331 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -18,6 +18,7 @@ import { fetchGeoJSONLayer } from './wfs/WFSApi' import swaggerUi from 'swagger-ui-express' import { OpenApiValidator } from 'express-openapi-validator' import yaml from 'js-yaml' +import querystring from 'querystring' const DEFAULT_PORT = 3001 const app = express() app.set('port', process.env.PORT || DEFAULT_PORT) @@ -268,6 +269,39 @@ new OpenApiValidator({ } }) + app.get(`${apiPath}/fha-wms`, async (req, res, next) => { + const headers = { + Authorization: `Basic ${process.env.FHA_WMS_BASIC_AUTH}` + } + const { service, request, layers, styles, format, transparent, version, width, height, crs, bbox } = req.query + const mapServerParams = { + service, + request, + layers, + styles, + format, + transparent, + version, + width, + height, + crs, + bbox + } + const url = `http://137.116.207.73/geoserver/ows?${querystring.stringify(mapServerParams)}` + try { + const response = await axios({ + method: 'get', + url, + responseType: 'arraybuffer', + headers + }) + res.end(response.data, 'base64') + } catch (error) { + console.log(error) + next(error) + } + }) + app.get(`${apiPath}/wfs`, async (req, res, next) => { const layerIDs = castArray(req.query.layerID) try { diff --git a/src/server/openapi.yaml b/src/server/openapi.yaml index f5948106..4afd7624 100644 --- a/src/server/openapi.yaml +++ b/src/server/openapi.yaml @@ -404,37 +404,75 @@ paths: application/json: schema: type: array - /nls-wmts: + /fha-wms: get: - summary: Route for password protected WMTS layers. + summary: Route for password protected WMS layers. parameters: - in: query - name: layerID - schema: + name: service + schema: type: string required: true - in: query - name: x - schema: + name: request + schema: + type: string + required: true + - in: query + name: layers + schema: + type: string + required: true + - in: query + name: styles + schema: type: string + allowEmptyValue : true + required: true + - in: query + name: format + schema: + type: string + required: true + - in: query + name: transparent + schema: + type: boolean required: true - in: query - name: y - schema: + name: version + schema: type: string + required: true + - in: query + name: width + schema: + type: number required: true - in: query - name: z - schema: + name: height + schema: + type: number + required: true + - in: query + name: crs + schema: type: string - required: true + required: true + - in: query + name: bbox + schema: + type: string + allowReserved: true + required: true responses: '200': - description: An array of GeoJSON layers. + description: Image content: - application/json: + image/jpeg: schema: - type: array + type: string + format: binary /void/{perspectiveID}: get: summary: Retrieve a VoID description -- GitLab