Mercurial > gemma
changeset 4323:ab7d80baebe6
deleting Profiles.vue
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Wed, 04 Sep 2019 14:16:57 +0200 |
parents | fabe67e204e7 |
children | 36d384326407 |
files | client/src/components/fairway/Profiles.vue |
diffstat | 1 files changed, 0 insertions(+), 675 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/components/fairway/Profiles.vue Wed Sep 04 14:10:50 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,675 +0,0 @@ -<template> - <div - :class="[ - 'box ui-element rounded bg-white text-nowrap', - { expanded: showProfiles } - ]" - > - <div style="width: 18rem"> - <UIBoxHeader - icon="chart-area" - :title="profilesLable" - :closeCallback="close" - /> - <div class="box-body"> - <UISpinnerOverlay v-if="surveysLoading || profileLoading" /> - <select - @change="moveToBottleneck" - v-model="selectedBottleneck" - class="form-control font-weight-bold" - > - <option :value="null"> - <translate>Select Bottleneck</translate> - </option> - <optgroup - v-for="(bottlenecksForCountry, cc) in orderedBottlenecks" - :key="cc" - :label="cc" - > - <option - v-for="bn in bottlenecksForCountry" - :key="bn.properties.id" - :value="bn.properties.name" - > - {{ bn.properties.name }} - </option> - </optgroup> - </select> - <div v-if="selectedBottleneck"> - <div class="d-flex mt-2"> - <div class="flex-fill" style="max-width: 75px;"> - <small class="text-muted"> - <translate>Waterlevel</translate>: - </small> - <select - v-model="selectedWaterLevel" - class="form-control form-control-sm small" - > - <option value="ref"> - <translate>Depth Reference</translate> - <template v-if="selectedSurvey"> - ({{ selectedSurvey.depth_reference }}/{{ - $options.filters.waterlevel( - selectedSurvey.waterlevel_value - ) - }} - m) - </template> - </option> - <option value="current"> - <translate>Current Waterlevel</translate> - <template v-if="bottleneck"> - ({{ - $options.filters.waterlevel( - bottleneck.get("gm_waterlevel") - ) - }} - m) - </template> - </option> - </select> - </div> - <div class="flex-fill ml-2"> - <small class="text-muted"> <translate>Survey</translate>: </small> - <select - v-model="selectedSurvey" - class="form-control form-control-sm small" - > - <option - v-for="survey in surveys" - :key="survey.date_info" - :value="survey" - >{{ survey.date_info | surveyDate }}</option - > - </select> - </div> - <div - class="flex-fill ml-2" - v-if="selectedSurvey && surveys.length > 1" - > - <small class="text-muted mt-1"> - <translate>Compare with</translate>: - </small> - <select - v-model="additionalSurvey" - class="form-control form-control-sm small" - > - <option :value="null">None</option> - <option - v-for="survey in additionalSurveys" - :key="survey.date_info" - :value="survey" - >{{ survey.date_info | surveyDate }}</option - > - </select> - </div> - </div> - <div class="mt-2 d-flex" v-if="additionalSurvey"> - <button - v-if="differencesLoading" - class="btn btn-info btn-xs flex-fill" - disabled - > - <font-awesome-icon icon="spinner" spin class="mr-1" /> - <translate>Calculating differences</translate> - </button> - <button - class="btn btn-info btn-xs flex-fill" - @click="differencesVisible ? showSurvey() : showDifferences()" - v-else - > - <translate v-if="differencesVisible" key="showsurvey" - >Show survey</translate - > - <translate v-else key="showdifferences" - >Show differences</translate - > - </button> - <button - v-if="!paneSetup.includes('FAIRWAYPROFILE')" - class="btn btn-info btn-xs ml-2" - @click="$store.commit('application/paneRotate')" - v-tooltip="rotatePanesTooltip" - > - <font-awesome-icon icon="redo" fixed-width /> - </button> - <button - class="btn btn-info btn-xs ml-2" - @click="toggleSyncMaps()" - v-tooltip="syncMapsTooltip" - > - <font-awesome-icon - :icon="mapsAreSynced ? 'unlink' : 'link'" - fixed-width - /> - </button> - </div> - <hr class="w-100 mb-0" /> - <small class="text-muted d-block mt-2"> - <translate>Saved cross profiles</translate>: - </small> - <div class="d-flex"> - <select - :class="[ - 'form-control form-control-sm flex-fill', - { 'rounded-left-only': selectedCut } - ]" - v-model="selectedCut" - > - <option></option> - <option - v-for="(cut, index) in previousCuts" - :value="cut" - :key="index" - >{{ cut.label }}</option - > - </select> - <button - class="btn btn-sm btn-dark input-button-right" - @click="deleteSelectedCut(selectedCut)" - v-if="selectedCut" - > - <font-awesome-icon icon="trash" /> - </button> - </div> - <small class="text-muted d-block mt-2"> - <translate>Enter coordinates manually</translate>: - </small> - <div class="position-relative"> - <input - class="form-control form-control-sm pr-5" - placeholder="Lat,Lon,Lat,Lon" - v-model="coordinatesInput" - /> - <button - class="btn btn-sm btn-info position-absolute input-button-right" - @click="applyManualCoordinates" - style="top: 0; right: 0;" - v-if="coordinatesInputIsValid" - > - <font-awesome-icon icon="check" /> - </button> - </div> - <small class="d-flex text-left mt-2" v-if="startPoint && endPoint"> - <div class="text-nowrap mr-3"> - <b> <translate>Start</translate>: </b> <br /> - Lat: {{ startPoint[1] }} <br /> - Lon: {{ startPoint[0] }} - </div> - <div class="text-nowrap"> - <b>End:</b> <br /> - Lat: {{ endPoint[1] }} <br /> - Lon: {{ endPoint[0] }} - </div> - <button - v-clipboard:copy="coordinatesForClipboard" - v-clipboard:success="onCopyCoordinates" - class="btn btn-info btn-sm ml-auto mt-auto" - > - <font-awesome-icon icon="copy" /> - </button> - </small> - <div class="d-flex mt-3"> - <div - class="pr-3 w-50" - v-if="startPoint && endPoint && !selectedCut" - > - <button - class="btn btn-info btn-sm w-100" - @click="showLabelInput = !showLabelInput" - > - <font-awesome-icon :icon="showLabelInput ? 'times' : 'check'" /> - {{ showLabelInput ? "Cancel" : "Save" }} - </button> - </div> - <div - :class="startPoint && endPoint && !selectedCut ? 'w-50' : 'w-100'" - > - <button - class="btn btn-info btn-sm w-100" - @click="toggleCutTool" - :disabled="!selectedSurvey" - > - <font-awesome-icon :icon="cutToolEnabled ? 'times' : 'plus'" /> - {{ cutToolEnabled ? "Cancel" : "New" }} - </button> - </div> - </div> - <div v-if="showLabelInput" class="mt-2"> - <small class="text-muted"> - <translate>Enter label for cross profile</translate>: - </small> - <div class="position-relative"> - <input - class="form-control form-control-sm pr-5" - v-model="cutLabel" - /> - <button - class="btn btn-sm btn-info position-absolute input-button-right" - @click="saveCut" - v-if="cutLabel" - style="top: 0; right: 0;" - > - <font-awesome-icon icon="check" /> - </button> - </div> - </div> - </div> - </div> - </div> - </div> -</template> - -<style lang="scss" scoped> -.input-button-right { - border-top-right-radius: $border-radius; - border-bottom-right-radius: $border-radius; - border-top-left-radius: 0 !important; - border-bottom-left-radius: 0 !important; -} - -.rounded-left-only { - border-top-right-radius: 0 !important; - border-bottom-right-radius: 0 !important; - border-top-left-radius: $border-radius; - border-bottom-left-radius: $border-radius; -} - -input, -select { - font-size: 0.8em; -} -</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): - * Markus Kottländer <markus.kottlaender@intevation.de> - */ -import { mapState, mapGetters } from "vuex"; -import Feature from "ol/Feature"; -import LineString from "ol/geom/LineString"; -import { displayError, displayInfo } from "@/lib/errors"; -import { HTTP } from "@/lib/http"; -import { COMPARESURVEYS } from "@/components/paneSetups"; - -export default { - name: "profiles", - data() { - return { - coordinatesInput: "", - cutLabel: "", - showLabelInput: false - }; - }, - computed: { - ...mapState("application", ["showProfiles", "paneSetup"]), - ...mapState("map", ["openLayersMaps", "syncedMaps", "cutToolEnabled"]), - ...mapState("bottlenecks", [ - "bottlenecksList", - "surveys", - "surveysLoading" - ]), - ...mapState("fairwayprofile", [ - "previousCuts", - "startPoint", - "endPoint", - "profileLoading", - "differencesLoading", - "waterLevels", - "currentProfile" - ]), - ...mapGetters("map", ["openLayersMap"]), - ...mapGetters("bottlenecks", ["orderedBottlenecks"]), - profilesLable() { - return this.$gettext("Bottleneck Surveys"); - }, - selectedBottleneck: { - get() { - return this.$store.state.bottlenecks.selectedBottleneck; - }, - set(name) { - this.$store.dispatch("bottlenecks/setSelectedBottleneck", name); - } - }, - selectedWaterLevel: { - get() { - return this.$store.state.fairwayprofile.selectedWaterLevel; - }, - set(value) { - this.$store.commit("fairwayprofile/setSelectedWaterLevel", value); - } - }, - selectedSurvey: { - get() { - return this.$store.state.bottlenecks.selectedSurvey; - }, - set(survey) { - this.$store.commit("fairwayprofile/additionalSurvey", null); - this.$store.commit("bottlenecks/selectedSurvey", survey); - } - }, - additionalSurvey: { - get() { - return this.$store.state.fairwayprofile.additionalSurvey; - }, - set(survey) { - this.$store.commit("fairwayprofile/additionalSurvey", survey); - } - }, - selectedCut: { - get() { - return this.$store.state.fairwayprofile.selectedCut; - }, - set(cut) { - this.$store.commit("fairwayprofile/selectedCut", cut); - if (!cut) { - this.$store.commit("fairwayprofile/clearCurrentProfile"); - this.openLayersMaps.forEach(m => { - m.getLayer("CUTTOOL") - .getSource() - .clear(); - }); - } - } - }, - additionalSurveys() { - return this.surveys.filter( - survey => survey.date_info !== this.selectedSurvey.date_info - ); - }, - coordinatesForClipboard() { - return ( - this.startPoint[1] + - "," + - this.startPoint[0] + - "," + - this.endPoint[1] + - "," + - this.endPoint[0] - ); - }, - coordinatesInputIsValid() { - const coordinates = this.coordinatesInput - .split(",") - .map(coord => parseFloat(coord.trim())) - .filter(c => Number(c) === c); - return coordinates.length === 4; - }, - differencesVisible() { - return ( - this.openLayersMap(COMPARESURVEYS.compare.id) && - !this.openLayersMap(COMPARESURVEYS.compare.id) - .getLayer("BOTTLENECKISOLINE") - .getVisible() && - this.openLayersMap(COMPARESURVEYS.compare.id) - .getLayer("DIFFERENCES") - .getVisible() - ); - }, - rotatePanesTooltip() { - return this.$gettext("Rotate Maps"); - }, - syncMapsTooltip() { - return this.$gettext( - this.mapsAreSynced ? "Unsynchronize Maps" : "Synchronize Maps" - ); - }, - mapsAreSynced() { - return this.syncedMaps.includes(COMPARESURVEYS.compare.id); - }, - bottleneck() { - return this.openLayersMap() - ? this.openLayersMap() - .getLayer("BOTTLENECKS") - .getSource() - .getFeatures() - .find(f => f.get("objnam") === this.selectedBottleneck) - : null; - } - }, - watch: { - selectedBottleneck() { - this.$store.dispatch("fairwayprofile/previousCuts"); - this.cutLabel = - this.selectedBottleneck + " (" + new Date().toISOString() + ")"; - }, - selectedSurvey(survey) { - this.loadProfile(survey); - }, - additionalSurvey(survey) { - if (survey) { - this.loadDifferences(); - this.$store.commit( - "application/paneSetup", - Object.keys(this.currentProfile).length - ? "COMPARESURVEYS_FAIRWAYPROFILE" - : "COMPARESURVEYS" - ); - this.$store.commit("map/syncedMaps", [COMPARESURVEYS.compare.id]); - } else { - this.$store.commit( - "application/paneSetup", - Object.keys(this.currentProfile).length ? "FAIRWAYPROFILE" : "DEFAULT" - ); - this.$store.commit("map/syncedMaps", []); - } - this.loadProfile(survey); - }, - selectedCut(cut) { - if (cut) { - this.applyCoordinates(cut.coordinates); - } - } - }, - methods: { - toggleSyncMaps() { - if (this.mapsAreSynced) { - this.$store.commit( - "map/syncedMaps", - this.syncedMaps.filter(m => m !== COMPARESURVEYS.compare.id) - ); - } else { - this.$store.commit("map/syncedMaps", [COMPARESURVEYS.compare.id]); - } - }, - loadDifferences() { - this.$store.commit("fairwayprofile/setDifferencesLoading", true); - HTTP.post( - "/diff", - { - bottleneck: this.selectedSurvey.bottleneck_id, - minuend: this.selectedSurvey.date_info, - subtrahend: this.additionalSurvey.date_info - }, - { - headers: { - "X-Gemma-Auth": localStorage.getItem("token") - } - } - ) - .then() - .catch(error => { - let status, data, message; - if (error.response) { - status = error.response.status; - data = error.response.data; - message = `${status}: ${data.message || data}`; - } else { - message = error; - } - displayError({ - title: this.$gettext("Backend Error"), - message: message - }); - }) - .finally(() => { - this.$store.commit("fairwayprofile/setDifferencesLoading", false); - }); - }, - showDifferences() { - this.openLayersMap(COMPARESURVEYS.compare.id) - .getLayer("BOTTLENECKISOLINE") - .setVisible(false); - this.openLayersMap(COMPARESURVEYS.compare.id) - .getLayer("DIFFERENCES") - .setVisible(true); - }, - showSurvey() { - this.openLayersMap(COMPARESURVEYS.compare.id) - .getLayer("BOTTLENECKISOLINE") - .setVisible(true); - this.openLayersMap(COMPARESURVEYS.compare.id) - .getLayer("DIFFERENCES") - .setVisible(false); - }, - close() { - this.$store.commit("application/showProfiles", false); - }, - loadProfile(survey) { - if (survey) { - this.$store.commit("fairwayprofile/profileLoading", true); - this.$store - .dispatch("fairwayprofile/loadProfile", survey) - .finally(() => { - this.$store.commit("fairwayprofile/profileLoading", false); - }); - } - }, - toggleCutTool() { - this.$store.commit("map/cutToolEnabled", !this.cutToolEnabled); - this.$store.commit("map/lineToolEnabled", false); - this.$store.commit("map/polygonToolEnabled", false); - this.$store.commit("map/setCurrentMeasurement", null); - }, - onCopyCoordinates() { - displayInfo({ - message: this.$gettext("Coordinates copied to clipboard!") - }); - }, - applyManualCoordinates() { - const coordinates = this.coordinatesInput - .split(",") - .map(coord => parseFloat(coord.trim())); - this.selectedCut = null; - this.coordinatesInput = ""; - this.applyCoordinates([ - coordinates[1], - coordinates[0], - coordinates[3], - coordinates[2] - ]); - }, - applyCoordinates(coordinates) { - // allow only numbers - coordinates = coordinates.filter(c => Number(c) === c); - if (coordinates.length === 4) { - // draw line on map - this.openLayersMaps.forEach(m => { - m.getLayer("CUTTOOL") - .getSource() - .clear(); - }); - const cut = new Feature({ - geometry: new LineString([ - [coordinates[0], coordinates[1]], - [coordinates[2], coordinates[3]] - ]).transform("EPSG:4326", "EPSG:3857") - }); - this.openLayersMaps.forEach(m => { - m.getLayer("CUTTOOL") - .getSource() - .addFeature(cut); - }); - - // draw diagram - this.$store.dispatch("fairwayprofile/cut", cut); - } else { - displayError({ - title: this.$gettext("Invalid input"), - message: this.$gettext( - "Please enter correct coordinates in the format: Lat,Lon,Lat,Lon" - ) - }); - } - }, - saveCut() { - const previousCuts = - JSON.parse(localStorage.getItem("previousCuts")) || []; - const newEntry = { - label: this.cutLabel, - bottleneckName: this.selectedBottleneck, - coordinates: [...this.startPoint, ...this.endPoint], - timestamp: new Date().getTime() - }; - const existingEntry = previousCuts.find(cut => { - return JSON.stringify(cut) === JSON.stringify(newEntry); - }); - if (!existingEntry) previousCuts.push(newEntry); - if (previousCuts.length > 100) previousCuts.shift(); - localStorage.setItem("previousCuts", JSON.stringify(previousCuts)); - this.$store.dispatch("fairwayprofile/previousCuts"); - - this.showLabelInput = false; - displayInfo({ - title: this.$gettext("Profile saved!"), - message: this.$gettext( - 'You can now select these coordinates from the "Saved cross profiles" menu to restore this cross profile.' - ) - }); - }, - deleteSelectedCut(cut) { - this.$store.commit("application/popup", { - icon: "trash", - title: this.$gettext("Delete cross profile"), - content: - this.$gettext("Do you really want to delete the cross profile:") + - `<br> - <b>${cut.label}</b>`, - confirm: { - label: this.$gettext("Delete"), - icon: "trash", - callback: () => { - let previousCuts = - JSON.parse(localStorage.getItem("previousCuts")) || []; - previousCuts = previousCuts.filter(cut => { - return JSON.stringify(cut) !== JSON.stringify(this.selectedCut); - }); - localStorage.setItem("previousCuts", JSON.stringify(previousCuts)); - this.$store.commit("fairwayprofile/selectedCut", null); - this.$store.dispatch("fairwayprofile/previousCuts"); - displayInfo({ title: this.$gettext("Profile deleted!") }); - } - }, - cancel: { - label: this.$gettext("Cancel"), - icon: "times" - } - }); - }, - moveToBottleneck() { - const bottleneck = this.bottlenecksList.find( - bn => bn.properties.name === this.selectedBottleneck - ); - if (!bottleneck) return; - this.$store.dispatch("map/moveToFeauture", { - feature: bottleneck, - zoom: 17, - preventZoomOut: true - }); - } - }, - mounted() { - this.$store.dispatch("bottlenecks/loadBottlenecksList"); - } -}; -</script>