Mercurial > gemma
view client/src/components/Userdetail.vue @ 389:e7d5383bc358
feat: Primitive validation and error messages
Added simple error messages to the usermanagement
Added simple validation rules for fields:
* password rules according issue70
* email used the regex from gocode
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Mon, 13 Aug 2018 16:21:26 +0200 |
parents | 0a9aaf21f69f |
children | c57b952c60be |
line wrap: on
line source
<template> <div class="userdetails shadow"> <div class="card"> <div class="card-header text-white bg-info mb-3"> {{ currentUser.user }} <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" class="form-control form-control-sm" id="user" aria-describedby="userHelp" v-model="currentUser.user"> <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="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>AT</option> <option>RO</option> <option>BG</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-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> <div class="form-group row"> <label for="password">Password</label> <input type="password" v-on:change="validatePassword" class="form-control form-control-sm" id="password" aria-describedby="passwordHelp" v-model="password"> <div v-show="errors.password" class="text-danger"><small><i class="fa fa-warning"></i> {{ errors.password }}</small></div> </div> <div class="form-group row"> <label for="passwordre">Retype Password</label> <input type="password" v-on:change="validatePassword" class="form-control form-control-sm" id="passwordre" aria-describedby="passwordreHelp" v-model="passwordre"> <div v-show="errors.passwordre" class="text-danger"><small><i class="fa fa-warning"></i> {{ errors.passwordre }}</small></div> </div> </div> <div> <button type="submit" :disabled="submitted" class="btn btn-info pull-right">Submit</button> </div> </form> </div> </div> </div> </template> <style lang="scss"> @import "../assets/application.scss"; .formfields { width: 10vw; } .userdetails { margin-top: $large-offset; width: 53vw; margin-right: auto; height: 100%; } form { margin-left: $offset; font-size: 0.9rem; } .shadow { box-shadow: $basic-shadow-light !important; } </style> <script> import app from "../main"; export default { name: "userdetail", data() { return { password: "", passwordre: "", currentUser: {}, path: null, submitted: false, errors: { email: "", country: "", password: "", passwordre: "" } }; }, mounted() { this.currentUser = { ...this.user }; this.path = this.user.name; }, watch: { user() { this.currentUser = { ...this.user }; this.path = this.user.name; } }, computed: { user() { return this.$store.getters["usermanagement/currentUser"]; }, validationErrors() { const errorMessages = this.errors; return ( errorMessages.email || errorMessages.country || errorMessages.password || errorMessages.passwordre ); } }, methods: { closeDetailview() { this.$store.commit("usermanagement/clearCurrentUser"); this.$store.commit("usermanagement/setUserDetailsInvisible"); }, validateCountry(event) { if (event.target.value !== "") { this.errors.country = ""; } else { this.errors.country = "Please choose a valid country"; } }, validatePassword() { if (this.password !== this.passwordre) { this.errors.passwordre = "Passwords do not match!"; } else { this.errors.passwordre = ""; } if ( // rules according to issue 70 this.password.length < 8 || /\W/.test(this.password) == false || /\d/.test(this.password) == false ) { this.errors.password = "Password should at least be 8 char long including 1 digit and 1 special char like $"; } else { this.errors.password = ""; } }, validateEmailaddress(event) { if ( /* cf. types.go */ // eslint-disable-next-line /(?:[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( event.target.value ) ) { this.errors.email = ""; } else { this.errors.email = "invalid email"; } }, save() { if (this.validationErrors) 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; app.$toast.error({ title: "Backend Error", message: `${status}: ${data}` }); }); }) .catch(error => { this.submitted = false; const { status, data } = error.response; app.$toast.error({ title: "Error while saving user", message: `${status}: ${data}` }); }); } } }; </script>