diff --git a/app/package-lock.json b/app/package-lock.json index 9478a726ea..5de4215126 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -36,7 +36,7 @@ "luxon": "^1.28.1", "marked": "^4.0.10", "medium-zoom": "^1.0.6", - "ol": "^9.1.0", + "ol": "^9.2.4", "ol-mapbox-style": "^11.0.0", "proj4": "^2.8.0", "regl": "^2.1.0", @@ -14820,9 +14820,9 @@ "dev": true }, "node_modules/ol": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/ol/-/ol-9.1.0.tgz", - "integrity": "sha512-nDrkJ2tzZNpo/wzN/PpHV5zdxbnXZaFktoMaD2cFLEc6gCwlgLY21Yd8wnt/4FjaVYwLBnbN9USXSwIBGcyksQ==", + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/ol/-/ol-9.2.4.tgz", + "integrity": "sha512-bsbu4ObaAlbELMIZWnYEvX4Z9jO+OyCBshtODhDKmqYTPEfnKOX3RieCr97tpJkqWTZvyV4tS9UQDvHoCdxS+A==", "dependencies": { "color-rgba": "^3.0.0", "color-space": "^2.0.1", @@ -33547,9 +33547,9 @@ "dev": true }, "ol": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/ol/-/ol-9.1.0.tgz", - "integrity": "sha512-nDrkJ2tzZNpo/wzN/PpHV5zdxbnXZaFktoMaD2cFLEc6gCwlgLY21Yd8wnt/4FjaVYwLBnbN9USXSwIBGcyksQ==", + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/ol/-/ol-9.2.4.tgz", + "integrity": "sha512-bsbu4ObaAlbELMIZWnYEvX4Z9jO+OyCBshtODhDKmqYTPEfnKOX3RieCr97tpJkqWTZvyV4tS9UQDvHoCdxS+A==", "requires": { "color-rgba": "^3.0.0", "color-space": "^2.0.1", diff --git a/app/package.json b/app/package.json index ff9f7959e8..6d0b0e3d46 100644 --- a/app/package.json +++ b/app/package.json @@ -43,7 +43,7 @@ "luxon": "^1.28.1", "marked": "^4.0.10", "medium-zoom": "^1.0.6", - "ol": "^9.1.0", + "ol": "^9.2.4", "ol-mapbox-style": "^11.0.0", "proj4": "^2.8.0", "regl": "^2.1.0", diff --git a/app/src/components/OLExportButton.vue b/app/src/components/OLExportButton.vue index 96c3866eb9..38efe32496 100644 --- a/app/src/components/OLExportButton.vue +++ b/app/src/components/OLExportButton.vue @@ -117,6 +117,11 @@ import { } from 'vuex'; import { getUid } from 'ol/util'; import { toLonLat } from 'ol/proj'; +import LayerGroup from 'ol/layer/Group'; +import TileLayer from 'ol/layer/Tile'; +import { TileWMS, WMTS, XYZ } from 'ol/source'; +import VectorSource from 'ol/source/Vector'; +import { GeoJSON, MVT, WKB } from 'ol/format'; export default { mixins: [dialogMixin], @@ -170,13 +175,11 @@ Text describing the current step of the tour and why it is interesting what the // Extract completely flat layers array without groups const layers = []; layerArray.map((l) => { - if (l.constructor.name.includes('Group')) { + if (l instanceof LayerGroup) { layers.push(this.extractLayerConfig(l.getLayersArray())); - } else if (l.constructor.name.includes('STACLayer')) { - layers.push(l.get('_jsonDefinition')); - } else { + } else if (l instanceof TileLayer) { const layerConfig = { - type: l.constructor.name.replace('Layer', ''), + type: 'Tile', properties: { id: l.get('configId') ? l.get('configId') : getUid(l), }, @@ -185,28 +188,60 @@ Text describing the current step of the tour and why it is interesting what the const olsource = l.getSource(); // only export visible layers if (olsource && l.isVisible()) { + // Find correct type + let foundType; + if (olsource instanceof XYZ) { + foundType = 'XYZ'; + } + if (olsource instanceof TileWMS) { + foundType = 'TileWMS'; + } + if (olsource instanceof VectorSource) { + foundType = 'VectorSource'; + } + if (olsource instanceof WMTS) { + foundType = 'WMTS'; + } // Extract source config const source = { - type: l.getSource().constructor.name.replace('Source', ''), + type: foundType, }; - if (['XYZ', 'TileWMS', 'WMS'].includes(olsource.constructor.name)) { + if (['XYZ', 'TileWMS', 'WMTS'].includes(foundType)) { if ('url' in olsource) { source.url = olsource.url; } else if ('urls' in olsource) { source.urls = olsource.urls; } - } else if (olsource.constructor.name === 'VectorSource') { + } else if (foundType === 'VectorSource') { source.url = olsource.getUrl(); - source.format = olsource.getFormat()?.constructor.name; + let vsf; + const olformat = olsource.getFormat(); + if (olformat instanceof GeoJSON) { + vsf = 'GeoJSON'; + } + if (olformat instanceof MVT) { + vsf = 'MVT'; + } + if (olformat instanceof WKB) { + vsf = 'WKB'; + } + if (vsf) { + source.format = vsf; + } } // Extract possible other configuration options - if (['TileWMS', 'WMS'].includes(olsource.constructor.name)) { + if (['TileWMS'].includes(foundType)) { source.params = olsource.getParams(); source.serverType = olsource.serverType_; } - if (olsource.constructor.name === 'VectorSource') { - // TODO: the getStyle function does not return the applied style as described in OL docs - layerConfig.style = ''; // l.getStyle(); + if (['WMTS'].includes(foundType)) { + source.layer = olsource.getLayer(); + source.format = olsource.getFormat(); + source.matrixSet = olsource.getMatrixSet(); + // TODO: i think we also need to have information on tilegrid here + } + if (foundType === 'VectorSource') { + layerConfig.style = l.getStyle(); } if (l.getOpacity() !== 1) { layerConfig.opacity = l.getOpacity(); diff --git a/app/src/components/map/MapOverlay.vue b/app/src/components/map/MapOverlay.vue index 79ef2f113d..232cac111b 100644 --- a/app/src/components/map/MapOverlay.vue +++ b/app/src/components/map/MapOverlay.vue @@ -57,6 +57,33 @@ export default { }); map.addOverlay(overlay); this.overlay = overlay; + // TODO: i imagine we don't really want to be injecting the style but this is + // the solution that seemed to work best right now + const style = document.createElement('style'); + style.innerHTML = `.tooltip { + padding: 1px 10px 1px 10px; + margin: 0px; + border-radius: 5px; + position: relative; + font-size: 14px; + box-shadow: none !important; + background: rgba(0, 0, 0, 0.8) !important; + color: #FFFFFF !important; + } + .tooltip:after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 0; + border: 10px solid transparent; + border-top-color: rgba(0, 0, 0, 0.6); + border-bottom: 0; + margin-left: -10px; + margin-bottom: -10px; + }`; + this.$parent.$refs.mapContainer.shadowRoot.appendChild(style); }, methods: {}, beforeDestroy() { diff --git a/app/src/config/trilateral.js b/app/src/config/trilateral.js index 6b645a02cf..0000aed983 100644 --- a/app/src/config/trilateral.js +++ b/app/src/config/trilateral.js @@ -315,16 +315,9 @@ export const layerNameMapping = Object.freeze({ }; return mapping[eoID]; }, - features: { - name: 'Ship detections', - dateFormatFunction: (date) => DateTime.fromISO(date).toFormat('yyyy_MM_dd'), - url: 'https://8ib71h0627.execute-api.us-east-1.amazonaws.com/v1/detections/ship/{site}/{featuresTime}.geojson', - allowedParameters: ['verified'], - }, }, airports: { url: 'https://8ib71h0627.execute-api.us-east-1.amazonaws.com/v1/planet/{z}/{x}/{y}?date={time}&site={site}', - name: 'Throughput at principal hub airports', protocol: 'xyz', tileSize: 256, dateFormatFunction: (date) => DateTime.fromISO(date).toFormat('yyyy_MM_dd'), @@ -348,12 +341,6 @@ export const layerNameMapping = Object.freeze({ }; return mapping[eoID]; }, - features: { - name: 'Plane detections', - dateFormatFunction: (date) => DateTime.fromISO(date).toFormat('yyyy_MM_dd'), - url: 'https://8ib71h0627.execute-api.us-east-1.amazonaws.com/v1/detections/plane/{site}/{featuresTime}.geojson', - allowedParameters: ['Country', 'label', 'score'], - }, }, water_quality_chl: { url: 'https://8ib71h0627.execute-api.us-east-1.amazonaws.com/v1/{z}/{x}/{y}@1x?url=s3://covid-eo-data/{site}-{time}.tif&resampling_method=bilinear&bidx=1&rescale=-100%2C100&color_map=rdbu_r', @@ -1313,7 +1300,7 @@ export const globalIndicators = [ { properties: { indicatorObject: { - indicator: 'sen4ama', + indicator: 'MCD', display: { baseLayers: cloudlessBaseLayerDefault, baseUrl: `https://services.sentinel-hub.com/ogc/wms/${shConfig.shInstanceId}`,