Mercurial > gemma
view client/src/components/systemconfiguration/MorphologyClassbreaks.vue @ 4434:0ca5e6c4f195
Added tag v4-preview20190918 for changeset b5619087e3e9
author | Sascha Wilde <wilde@intevation.de> |
---|---|
date | Wed, 18 Sep 2019 18:04:39 +0200 |
parents | aa249a25f0ec |
children | 2e19ed576c68 |
line wrap: on
line source
<template> <div class="d-flex flex-column py-4"> <div class="px-3"> <h6 class="font-weight-bold"><translate>Sounding Result</translate></h6> <div class="d-flex flex-wrap"> <div class="input-group mb-3 mr-2 classbreak" v-for="(value, i) in morphologyClassbreaks" :key="i" > <div class="input-group-prepend"> <button :class="[ 'btn btn-sm btn-outline-secondary', { hasColor: morphologyClassbreaks[i][1] !== '#ffffff' } ]" :style=" 'width: 28px; background-color: ' + (morphologyClassbreaks[i][1] || 'transparent') " type="button" @click="showColorPicker('sounding-' + i)" > <font-awesome-icon icon="tint" /> </button> <div class="color-picker card shadow-sm" v-if="activeColorPicker === 'sounding-' + i" > <UIBoxHeader :title="colorPickerTitle" icon="paint-brush" :actions="[ { callback: () => { morphologyClassbreaks[i][1] = '#ffffff'; activeColorPicker = null; }, icon: 'trash' }, { callback: () => { activeColorPicker = null; }, icon: 'check' } ]" /> <chrome-picker v-model="morphologyClassbreaks[i][1]" @input="color => (morphologyClassbreaks[i][1] = color.hex)" /> </div> </div> <form id="novalidatedform" /> <input v-model.number="morphologyClassbreaks[i][0]" type="number" min="0" step="0.01" class="form-control form-control-sm numfield" /> <div class="input-group-append"> <button class="btn btn-sm btn-outline-secondary" type="button" @click="morphologyClassbreaks.splice(i, 1)" > <font-awesome-icon icon="times" /> </button> <button class="btn btn-sm btn-outline-secondary" @click="addClassbreak(morphologyClassbreaks, i)" > <font-awesome-icon icon="plus" /> </button> </div> </div> <button v-if="!morphologyClassbreaks.length" class="btn btn-sm btn-success mb-3" @click="addClassbreak(morphologyClassbreaks, 0)" > <font-awesome-icon icon="plus" /> </button> </div> </div> <div class="mb-4 px-3"> <a @click.prevent="submitClassbreaks" :class="[ 'btn btn-info btn-sm text-white', { disabled: !checkClassbreaks } ]" > <translate>Send</translate> </a> <a @click.prevent="resetClassbreaks" class="btn btn-outline-info btn-sm ml-2" > <translate>Reset to defaults</translate> </a> <span class="text-danger" v-if="!checkClassbreaks"> {{ validationMessage }} </span> <span class="text-secondary fix-trans-space" v-translate> Changes need a map reload. Consider informing your users. </span> </div> <div class="px-3"> <h6 class="font-weight-bold"> <translate>Sounding Result Comparison</translate> </h6> <div class="d-flex flex-wrap"> <div class="input-group mb-3 mr-2 classbreak" v-for="(value, i) in morphologyClassbreaksCompare" :key="i" > <div class="input-group-prepend"> <button :class="[ 'btn btn-sm btn-outline-secondary', { hasColor: morphologyClassbreaksCompare[i][1] !== '#ffffff' } ]" :style=" 'width: 28px; background-color: ' + (morphologyClassbreaksCompare[i][1] || 'transparent') " type="button" @click="showColorPicker('compare-' + i)" > <font-awesome-icon icon="tint" /> </button> <div class="color-picker card shadow-sm" v-if="activeColorPicker === 'compare-' + i" > <UIBoxHeader :title="colorPickerTitle" icon="paint-brush" :actions="[ { callback: () => { morphologyClassbreaksCompare[i][1] = '#ffffff'; activeColorPicker = null; }, icon: 'trash' }, { callback: () => { activeColorPicker = null; }, icon: 'check' } ]" /> <chrome-picker v-model="morphologyClassbreaksCompare[i][1]" @input=" color => (morphologyClassbreaksCompare[i][1] = color.hex) " /> </div> </div> <input v-model.number="morphologyClassbreaksCompare[i][0]" type="number" step="0.01" class="form-control form-control-sm numfield" /> <div class="input-group-append"> <button class="btn btn-sm btn-outline-secondary" type="button" @click="morphologyClassbreaksCompare.splice(i, 1)" > <font-awesome-icon icon="times" /> </button> <button class="btn btn-sm btn-outline-secondary" @click="addClassbreak(morphologyClassbreaksCompare, i)" > <font-awesome-icon icon="plus" /> </button> </div> </div> <button v-if="!morphologyClassbreaksCompare.length" class="btn btn-sm btn-success mb-3" @click="addClassbreak(morphologyClassbreaksCompare, 0)" > <font-awesome-icon icon="plus" /> </button> </div> </div> <div class="px-3"> <a @click.prevent="submitClassbreaksCompare" :class="[ 'btn btn-info btn-sm text-white', { disabled: !checkClassbreaksCompare } ]" > <translate>Send</translate> </a> <a @click.prevent="resetClassbreaksCompare" class="btn btn-outline-info btn-sm ml-2" > <translate>Reset to defaults</translate> </a> <span class="text-danger" v-if="!checkClassbreaksCompare"> {{ validationMessageForCompare }} </span> <span class="text-secondary fix-trans-space" v-translate> Colour changes need a map reload. Value changes need a de- and re-select of a difference calculation. Inform your users! </span> </div> </div> </template> <style lang="sass" scoped> .numfield:invalid border: 2px solid border-color: #ff0000 .classbreak width: 154px .btn-outline-secondary border-color: #ccc color: #ccc &:hover:not(.hasColor) background: #eee !important .input-group-prepend .btn-outline-secondary.hasColor color: rgba(255, 255, 255, 0.5) .input-group-append .btn-outline-secondary &:hover color: #dc3545 &:last-child:hover color: #28a745 .color-picker position: absolute top: -4px left: 19px z-index: 9 overflow: hidden border-top-left-radius: 0 !important .btn border-radius: 0 !important .vc-chrome box-shadow: none /deep/ .vc-chrome-alpha-wrap display: none !important .vc-chrome-hue-wrap margin-top: 10px .vc-chrome-saturation-wrap border-radius: 0 </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@intevation.de> */ import { mapState } from "vuex"; import { Chrome } from "vue-color"; import defaults from "./defaults"; export default { components: { "chrome-picker": Chrome }, data() { return { morphologyClassbreaks: [], morphologyClassbreaksCompare: [], activeColorPicker: null, closeColorPickerListener: null, validationMessage: "", validationMessageForCompare: "" }; }, computed: { ...mapState("application", ["config"]), colorPickerTitle() { return this.$gettext("Choose color"); }, checkClassbreaks() { return ( this.valuesAreValid(this.morphologyClassbreaks) && !this.hasDoublettes(this.morphologyClassbreaks) ); }, checkClassbreaksCompare() { return ( this.valuesAreValid(this.morphologyClassbreaksCompare, "compare") && !this.hasDoublettes(this.morphologyClassbreaksCompare, "compare") ); } }, methods: { // check if the same value is used for more than one field. hasDoublettes(m, compare) { const errorMessage = this.$gettext( "Same value is used in multiple fields." ); let values = []; for (let i = 0; i < m.length; i++) { values[i] = Number(m[i][0]); } if (new Set(values).size !== values.length) { // determine which message to change if (compare !== "compare") { this.validationMessage = errorMessage; } else { this.validationMessageForCompare = errorMessage; } return true; } return false; }, valuesAreValid(m, compare) { const errorMessage = this.$gettext( "There are invalid classbreak values." ); let values = m.map(e => { const element = e[0]; if (!isNaN(element)) { if (element === "") return false; // check if the field is empty if (!isNaN(element)) { const numberParts = String(element).split("."); // check number of decimal places return numberParts.length == 2 ? numberParts[1].length < 3 : true; } } return false; }); if (values.every(e => e === true)) { return true; } if (compare !== "compare") { this.validationMessage = errorMessage; } else { this.validationMessageForCompare = errorMessage; } return false; }, addClassbreak(classbreaks, i) { classbreaks.splice( i, 0, classbreaks.length > i ? [classbreaks[i][0], classbreaks[i][1]] // create new array! : [1, "#ffffff"] ); }, showColorPicker(id) { this.activeColorPicker = this.activeColorPicker === id ? null : id; }, submitClassbreaks() { this.$store .dispatch("application/saveConfig", { morphology_classbreaks: this.morphologyClassbreaks .map(cb => (cb[1] === "#ffffff" ? cb[0] : cb.join(":"))) .join(",") }) .finally(() => this.$store.dispatch("application/loadConfig")); }, submitClassbreaksCompare() { this.$store .dispatch("application/saveConfig", { morphology_classbreaks_compare: this.morphologyClassbreaksCompare .map(cb => (cb[1] === "#ffffff" ? cb[0] : cb.join(":"))) .join(",") }) .finally(() => this.$store.dispatch("application/loadConfig")); }, resetClassbreaks() { this.morphologyClassbreaks = this.parseClassbreakString( defaults.morphology_classbreaks ); }, resetClassbreaksCompare() { this.morphologyClassbreaksCompare = this.parseClassbreakString( defaults.morphology_classbreaks_compare ); }, parseClassbreakString(str) { return str .split(",") .map(cb => cb.split(":")) .map(cb => { cb[0] = Number(cb[0]); cb[1] = cb[1] || "#ffffff"; return cb; }); } }, mounted() { this.morphologyClassbreaks = this.parseClassbreakString( this.config.morphology_classbreaks ); this.morphologyClassbreaksCompare = this.parseClassbreakString( this.config.morphology_classbreaks_compare ); this.closeColorPickerListener = e => { // Escape if (e.keyCode === 27) { this.activeColorPicker = null; } }; window.addEventListener("keydown", this.closeColorPickerListener); }, destroyed() { window.removeEventListener("keydown", this.closeColorPickerListener); } }; </script>