Mercurial > gemma
changeset 1143:846e336d8ee5
merge
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Mon, 12 Nov 2018 15:00:45 +0100 |
parents | dc3f0277628a (current diff) a473d91b0856 (diff) |
children | 5f98d0c9d738 |
files | client/src/application/Sidebar.vue client/src/application/Topbar.vue client/src/bottlenecks/Bottlenecks.vue client/src/linetool/Linetool.vue client/src/map/Maplayer.vue |
diffstat | 18 files changed, 320 insertions(+), 251 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/App.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/App.vue Mon Nov 12 15:00:45 2018 +0100 @@ -15,8 +15,8 @@ <div class="bottomcontainer d-flex flex-row align-items-end"> <Userbar></Userbar> <Morphtool v-if="routeName == 'mainview'"></Morphtool> - <Linetool v-if="routeName == 'mainview'"></Linetool> <Pdftool v-if="routeName == 'mainview'"></Pdftool> + <Drawtool v-if="routeName == 'mainview'"></Drawtool> </div> <Zoom v-if="routeName == 'mainview'"></Zoom> </div> @@ -26,7 +26,7 @@ </div> </template> -<style lang="scss"> +<style lang="scss" scoped> html { height: 100%; width: 100%; @@ -115,7 +115,7 @@ Bottlenecks: () => import("./bottlenecks/Bottlenecks"), Topbar: () => import("./application/Topbar"), Userbar: () => import("./application/Userbar"), - Linetool: () => import("./linetool/Linetool"), + Drawtool: () => import("./drawtool/Drawtool"), Morphtool: () => import("./morphtool/Morphtool"), Pdftool: () => import("./pdftool/Pdftool"), Zoom: () => import("./zoom/zoom")
--- a/client/src/application/Main.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/application/Main.vue Mon Nov 12 15:00:45 2018 +0100 @@ -15,7 +15,7 @@ </div> </template> -<style lang="scss"> +<style lang="scss" scoped> .profile { background-color: white; height: 50vh;
--- a/client/src/application/Sidebar.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/application/Sidebar.vue Mon Nov 12 15:00:45 2018 +0100 @@ -81,7 +81,7 @@ }; </script> -<style lang="scss"> +<style lang="scss" scoped> .menupoints { text-align: left; }
--- a/client/src/application/Topbar.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/application/Topbar.vue Mon Nov 12 15:00:45 2018 +0100 @@ -30,7 +30,7 @@ </div> </template> -<style lang="scss"> +<style lang="scss" scoped> .searchgroup { width: 90%; }
--- a/client/src/application/Userbar.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/application/Userbar.vue Mon Nov 12 15:00:45 2018 +0100 @@ -10,7 +10,7 @@ </div> </template> -<style lang="scss"> +<style lang="scss" scoped> .userpic { background: white; position: absolute;
--- a/client/src/bottlenecks/Bottlenecks.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/bottlenecks/Bottlenecks.vue Mon Nov 12 15:00:45 2018 +0100 @@ -217,7 +217,7 @@ }; </script> -<style lang="scss"> +<style lang="scss" scoped> .bottlenecks { position: absolute; z-index: -2;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/drawtool/Drawtool.vue Mon Nov 12 15:00:45 2018 +0100 @@ -0,0 +1,226 @@ +<template> + <div class="d-flex flex-column"> + <div @click="toggleLineMode" class="ui-element d-flex shadow drawtool"> + <i :class="['fa fa-pencil', {inverted: drawMode === 'LineString'}]"></i> + </div> + <div @click="togglePolygonMode" class="ui-element d-flex shadow drawtool"> + <i :class="['fa fa-edit', {inverted: drawMode === 'Polygon'}]"></i> + </div> + <div @click="toggleCutMode" class="ui-element d-flex shadow drawtool" v-if="selectedSurvey"> + <i :class="['fa fa-area-chart', {inverted: cutMode}]"></i> + </div> + </div> +</template> + +<style lang="sass" scoped> +.drawtool + background-color: white + padding: $small-offset + border-radius: $border-radius + margin-left: $offset + height: $icon-width + width: $icon-height + margin-bottom: $offset + margin-right: $offset + z-index: 2 + +.inverted + color: #0077ff +</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 by via donau + * – Österreichische Wasserstraßen-Gesellschaft mbH + * Software engineering by Intevation GmbH + * + * Author(s): + * Thomas Junk <thomas.junk@intevation.de> + * Markus Kottländer <markus.kottlaender@intevation.de> + */ +import { mapState, mapGetters } from "vuex"; +import { getLength, getArea } from "ol/sphere.js"; +import LineString from "ol/geom/LineString.js"; +import Draw from "ol/interaction/Draw.js"; +import { displayError } from "../application/lib/errors.js"; +import { calculateFairwayCoordinates } from "../application/lib/geo.js"; + +const DEMODATA = 2.5; + +export default { + name: "drawtool", + computed: { + ...mapGetters("map", ["getLayerByName"]), + ...mapState("map", ["drawMode", "drawTool", "cutMode", "cutTool", "openLayersMap"]), + ...mapState("bottlenecks", ["selectedSurvey"]) + }, + methods: { + toggleLineMode() { + this.disableDrawTool(); + this.disableCutTool(); + this.$store.commit("map/drawMode", this.drawMode !== "LineString" ? "LineString" : null); + this.$store.commit("map/cutMode", null); + if (this.drawMode) this.enableDrawTool(); + }, + togglePolygonMode() { + this.disableDrawTool(); + this.disableCutTool(); + this.$store.commit("map/drawMode", this.drawMode !== "Polygon" ? "Polygon" : null); + this.$store.commit("map/cutMode", null); + if (this.drawMode) this.enableDrawTool(); + }, + toggleCutMode() { + this.disableCutTool(); + this.disableDrawTool(); + this.$store.commit('map/cutMode', !this.cutMode); + this.$store.commit("map/drawMode", null); + if (this.cutMode) this.enableCutTool(); + }, + enableDrawTool() { + const drawVectorSrc = this.getLayerByName("Draw Tool").data.getSource(); + drawVectorSrc.clear(); + const drawTool = new Draw({ + source: drawVectorSrc, + type: this.drawMode, + maxPoints: this.drawMode === "LineString" ? 2 : 50 + }); + drawTool.on("drawstart", () => { + drawVectorSrc.clear(); + this.$store.commit("map/setCurrentMeasurement", null); + // we are not setting an id here, to avoid the regular identify to + // pick it up + // event.feature.setId("drawn.1"); // unique id for new feature + }); + drawTool.on("drawend", this.drawEnd); + this.$store.commit("map/drawTool", drawTool); + this.openLayersMap.addInteraction(drawTool); + }, + disableDrawTool() { + this.$store.commit("map/setCurrentMeasurement", null); + this.getLayerByName("Draw Tool").data.getSource().clear(); + this.openLayersMap.removeInteraction(this.drawTool); + this.$store.commit("map/drawTool", null); + }, + drawEnd(event) { + if (this.drawMode === "Polygon") { + const areaSize = getArea(event.feature.getGeometry()); + // also place the a rounded areaSize in a property, + // so identify will show it + this.$store.commit("map/setCurrentMeasurement", { + quantity: "Area", + unitSymbol: areaSize > 100000 ? "km²" : "m²", + value: areaSize > 100000 + ? Math.round(areaSize / 1000) / 1000 // convert into 1 km² == 1000*1000 m² and round to 1000 m² + : Math.round(areaSize) + }); + } + if (this.drawMode === "LineString") { + const length = getLength(event.feature.getGeometry()); + this.$store.commit("map/setCurrentMeasurement", { + quantity: "Length", + unitSymbol: "m", + value: Math.round(length * 10) / 10 + }); + } + }, + enableCutTool() { + const cutVectorSrc = this.getLayerByName("Cut Tool").data.getSource(); + cutVectorSrc.clear(); + const cutTool = new Draw({ + source: cutVectorSrc, + type: "LineString", + maxPoints: 2 + }); + cutTool.on("drawstart", () => { + cutVectorSrc.clear(); + // we are not setting an id here, to avoid the regular identify to + // pick it up + // event.feature.setId("drawn.1"); // unique id for new feature + }); + cutTool.on("drawend", this.cutEnd); + this.$store.commit("map/cutTool", cutTool); + this.openLayersMap.addInteraction(cutTool); + }, + disableCutTool() { + this.$store.commit("map/setCurrentMeasurement", null); + this.getLayerByName("Cut Tool").data.getSource().clear(); + this.openLayersMap.removeInteraction(this.cutTool); + this.$store.commit("map/cutTool", null); + }, + cutEnd(event) { + const length = getLength(event.feature.getGeometry()); + this.$store.commit("map/setCurrentMeasurement", { + quantity: "Length", + unitSymbol: "m", + value: Math.round(length * 10) / 10 + }); + + // if a survey has been selected, request a profile + // TODO an improvement could be to check if the line intersects + // with the bottleneck area's polygon before trying the server request + if (this.selectedSurvey) { + this.$store.commit("fairwayprofile/clearCurrentProfile"); + console.log("requesting profile for", this.selectedSurvey); + const inputLineString = event.feature.getGeometry().clone(); + inputLineString.transform("EPSG:3857", "EPSG:4326"); + const [start, end] = inputLineString + .getCoordinates() + .map(coords => coords.map(coord => parseFloat(coord.toFixed(8)))); + this.$store.commit("fairwayprofile/setStartPoint", start); + this.$store.commit("fairwayprofile/setEndPoint", end); + const profileLine = new LineString([start, end]); + this.$store + .dispatch("fairwayprofile/loadProfile", this.selectedSurvey) + .then(() => { + var vectorSource = this.getLayerByName( + "Fairway Dimensions" + ).data.getSource(); + this.calculateIntersection(vectorSource, profileLine); + }) + .then(() => { + this.$store.commit("application/showSplitscreen", true); + }) + .catch(error => { + const { status, data } = error.response; + displayError({ + title: "Backend Error", + message: `${status}: ${data.message || data}` + }); + }); + } + }, + calculateIntersection(vectorSource, profileLine) { + const transformedLine = profileLine + .clone() + .transform("EPSG:4326", "EPSG:3857") + .getExtent(); + const featureCallback = feature => { + // transform back to prepare for usage + var intersectingPolygon = feature + .getGeometry() + .clone() + .transform("EPSG:3857", "EPSG:4326"); + const fairwayCoordinates = calculateFairwayCoordinates( + profileLine, + intersectingPolygon, + DEMODATA + ); + this.$store.commit( + "fairwayprofile/setFairwayCoordinates", + fairwayCoordinates + ); + }; + vectorSource.forEachFeatureIntersectingExtent( + // need to use EPSG:3857 which is the proj of vectorSource + transformedLine, + featureCallback + ); + }, + } +}; +</script>
--- a/client/src/identify/Identify.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/identify/Identify.vue Mon Nov 12 15:00:45 2018 +0100 @@ -39,7 +39,7 @@ </div> </template> -<style lang="scss"> +<style lang="scss" scoped> .features { max-height: $identify-height; overflow-y: auto;
--- a/client/src/layers/Layers.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/layers/Layers.vue Mon Nov 12 15:00:45 2018 +0100 @@ -19,7 +19,7 @@ </div> </template> -<style lang="scss"> +<style lang="scss" scoped> .layerselectmenu { position: relative; margin-right: $offset;
--- a/client/src/layers/Layerselect.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/layers/Layerselect.vue Mon Nov 12 15:00:45 2018 +0100 @@ -11,7 +11,7 @@ </div> </template> -<style lang="scss"> +<style lang="scss" scoped> .selection { text-align: left; }
--- a/client/src/linetool/Linetool.vue Mon Nov 12 15:00:04 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -<template> - <div @click="cycleDrawMode" class="ui-element d-flex shadow drawtool"> - <i :class="icon"></i> - </div> -</template> - -<style lang="scss"> -.drawtool { - position: absolute; - bottom: 0; - right: 0; - background-color: white; - padding: $small-offset; - border-radius: $border-radius; - margin-left: $offset; - height: $icon-width; - width: $icon-height; - margin-bottom: $offset; - margin-right: $offset; - z-index: 2; -} - -.inverted { - color: #0077ff; -} -</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 by via donau - * – Österreichische Wasserstraßen-Gesellschaft mbH - * Software engineering by Intevation GmbH - * - * Author(s): - * Thomas Junk <thomas.junk@intevation.de> - */ -import { mapState } from "vuex"; - -export default { - name: "linetool", - methods: { - cycleDrawMode() { - if (!this.selectedSurvey && this.drawMode === "LineString") { - this.$store.commit("map/activateDrawModePolygon"); - } else { - this.$store.commit("map/toggleDrawModeLine"); - } - } - }, - computed: { - ...mapState("map", ["identifiedFeatures", "drawMode"]), - ...mapState("bottlenecks", ["selectedSurvey"]), - icon() { - return { - fa: true, - "fa-area-chart": this.selectedSurvey, - "fa-edit": !this.selectedSurvey && this.drawMode === "Polygon", - "fa-pencil": !this.selectedSurvey && this.drawMode !== "Polygon", - inverted: this.drawMode - }; - } - } -}; -</script>
--- a/client/src/login/Login.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/login/Login.vue Mon Nov 12 15:00:45 2018 +0100 @@ -51,7 +51,7 @@ </div> </template>) -<style lang="scss"> +<style lang="scss" scoped> .login { background-color: white; min-width: 375px;
--- a/client/src/map/Maplayer.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/map/Maplayer.vue Mon Nov 12 15:00:45 2018 +0100 @@ -2,7 +2,7 @@ <div id="map" :class="mapStyle"></div> </template> -<style lang="scss"> +<style lang="scss" scoped> .mapsplit { height: 50vh; } @@ -44,18 +44,8 @@ import "ol/ol.css"; import { Map, View } from "ol"; import { WFS, GeoJSON } from "ol/format.js"; -import LineString from "ol/geom/LineString.js"; -import Draw from "ol/interaction/Draw.js"; -import { Vector as VectorLayer } from "ol/layer.js"; -import { Vector as VectorSource } from "ol/source.js"; -import { getLength, getArea } from "ol/sphere.js"; import { Stroke, Style, Fill } from "ol/style.js"; -import { displayError } from "../application/lib/errors.js"; -import { calculateFairwayCoordinates } from "../application/lib/geo.js"; - -const DEMODATA = 2.5; - /* for the sake of debugging */ /* eslint-disable no-console */ export default { @@ -63,8 +53,7 @@ props: ["lat", "long", "zoom", "split"], data() { return { - projection: "EPSG:3857", - interaction: null + projection: "EPSG:3857" }; }, computed: { @@ -79,143 +68,19 @@ } }, methods: { - removeCurrentInteraction() { - this.$store.commit("map/setCurrentMeasurement", null); - this.getLayerByName("Draw Tool") - .data.getSource() - .clear(); - this.openLayersMap.removeInteraction(this.interaction); - this.interaction = null; - }, - createInteraction(drawMode) { - const drawVectorSrc = this.getLayerByName("Draw Tool").data.getSource(); - drawVectorSrc.clear(); - var draw = new Draw({ - source: drawVectorSrc, - type: drawMode, - maxPoints: drawMode === "LineString" ? 2 : 50 - }); - draw.on("drawstart", () => { - drawVectorSrc.clear(); - this.$store.commit("map/setCurrentMeasurement", null); - // we are not setting an id here, to avoid the regular identify to - // pick it up - // event.feature.setId("drawn.1"); // unique id for new feature - }); - draw.on("drawend", this.drawEnd); - return draw; - }, - drawEnd(event) { - if (this.drawMode === "Polygon") { - const areaSize = getArea(event.feature.getGeometry()); - // also place the a rounded areaSize in a property, - // so identify will show it - if (areaSize > 100000) { - this.$store.commit("map/setCurrentMeasurement", { - quantity: "Area", - unitSymbol: "km²", - // convert into 1 km² == 1000*1000 m² and round to 1000 m² - value: Math.round(areaSize / 1000) / 1000 - }); - } else { - this.$store.commit("map/setCurrentMeasurement", { - quantity: "Area", - unitSymbol: "m²", - value: Math.round(areaSize) - }); - } - } - if (this.drawMode === "LineString") { - const length = getLength(event.feature.getGeometry()); - this.$store.commit("map/setCurrentMeasurement", { - quantity: "Length", - unitSymbol: "m", - value: Math.round(length * 10) / 10 - }); - } - - // if a survey has been selected, request a profile - // TODO an improvement could be to check if the line intersects - // with the bottleneck area's polygon before trying the server request - if (this.selectedSurvey) { - this.$store.commit("fairwayprofile/clearCurrentProfile"); - console.log("requesting profile for", this.selectedSurvey); - const inputLineString = event.feature.getGeometry().clone(); - inputLineString.transform("EPSG:3857", "EPSG:4326"); - const [start, end] = inputLineString - .getCoordinates() - .map(coords => coords.map(coord => parseFloat(coord.toFixed(8)))); - this.$store.commit("fairwayprofile/setStartPoint", start); - this.$store.commit("fairwayprofile/setEndPoint", end); - const profileLine = new LineString([start, end]); - this.$store - .dispatch("fairwayprofile/loadProfile", this.selectedSurvey) - .then(() => { - var vectorSource = this.getLayerByName( - "Fairway Dimensions" - ).data.getSource(); - this.calculateIntersection(vectorSource, profileLine); - }) - .then(() => { - this.$store.commit("application/showSplitscreen", true); - }) - .catch(error => { - const { status, data } = error.response; - displayError({ - title: "Backend Error", - message: `${status}: ${data.message || data}` - }); - }); - } - }, - calculateIntersection(vectorSource, profileLine) { - const transformedLine = profileLine - .clone() - .transform("EPSG:4326", "EPSG:3857") - .getExtent(); - const featureCallback = feature => { - // transform back to prepare for usage - var intersectingPolygon = feature - .getGeometry() - .clone() - .transform("EPSG:3857", "EPSG:4326"); - const fairwayCoordinates = calculateFairwayCoordinates( - profileLine, - intersectingPolygon, - DEMODATA - ); - this.$store.commit( - "fairwayprofile/setFairwayCoordinates", - fairwayCoordinates - ); - }; - vectorSource.forEachFeatureIntersectingExtent( - // need to use EPSG:3857 which is the proj of vectorSource - transformedLine, - featureCallback - ); - }, - activateInteraction() { - const interaction = this.createInteraction(this.drawMode); - this.interaction = interaction; - this.openLayersMap.addInteraction(interaction); - }, identify(coordinate, pixel) { this.$store.commit("map/setIdentifiedFeatures", []); // checking our WFS layers var features = this.openLayersMap.getFeaturesAtPixel(pixel); if (features) { this.$store.commit("map/setIdentifiedFeatures", features); - + // get selected bottleneck from identified features for (let feature of features) { let id = feature.getId(); // RegExp.prototype.test() works with number, str and undefined if (/^bottlenecks\./.test(id)) { - this.$store.dispatch( - "bottlenecks/setSelectedBottleneck", - feature.get("objnam") - ); + this.$store.dispatch("bottlenecks/setSelectedBottleneck", feature.get("objnam")); } } } @@ -343,14 +208,6 @@ } }, watch: { - drawMode(newValue) { - if (this.interaction) { - this.removeCurrentInteraction(); - } - if (newValue) { - this.activateInteraction(); - } - }, split() { const map = this.openLayersMap; this.$nextTick(() => {
--- a/client/src/morphtool/Morphtool.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/morphtool/Morphtool.vue Mon Nov 12 15:00:45 2018 +0100 @@ -104,12 +104,13 @@ * Author(s): * Thomas Junk <thomas.junk@intevation.de> */ -import { mapState } from "vuex"; +import { mapState, mapGetters } from "vuex"; export default { name: "morphtool", computed: { - ...mapState("map", ["drawMode"]), + ...mapGetters("map", ["getLayerByName"]), + ...mapState("map", ["openLayersMap", "cutTool"]), ...mapState("bottlenecks", [ "selectedBottleneck", "surveys", @@ -120,9 +121,9 @@ clearSelection() { this.$store.dispatch("bottlenecks/setSelectedBottleneck", null); this.$store.commit("application/showSplitscreen", false); - if (this.drawMode) { - this.$store.commit("map/toggleDrawModeLine"); - } + this.$store.commit("map/cutMode", false); + this.getLayerByName("Cut Tool").data.getSource().clear(); + this.openLayersMap.removeInteraction(this.cutTool) } } };
--- a/client/src/pdftool/Pdftool.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/pdftool/Pdftool.vue Mon Nov 12 15:00:45 2018 +0100 @@ -1,5 +1,5 @@ <template> - <div class="pdftool"> + <div class="pdftool" :style="selectedSurvey ? 'bottom: 140px' : ''"> <div @click="$store.commit('application/showPdfTool', !showPdfTool)" class="d-flex flex-column ui-element minimizer"> <i :class="['fa', 'mt-1', {'fa-file-pdf-o': !showPdfTool}, {'fa-close': showPdfTool}]"></i> </div> @@ -44,10 +44,10 @@ <style lang="scss" scoped> .pdftool { - position: relative; + position: absolute; margin-right: $offset; margin-bottom: $offset; - bottom: 48px; + bottom: 96px; right: 0; } @@ -110,6 +110,7 @@ }, computed: { ...mapState("application", ["showPdfTool"]), + ...mapState("bottlenecks", ["selectedSurvey"]), style() { return { "ui-element": true,
--- a/client/src/store/map.js Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/store/map.js Mon Nov 12 15:00:45 2018 +0100 @@ -35,10 +35,12 @@ namespaced: true, state: { openLayersMap: null, - identifiedFeatures: [], - currentMeasurement: null, - // there are three states of drawMode: null, "LineString", "Polygon" - drawMode: null, + identifiedFeatures: [], // map features identified by clicking on the map + currentMeasurement: null, // distance or area from drawTool + drawMode: null, // null, "LineString", "Polygon" + drawTool: null, // open layers interaction object (Draw) + cutMode: false, // true or false + cutTool: null, // open layers interaction object (Draw) layers: [ { name: "Open Streetmap", @@ -280,6 +282,54 @@ }), isVisible: true, showInLegend: false + }, + { + name: "Cut Tool", + data: new VectorLayer({ + source: new VectorSource({ wrapX: false }), + style: function(feature) { + // adapted from OpenLayer's LineString Arrow Example + var geometry = feature.getGeometry(); + var styles = [ + // linestring + new Style({ + stroke: new Stroke({ + color: "#369aca", + width: 2 + }) + }) + ]; + + if (geometry.getType() === "LineString") { + geometry.forEachSegment(function(start, end) { + var dx = end[0] - start[0]; + var dy = end[1] - start[1]; + var rotation = Math.atan2(dy, dx); + // arrows + styles.push( + new Style({ + geometry: new Point(end), + image: new Icon({ + // we need to make sure the image is loaded by Vue Loader + src: require("../application/assets/linestring_arrow.png"), + // fiddling with the anchor's y value does not help to + // position the image more centered on the line ending, as the + // default line style seems to be slightly uncentered in the + // anti-aliasing, but the image is not placed with subpixel + // precision + anchor: [0.75, 0.5], + rotateWithView: true, + rotation: -rotation + }) + }) + ); + }); + } + return styles; + } + }), + isVisible: true, + showInLegend: false } ] }, @@ -305,15 +355,17 @@ setCurrentMeasurement: (state, measurement) => { state.currentMeasurement = measurement; }, - toggleDrawModeLine: state => { - if (state.drawMode) { - state.drawMode = null; - } else { - state.drawMode = "LineString"; - } + drawMode: (state, mode) => { + state.drawMode = mode; + }, + drawTool: (state, drawTool) => { + state.drawTool = drawTool; }, - activateDrawModePolygon: state => { - state.drawMode = "Polygon"; - } + cutMode: (state, mode) => { + state.cutMode = mode; + }, + cutTool: (state, cutTool) => { + state.cutTool = cutTool; + }, } };
--- a/client/src/usermanagement/Userdetail.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/usermanagement/Userdetail.vue Mon Nov 12 15:00:45 2018 +0100 @@ -70,7 +70,7 @@ </div> </template> -<style lang="scss"> +<style lang="scss" scoped> .mailbutton { width: 12vw; } @@ -90,6 +90,7 @@ font-size: $smaller; } </style> + <script> /* * This is Free Software under GNU Affero General Public License v >= 3.0
--- a/client/src/usermanagement/Users.vue Mon Nov 12 15:00:04 2018 +0100 +++ b/client/src/usermanagement/Users.vue Mon Nov 12 15:00:45 2018 +0100 @@ -69,7 +69,7 @@ </div> </template> -<style lang="scss"> +<style lang="scss" scoped> @import "../application/assets/tooltip.scss"; .main { height: 100vh;