Mercurial > gemma
view client/src/components/map/Map.vue @ 5560:f2204f91d286
Join the log lines of imports to the log exports to recover data from them.
Used in SR export to extract information that where in the meta json
but now are only found in the log.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 09 Feb 2022 18:34:40 +0100 |
parents | fb3e127bccb4 |
children | 84d01a536bec |
line wrap: on
line source
<template> <div :id="'map-' + paneId" :class="['map', { nocursor: this.hasActiveInteractions }]" > <Zoom :map="map" /> </div> </template> <style lang="sass" scoped> .map width: 100% height: 100% background-color: #eee background-image: linear-gradient(45deg, #e8e8e8 25%, transparent 25%, transparent 75%, #e8e8e8 75%, #e8e8e8), linear-gradient(45deg, #e8e8e8 25%, transparent 25%, transparent 75%, #e8e8e8 75%, #e8e8e8) background-size: 20px 20px background-position: 0 0, 10px 10px &.nocursor cursor: none </style> <script> /* This is Free Software under GNU Affero General Public License v >= 3.0 * without warranty, see README.md and license for details. * * SPDX-License-Identifier: AGPL-3.0-or-later * License-Filename: LICENSES/AGPL-3.0.txt * * Copyright (C) 2018, 2019 by via donau * – Österreichische Wasserstraßen-Gesellschaft mbH * Software engineering by Intevation GmbH * * Author(s): * * Thomas Junk <thomas.junk@intevation.de> * * Bernhard E. Reiter <bernhard.reiter@intevation.de> */ /*eslint no-unused-vars: ["error", { "argsIgnorePattern": "_" }]*/ import { HTTP } from "@/lib/http"; import { mapState } from "vuex"; import { Map, View } from "ol"; import { Stroke, Style, Fill } from "ol/style"; import { displayError } from "@/lib/errors"; import { pane } from "@/lib/mixins"; import { layerFactory } from "@/components/layers/layers"; import { ImageWMS as ImageSource } from "ol/source"; import { styles } from "@/components/layers/styles"; import "ol/ol.css"; export default { mixins: [pane], components: { Zoom: () => import("@/components/map/Zoom") }, data() { return { map: null }; }, computed: { ...mapState("map", [ "initialLoad", "extent", "syncedMaps", "syncedView", "ongoingRefresh" ]), ...mapState("bottlenecks", ["selectedSurvey"]), ...mapState("fairwayprofile", ["additionalSurvey"]), ...mapState("application", [ "paneSetup", "paneRotate", "config", "ongoingPDFExport" ]), ...mapState("imports", ["selectedStretchId", "selectedSectionId"]), layers() { return layerFactory(this.paneId); }, hasActiveInteractions() { return ( this.map && this.map .getInteractions() .getArray() .filter( i => ["linetool", "polygontool", "cuttool"].includes(i.get("id")) && i.getActive() ).length ); } }, watch: { ongoingRefresh() { if (this.ongoingRefresh) return; this.loadStyles(); }, paneSetup() { this.$nextTick(() => this.map.updateSize()); }, paneRotate() { this.$nextTick(() => this.map.updateSize()); }, syncedMaps(syncedMaps) { if (syncedMaps.includes(this.paneId) || this.paneId === "main") { this.map.setView(this.syncedView); } else { this.map.setView( new View({ enableRotation: false, center: [this.extent.lon, this.extent.lat], minZoom: 5, // restrict zooming out to ~size of Europe for width 1000px zoom: this.extent.zoom, projection: "EPSG:3857" }) ); } }, selectedSurvey(survey) { if (this.paneId === "main") { if (survey) { this.updateBottleneckFilter(survey.bottleneck_id, survey.date_info); } else { this.updateBottleneckFilter("does_not_exist", "1999-10-01"); } } }, additionalSurvey(survey) { if (this.paneId === "compare-survey") { if (survey) { this.updateBottleneckFilter(survey.bottleneck_id, survey.date_info); } else { this.updateBottleneckFilter("does_not_exist", "1999-10-01"); } } }, selectedStretchId(id) { let stretch = this.layers.get("STRETCHES"); stretch .getSource() .getFeatures() .forEach(f => { f.set("highlighted", false); f.setStyle(null); if (id === f.getId()) { f.set("highlighted", true); let highlight = new Style({ fill: new Fill({ color: this.colorLuminance( stretch .getStyle() .getFill() .getColor(), 0.3 ) }), stroke: new Stroke({ color: this.colorLuminance( stretch .getStyle() .getStroke() .getColor(), 0.3 ), width: 3 }) }); f.setStyle(highlight); } }); }, selectedSectionId(id) { let section = this.layers.get("SECTIONS"); section .getSource() .getFeatures() .forEach(f => { f.set("highlighted", false); if (id === f.getId()) { f.set("highlighted", true); let highlight = new Style({ fill: new Fill({ color: this.colorLuminance( section .getStyle() .getFill() .getColor(), 0.3 ) }), stroke: new Stroke({ color: this.colorLuminance( section .getStyle() .getStroke() .getColor(), 0.3 ), width: 4 }) }); f.setStyle(highlight); } }); } }, methods: { colorLuminance(color, lum) { let [r, g, b, a] = color .substring(5, color.length - 1) .split(",") .map(e => Number(e)); let [r1, g1, b1] = [r, g, b].map(e => Math.round(Math.min(Math.max(0, e + e * lum), 255)) ); return `rgba(${r1},${g1},${b1},${a})`; }, updateBottleneckFilter(bottleneck_id, datestr) { if (!bottleneck_id) return; const exists = bottleneck_id != "does_not_exist"; if (exists) { this.layers .get("BOTTLENECKISOLINE") .getSource() .updateParams({ cql_filter: `date_info='${datestr}' AND bottleneck_id='${bottleneck_id}'` }); } this.layers.get("BOTTLENECKISOLINE").setVisible(exists); }, initMap() { if (!this.syncedView) { this.$store.commit( "map/syncedView", new View({ enableRotation: false, center: [this.extent.lon, this.extent.lat], minZoom: 5, // restrict zooming out to ~size of Europe for width 1000px zoom: this.extent.zoom, projection: "EPSG:3857" }) ); } // move to user specific default extent if map loads for the first time // checking initialLoad will be obsolete once we abandoned the separated admin context if (this.initialLoad) { this.$store.commit("map/initialLoad", false); var currentUser = this.$store.state.user.user; HTTP.get("/users/" + encodeURIComponent(`${currentUser}`), { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } }) .then(response => { this.mountMap(); this.$store.dispatch("map/moveToBoundingBox", { boundingBox: [ response.data.extent.x1, response.data.extent.y1, response.data.extent.x2, response.data.extent.y2 ], zoom: 17, preventZoomOut: true, duration: 0 }); }) .catch(error => { this.mountMap(); let message = "Backend not reachable"; if (error.response) { const { status, data } = error.response; message = `${status}: ${data.message || data}`; } displayError({ title: this.$gettext("Backend Error"), message: message }); }); } else { this.mountMap(); } }, mountMap() { const source = new ImageSource({ preload: 1, url: this.config.ecdis_wms_url, crossOrigin: "anonymous", params: JSON.parse(this.config.ecdis_wms_params) }); source.on("imageloaderror", _ => { if (this.ongoingPDFExport) { displayError({ title: this.$gettext("Loading Error"), message: this.$gettext( "The ECDIS chart could not be loaded completely, the map might be corrupted. Please retry later" ), options: { timeout: 0, showProgressBar: false, closeOnClick: true, pauseOnHover: true, bodyMaxLength: 1024 } }); } }); this.layers.get("INLANDECDIS").setSource(source); this.map = new Map({ layers: this.layers.config, target: "map-" + this.paneId, controls: [], view: this.syncedMaps.includes(this.paneId) || this.paneId === "main" ? this.syncedView : new View({ center: [this.extent.lon, this.extent.lat], minZoom: 5, zoom: this.extent.zoom, projection: "EPSG:3857" }) }); this.map.getLayer = id => this.layers.get(id); // store map position on every move // will be obsolete once we abandoned the separated admin context this.map.on("moveend", event => { const center = event.map.getView().getCenter(); this.$store.commit("map/extent", { lat: center[1], lon: center[0], zoom: event.map.getView().getZoom() }); }); this.$store.dispatch("map/openLayersMap", this.map); this.$store.dispatch("map/initIdentifyTool", this.map); }, loadStyles() { const getRGBA = color => { return ( "rgba(" + parseInt(color.slice(1, 3), 16) + ", " + parseInt(color.slice(3, 5), 16) + ", " + parseInt(color.slice(5, 7), 16) + ", " + (color.length > 7 ? parseInt(color.slice(7, 9), 16) / 255 : "1") + ")" ); }; // load configured bottleneck colors HTTP.get("/system/settings", { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }).then(response => { let btlnStrokeC = getRGBA(response.data.bottlenecks_stroke), btlnFillC = getRGBA(response.data.bottlenecks_fill), strFillC = getRGBA(response.data.stretches_fill), strStrokeC = getRGBA(response.data.stretches_stroke), secStrokeC = getRGBA(response.data.sections_stroke), secFillC = getRGBA(response.data.sections_fill), fwd1StrokeC = getRGBA(response.data.fairwaydimensionslos1_stroke), fwd1FillC = getRGBA(response.data.fairwaydimensionslos1_fill), fwd2StrokeC = getRGBA(response.data.fairwaydimensionslos2_stroke), fwd2FillC = getRGBA(response.data.fairwaydimensionslos2_fill), fwd3StrokeC = getRGBA(response.data.fairwaydimensionslos3_stroke), fwd3FillC = getRGBA(response.data.fairwaydimensionslos3_fill), wwpStokeC = getRGBA(response.data.waterwayprofiles_stroke); let btlnStyle = new Style({ stroke: new Stroke({ color: btlnStrokeC, width: 4 }), fill: new Fill({ color: btlnFillC }) }), strStyle = new Style({ stroke: new Stroke({ color: strStrokeC, width: 2 }), fill: new Fill({ color: strFillC }) }), secStyle = new Style({ stroke: new Stroke({ color: secStrokeC, width: 5 }), fill: new Fill({ color: secFillC }) }), fwd1Style = new Style({ stroke: new Stroke({ lineDash: [2, 4], lineCap: "round", color: fwd1StrokeC, width: 2 }), fill: new Fill({ color: fwd1FillC }) }), fwd2Style = new Style({ stroke: new Stroke({ lineDash: [3, 6], lineCap: "round", color: fwd2StrokeC, width: 2 }), fill: new Fill({ color: fwd2FillC }) }), fwd3Style = new Style({ stroke: new Stroke({ color: fwd3StrokeC, width: 2 }), fill: new Fill({ color: fwd3FillC }) }), wwpStyle = new Style({ stroke: new Stroke({ color: wwpStokeC, lineDash: [5, 5], width: 2 }) }); this.layers.get("WATERWAYPROFILES").setStyle(wwpStyle); this.layers .get("FAIRWAYDIMENSIONSLOS1") .setStyle(() => [fwd1Style, styles.textFW1]); this.layers .get("FAIRWAYDIMENSIONSLOS2") .setStyle(() => [fwd2Style, styles.textFW2]); this.layers .get("FAIRWAYDIMENSIONSLOS3") .setStyle(() => [fwd3Style, styles.textFW3]); this.layers.get("SECTIONS").setStyle(secStyle); this.layers.get("STRETCHES").setStyle(strStyle); this.layers.get("BOTTLENECKS").setStyle(btlnStyle); this.$store.commit("gauges/deleteNashSutcliffeCache"); this.$store.dispatch("map/refreshLayers"); }); } }, mounted() { // ToDo set path to correct endpoint in order to retrieve an OSM URL HTTP.get("/system/config", { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }) .then(response => { if (response.data["osm-url"]) { this.layers .get("OPENSTREETMAP") .getSource() .setUrl(response.data["osm-url"]); } this.initMap(); if (this.selectedSurvey && this.paneId === "main") { this.updateBottleneckFilter( this.selectedSurvey.bottleneck_id, this.selectedSurvey.date_info ); } if (this.additionalSurvey && this.paneId === "compare-survey") { this.updateBottleneckFilter( this.additionalSurvey.bottleneck_id, this.additionalSurvey.date_info ); } this.loadStyles(); }) .catch(error => { let message = "Backend not reachable"; if (error.response) { const { status, data } = error.response; message = `${status}: ${data.message || data}`; } displayError({ title: this.$gettext("Backend Error"), message: message }); }); }, destroyed() { this.$store.commit("map/removeOpenLayersMap", this.map); } }; </script>