Mercurial > gemma
view client/src/usermanagement/Userdetail.vue @ 1063:7ec2133c6404
client: add area measurement. simpify code
* Add a third draw mode which can only be activated when no
morphology is selected and we are already in LineString mode.
It adds an area calculation. Because the Polygon drawMode ends
on a double click, there needs to be an extra callback for this to
run identify so that the area calculation is shown all times.
* Add Bernhard as author to some files and also simplify copyright
note.
* Remove DRAWMODES in the code to simplify as this is just one
indirection used once in stores/application.js.
* Use mapState instead mapGetters to get the drawMode at all places
to save some code lines.
author | Bernhard Reiter <bernhard@intevation.de> |
---|---|
date | Thu, 25 Oct 2018 23:16:53 +0200 |
parents | ca628dce90dd |
children | d9e6a1f6f394 |
line wrap: on
line source
<template> <div class="userdetails shadow fadeIn animated"> <div class="card"> <div class="card-header shadow-sm text-white bg-info mb-3"> {{ this.cardHeader }} <span @click="closeDetailview" class="pull-right"> <i class="fa fa-close"></i> </span> </div> <div class="card-body"> <form @submit.prevent="save"> <div class="formfields"> <div v-if="currentUser.isNew" class="form-group row"> <label for="user">Username</label> <input type="user" :placeholder="userNamePlaceholder" class="form-control form-control-sm" id="user" aria-describedby="userHelp" v-model="currentUser.user"> <div v-show="errors.user" class="text-danger"> <small> <i class="fa fa-warning"></i> {{ errors.user }}</small> </div> </div> <div class="form-group row"> <label for="country">Country</label> <select class="form-control form-control-sm" v-on:change="validateCountry" v-model="currentUser.country"> <option disabled value="">Please select one</option> <option v-for="country in countries" v-bind:value="country" v-bind:key="country">{{country}}</option> </select> <div v-show="errors.country" class="text-danger"> <small> <i class="fa fa-warning"></i> {{ errors.country }}</small> </div> </div> <div class="form-group row"> <label for="email">Email address</label> <input type="email" v-on:change="validateEmailaddress" class="form-control form-control-sm" id="email" aria-describedby="emailHelp" v-model="currentUser.email"> <div v-show="errors.email" class="text-danger"> <small> <i class="fa fa-warning"></i> {{ errors.email }}</small> </div> </div> <div class="form-group row"> <label for="role">Role</label> <select class="form-control form-control-sm" v-on:change="validateRole" v-model="currentUser.role"> <option disabled value="">Please select one</option> <option value="sys_admin">Sysadmin</option> <option value="waterway_admin">Waterway Admin</option> <option value="waterway_user">Waterway User</option> </select> <div v-show="errors.role" class="text-danger"> <small> <i class="fa fa-warning"></i> {{ errors.role }}</small> </div> </div> <div class="form-group row"> <PasswordField @fieldchange="passwordChanged" :placeholder="passwordPlaceholder" :label="passwordLabel" :passworderrors="errors.password"></PasswordField> </div> <div class="form-group row"> <PasswordField @fieldchange="passwordReChanged" :placeholder="passwordRePlaceholder" :label="passwordReLabel" :passworderrors="errors.passwordre"></PasswordField> </div> </div> <div> <button type="submit" :disabled="submitted" class="shadow-sm btn btn-info pull-right">Submit</button> </div> <div v-if="currentUser.role !='waterway_user' " class="form-group row d-flex flex-row justify-content-start mailbutton"> <a @click="sendTestMail" class="btn btn-light"><i class="fa fa-telegram"> Send testmail</i></a> <div v-if="mailsent">Mail was sent</div> </div> </form> </div> </div> </div> </template> <style lang="scss"> .mailbutton { width: 12vw; } .formfields { width: 10vw; } .userdetails { margin-top: $offset; min-width: 40vw; margin-right: auto; height: 100%; } form { margin-left: $offset; font-size: $smaller; } </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 { HTTP } from "../application/lib/http"; import { displayError } from "../application/lib/errors.js"; import { mapGetters } from "vuex"; import PasswordField from "./Passwordfield"; const emptyErrormessages = () => { return { email: "", country: "", role: "", password: "", passwordre: "" }; }; const isEmailValid = email => { /** * * For convenience purposes the same regex used as in the go code * cf. types.go * */ // eslint-disable-next-line return /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/.test( email ); }; const violatedPasswordRules = password => { return ( // rules according to issue 70 password.length < 7 || /\W/.test(password) == false || /\d/.test(password) == false ); }; export default { name: "userdetail", components: { PasswordField }, data() { return { mailsent: false, passwordLabel: "Password", passwordReLabel: "Repeat Password", passwordPlaceholder: "password", passwordRePlaceholder: "password again", password: "", passwordre: "", currentUser: {}, path: null, submitted: false, errors: { email: "", country: "", role: "", password: "", passwordre: "" } }; }, mounted() { this.currentUser = { ...this.user }; this.path = this.user.name; }, watch: { user() { this.currentUser = { ...this.user }; this.path = this.user.name; this.clearPassword(); this.clearErrors(); } }, computed: { cardHeader() { if (this.currentUser.isNew) return "N.N"; return this.currentUser.user; }, userNamePlaceholder() { if (this.currentUser.isNew) return "N.N"; return ""; }, ...mapGetters("application", ["countries"]), user() { return this.$store.getters["usermanagement/currentUser"]; }, isFormValid() { return ( isEmailValid(this.currentUser.email) && this.currentUser.country && this.password === this.passwordre && (this.password === "" || !violatedPasswordRules(this.password)) ); } }, methods: { sendTestMail() { if (this.mailsent) return; HTTP.get("/testmail/" + this.currentUser.user, { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } }) .then(() => { this.mailsent = true; }) .catch(error => { this.loginFailed = true; this.submitted = false; const { status, data } = error.response; displayError({ title: "Backend Error", message: `${status}: ${data.message || data}` }); }); }, passwordChanged(value) { this.password = value; this.validatePassword(); }, passwordReChanged(value) { this.passwordre = value; this.validatePassword(); }, clearErrors() { this.errors = emptyErrormessages(); }, clearPassword() { this.password = ""; this.passwordre = ""; }, closeDetailview() { this.$store.commit("usermanagement/clearCurrentUser"); this.$store.commit("usermanagement/setUserDetailsInvisible"); }, validateCountry() { this.errors.country = this.currentUser.country ? "" : "Please choose a country"; }, validateRole() { this.errors.role = this.currentUser.role ? "" : "Please choose a role"; }, validatePassword() { this.errors.passwordre = this.password === this.passwordre ? "" : "Passwords do not match!"; this.errors.password = this.password === "" || !violatedPasswordRules(this.password) ? "" : "Password should at least be 8 char long including 1 digit and 1 special char like $"; }, validateEmailaddress() { this.errors.email = isEmailValid(this.currentUser.email) ? "" : "invalid email"; }, validate() { this.validateCountry(); this.validateRole(); this.validatePassword(); this.validateEmailaddress(); }, save() { this.validate(); if (!this.isFormValid) return; if (this.password) this.currentUser.password = this.password; this.submitted = true; this.$store .dispatch("usermanagement/saveCurrentUser", { path: this.user.user, user: this.currentUser }) .then(() => { this.submitted = false; this.$store.dispatch("usermanagement/loadUsers").catch(error => { const { status, data } = error.response; displayError({ title: "Backend Error", message: `${status}: ${data.message || data}` }); }); }) .catch(error => { this.submitted = false; const { status, data } = error.response; displayError({ title: "Error while saving user", message: `${status}: ${data.message || data}` }); }); } } }; </script>