Mercurial > gemma
changeset 3079:57255fda7594
client: compare surveys on map
The compare survey is now displayed in a second map.
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Thu, 18 Apr 2019 12:40:42 +0200 |
parents | 71129566acdf |
children | 22857a12ed9e |
files | client/src/components/fairway/Profiles.vue client/src/components/layers/Layerselect.vue client/src/components/map/Map.vue client/src/lib/mixins.js client/src/store/application.js client/src/store/fairway.js client/src/store/map.js |
diffstat | 7 files changed, 204 insertions(+), 180 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/components/fairway/Profiles.vue Thu Apr 18 10:17:36 2019 +0200 +++ b/client/src/components/fairway/Profiles.vue Thu Apr 18 12:40:42 2019 +0200 @@ -94,13 +94,17 @@ </select> </div> </div> - <div class="mt-3"> + <div class="mt-3" v-if="additionalSurvey"> <button - :disabled="!additionalSurvey" class="btn btn-info btn-sm w-100" - @click="showSurveyDiffences" + @click="differencesVisible ? showSurvey() : showDifferences()" > - <translate>Show differences</translate> + <translate v-if="differencesVisible" key="showsurvey" + >Show survey</translate + > + <translate v-else key="showdifferences" + >Show differences</translate + > </button> </div> <hr class="w-100 mb-0" /> @@ -375,6 +379,16 @@ .map(coord => parseFloat(coord.trim())) .filter(c => Number(c) === c); return coordinates.length === 4; + }, + differencesVisible() { + return ( + !this.openLayersMap("compare-sounding-results") + .getLayer("BOTTLENECKISOLINE") + .getVisible() && + this.openLayersMap("compare-sounding-results") + .getLayer("DIFFERENCES") + .getVisible() + ); } }, watch: { @@ -387,6 +401,20 @@ this.loadProfile(survey); }, additionalSurvey(survey) { + if (survey) { + this.loadDifferences(); + this.$store.commit("application/addPane", { + id: "compare-sounding-results", + component: "Map" + }); + this.$store.commit("application/paneRotate", 4); + } else { + this.$store.commit( + "application/removePane", + "compare-sounding-results" + ); + this.$store.commit("application/paneRotate", 1); + } this.loadProfile(survey); }, selectedCut(cut) { @@ -396,7 +424,7 @@ } }, methods: { - showSurveyDiffences() { + loadDifferences() { this.$store.commit("fairwayprofile/setDifferencesLoading", true); HTTP.post( "/diff", @@ -411,24 +439,6 @@ } } ) - .then(() => { - this.openLayersMap - .getLayer("DIFFERENCES") - .getSource() - .updateParams({ - cql_filter: - "objnam='" + - this.selectedBottleneck + - "' AND " + - "minuend='" + - this.selectedSurvey.date_info + - "' AND subtrahend='" + - this.additionalSurvey.date_info + - "'" - }); - this.openLayersMap.getLayer("BOTTLENECKISOLINE").setVisible(false); - this.openLayersMap.getLayer("DIFFERENCES").setVisible(true); - }) .catch(error => { const { status, data } = error.response; displayError({ @@ -440,6 +450,22 @@ this.$store.commit("fairwayprofile/setDifferencesLoading", false); }); }, + showDifferences() { + this.openLayersMap("compare-sounding-results") + .getLayer("BOTTLENECKISOLINE") + .setVisible(false); + this.openLayersMap("compare-sounding-results") + .getLayer("DIFFERENCES") + .setVisible(true); + }, + showSurvey() { + this.openLayersMap("compare-sounding-results") + .getLayer("BOTTLENECKISOLINE") + .setVisible(true); + this.openLayersMap("compare-sounding-results") + .getLayer("DIFFERENCES") + .setVisible(false); + }, close() { this.$store.commit("application/showProfiles", false); },
--- a/client/src/components/layers/Layerselect.vue Thu Apr 18 10:17:36 2019 +0200 +++ b/client/src/components/layers/Layerselect.vue Thu Apr 18 12:40:42 2019 +0200 @@ -60,7 +60,7 @@ ]), ...mapGetters("map", ["openLayersMap"]), layer() { - return this.openLayersMap.getLayer(this.layerId); + return this.openLayersMap().getLayer(this.layerId); }, label() { return this.$gettext(this.layer.get("label"));
--- a/client/src/components/map/Map.vue Thu Apr 18 10:17:36 2019 +0200 +++ b/client/src/components/map/Map.vue Thu Apr 18 12:40:42 2019 +0200 @@ -1,24 +1,18 @@ <template> <div - :id="'map-' + uuid" - :class="[ - 'map', - { - splitscreen: this.splitscreen, - nocursor: this.hasActiveInteractions - } - ]" - ></div> + :id="'map-' + paneId" + :class="['map', { nocursor: this.hasActiveInteractions }]" + /> </template> <style lang="sass" scoped> .map width: 100% height: 100% - - &.splitscreen - height: 50% - + 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> @@ -43,14 +37,14 @@ import { Map, View } from "ol"; import { Stroke, Style, Fill } from "ol/style"; import { displayError } from "@/lib/errors"; -import { uuid, pane } from "@/lib/mixins"; +import { pane } from "@/lib/mixins"; import layers from "@/components/map/layers"; import "ol/ol.css"; /* for the sake of debugging */ /* eslint-disable no-console */ export default { - mixins: [uuid, pane], + mixins: [pane], data() { return { map: null, @@ -60,27 +54,62 @@ computed: { ...mapState("map", ["initialLoad", "extent", "syncedView"]), ...mapState("bottlenecks", ["selectedSurvey"]), - ...mapState("application", ["showSplitscreen", "panes", "paneRotate"]), + ...mapState("fairwayprofile", ["additionalSurvey"]), + ...mapState("application", ["panes", "paneRotate"]), ...mapState("imports", ["selectedStretchId"]), layers() { return layers(); }, hasActiveInteractions() { - let active = false; - if (this.map) { + return ( + this.map && this.map .getInteractions() .getArray() - .filter(i => - ["linetool", "polygontool", "cuttool"].includes(i.get("id")) - ) - .forEach(i => { - if (i.getActive()) { - active = true; - } - }); + .filter( + i => + ["linetool", "polygontool", "cuttool"].includes(i.get("id")) && + i.getActive() + ).length + ); + } + }, + watch: { + panes() { + this.$nextTick(() => this.map.updateSize()); + }, + paneRotate() { + this.$nextTick(() => this.map.updateSize()); + }, + 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"); + } } - return active; + }, + additionalSurvey(survey) { + if (this.paneId === "compare-sounding-results") { + if (survey) { + this.updateBottleneckFilter(survey.bottleneck_id, survey.date_info); + } else { + this.updateBottleneckFilter("does_not_exist", "1999-10-01"); + } + } + }, + selectedStretchId(id) { + this.layers + .get("STRETCHES") + .getSource() + .getFeatures() + .forEach(f => { + f.set("highlighted", false); + if (id === f.getId()) { + f.set("highlighted", true); + } + }); } }, methods: { @@ -96,112 +125,88 @@ }); } this.layers.get("BOTTLENECKISOLINE").setVisible(exists); - } - }, - watch: { - showSplitscreen(show) { - if (show) { - setTimeout(() => { - this.splitscreen = true; - }, 350); - } else { - this.splitscreen = false; + }, + initMap() { + if (!this.syncedView) { + this.$store.commit( + "map/syncedView", + new View({ + 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" + }) + ); } - }, - panes() { - this.$nextTick(() => this.map.updateSize()); - }, - paneRotate() { - this.$nextTick(() => this.map.updateSize()); - }, - splitscreen() { - this.$nextTick(() => this.map.updateSize()); - }, - selectedSurvey(newSelectedSurvey) { - if (newSelectedSurvey) { - this.updateBottleneckFilter( - newSelectedSurvey.bottleneck_id, - newSelectedSurvey.date_info - ); - } else { - this.updateBottleneckFilter("does_not_exist", "1999-10-01"); + this.map = new Map({ + layers: this.layers.config, + target: "map-" + this.paneId, + controls: [], + view: this.syncedView + }); + 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); + + // 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/" + currentUser, { + headers: { + "X-Gemma-Auth": localStorage.getItem("token"), + "Content-type": "text/xml; charset=UTF-8" + } + }) + .then(response => { + 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 + }); + }) + .catch(error => { + const { status, data } = error.response; + displayError({ + title: this.$gettext("Backend Error"), + message: `${status}: ${data.message || data}` + }); + }); } - }, - selectedStretchId(id) { - this.layers - .get("STRETCHES") - .getSource() - .getFeatures() - .forEach(f => { - f.set("highlighted", false); - if (id === f.getId()) { - f.set("highlighted", true); - } - }); + + this.$store.dispatch("map/initIdentifyTool", this.map); } }, mounted() { - if (!this.syncedView) { - this.$store.commit( - "map/syncedView", - new View({ - 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" - }) + this.initMap(); + + if (this.selectedSurvey && this.paneId === "main") { + this.updateBottleneckFilter( + this.selectedSurvey.bottleneck_id, + this.selectedSurvey.date_info ); } - this.map = new Map({ - layers: this.layers.config, - target: "map-" + this.uuid, - controls: [], - view: this.syncedView - }); - 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); - - // move to user specific default extent if map loads for the first timeout - // 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/" + currentUser, { - headers: { - "X-Gemma-Auth": localStorage.getItem("token"), - "Content-type": "text/xml; charset=UTF-8" - } - }) - .then(response => { - 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 - }); - }) - .catch(error => { - const { status, data } = error.response; - displayError({ - title: this.$gettext("Backend Error"), - message: `${status}: ${data.message || data}` - }); - }); + if (this.additionalSurvey && this.paneId === "compare-sounding-results") { + this.updateBottleneckFilter( + this.additionalSurvey.bottleneck_id, + this.additionalSurvey.date_info + ); } // load configured bottleneck colors @@ -233,8 +238,6 @@ .catch(error => { console.log(error); }); - - this.$store.dispatch("map/initIdentifyTool", this.map); }, destroyed() { this.$store.commit("map/removeOpenLayersMap", this.map);
--- a/client/src/lib/mixins.js Thu Apr 18 10:17:36 2019 +0200 +++ b/client/src/lib/mixins.js Thu Apr 18 12:40:42 2019 +0200 @@ -11,9 +11,6 @@ * Author(s): * Markus Kottländer <markus.kottlaender@intevation.de> */ - -import * as uuidGen from "uuid"; - const sortTable = { data() { return { @@ -31,14 +28,6 @@ } }; -const uuid = { - computed: { - uuid() { - return uuidGen.v4(); - } - } -}; - const pane = { props: { paneCreated: Function, @@ -65,4 +54,4 @@ } }; -export { sortTable, uuid, pane }; +export { sortTable, pane };
--- a/client/src/store/application.js Thu Apr 18 10:17:36 2019 +0200 +++ b/client/src/store/application.js Thu Apr 18 12:40:42 2019 +0200 @@ -83,8 +83,14 @@ popup: (state, popup) => { state.popup = popup; }, - panes: (state, panes) => { - state.panes = panes; + addPane: (state, pane) => { + state.panes.push(pane); + }, + removePane: (state, paneId) => { + const index = state.panes.findIndex(p => p.id === paneId); + if (index !== -1) { + state.panes.splice(index, 1); + } }, paneRotate: (state, rotate) => { state.paneRotate = rotate;
--- a/client/src/store/fairway.js Thu Apr 18 10:17:36 2019 +0200 +++ b/client/src/store/fairway.js Thu Apr 18 12:40:42 2019 +0200 @@ -219,7 +219,7 @@ Promise.all(profileLoaders) .then(() => { commit("map/cutToolEnabled", false, { root: true }); - const los3 = rootGetters["map/openLayersMap"].getLayer( + const los3 = rootGetters["map/openLayersMap"]().getLayer( "FAIRWAYDIMENSIONSLOS3" ); los3.getSource().forEachFeatureIntersectingExtent( @@ -241,7 +241,7 @@ } } ); - const los2 = rootGetters["map/openLayersMap"].getLayer( + const los2 = rootGetters["map/openLayersMap"]().getLayer( "FAIRWAYDIMENSIONSLOS2" ); los2.getSource().forEachFeatureIntersectingExtent( @@ -263,7 +263,7 @@ } } ); - const los1 = rootGetters["map/openLayersMap"].getLayer( + const los1 = rootGetters["map/openLayersMap"]().getLayer( "FAIRWAYDIMENSIONSLOS1" ); los1.getSource().forEachFeatureIntersectingExtent(
--- a/client/src/store/map.js Thu Apr 18 10:17:36 2019 +0200 +++ b/client/src/store/map.js Thu Apr 18 12:40:42 2019 +0200 @@ -52,8 +52,10 @@ namespaced: true, state: init(), getters: { - openLayersMap: state => { - return state.openLayersMaps.length ? state.openLayersMaps[0] : null; + openLayersMap: state => id => { + return state.openLayersMaps.find( + map => map.getTarget() === "map-" + (id || "main") + ); }, filteredIdentifiedFeatures: state => { return state.identifiedFeatures.filter(f => f.getId()); @@ -486,12 +488,11 @@ } }); }, - moveToBoundingBox({ getters }, { boundingBox, zoom, preventZoomOut }) { + moveToBoundingBox({ state }, { boundingBox, zoom, preventZoomOut }) { const extent = transformExtent(boundingBox, "EPSG:4326", "EPSG:3857"); - let view = getters.openLayersMap.getView(); - const currentZoom = view.getZoom(); + const currentZoom = state.syncedView.getZoom(); zoom = zoom || currentZoom; - view.fit(extent, { + state.syncedView.fit(extent, { maxZoom: preventZoomOut ? Math.max(zoom, currentZoom) : zoom, duration: 700 }); @@ -500,13 +501,12 @@ const boundingBox = bbox(feature.geometry); dispatch("moveToBoundingBox", { boundingBox, zoom, preventZoomOut }); }, - moveMap({ getters }, { coordinates, zoom, preventZoomOut }) { - let view = getters.openLayersMap.getView(); - const currentZoom = view.getZoom(); + moveMap({ state }, { coordinates, zoom, preventZoomOut }) { + const currentZoom = state.syncedView.getZoom(); zoom = zoom || currentZoom; - view.animate({ + state.syncedView.animate({ zoom: preventZoomOut ? Math.max(zoom, currentZoom) : zoom, - center: fromLonLat(coordinates, view.getProjection()), + center: fromLonLat(coordinates, state.syncedView.getProjection()), duration: 700 }); }