Mercurial > gemma
comparison 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 |
comparison
equal
deleted
inserted
replaced
384:af82a8989b44 | 389:e7d5383bc358 |
---|---|
1 <template> | 1 <template> |
2 <div class="userdetails shadow"> | 2 <div class="userdetails shadow"> |
3 <div class="card"> | 3 <div class="card"> |
4 <div class="card-header text-white bg-info mb-3"> | 4 <div class="card-header text-white bg-info mb-3"> |
5 {{ currentUser.user }} | 5 {{ currentUser.user }} |
6 <span @click="closeDetailview" class="pull-right"><i class="fa fa-close"></i></span> | |
6 </div> | 7 </div> |
7 <div class="card-body"> | 8 <div class="card-body"> |
8 <form @submit.prevent="save"> | 9 <form @submit.prevent="save"> |
9 <div class="form-group row"> | 10 <div class="formfields"> |
10 <label for="country">Country</label> | 11 <div v-if="currentUser.isNew" class="form-group row"> |
11 <select class="form-control form-control-sm" v-model="currentUser.country"> | 12 <label for="user">Username</label> |
12 <option disabled value="">Please select one</option> | 13 <input type="user" class="form-control form-control-sm" id="user" aria-describedby="userHelp" v-model="currentUser.user"> |
13 <option>AT</option> | 14 <div v-show="errors.email" class="text-danger"><small><i class="fa fa-warning"></i> {{ errors.email }}</small></div> |
14 <option>RO</option> | 15 </div> |
15 <option>BG</option> | 16 <div class="form-group row"> |
16 </select> | 17 <label for="country">Country</label> |
18 <select class="form-control form-control-sm" v-on:change="validateCountry" v-model="currentUser.country"> | |
19 <option disabled value="">Please select one</option> | |
20 <option>AT</option> | |
21 <option>RO</option> | |
22 <option>BG</option> | |
23 </select> | |
24 <div v-show="errors.country" class="text-danger"><small><i class="fa fa-warning"></i> {{ errors.country }}</small></div> | |
25 </div> | |
26 <div class="form-group row"> | |
27 <label for="email">Email address</label> | |
28 <input type="email" v-on:change="validateEmailaddress" class="form-control form-control-sm" id="email" aria-describedby="emailHelp" v-model="currentUser.email"> | |
29 <div v-show="errors.email" class="text-danger"><small><i class="fa fa-warning"></i> {{ errors.email }}</small></div> | |
30 </div> | |
31 <div class="form-group row"> | |
32 <label for="role">Role</label> | |
33 <select class="form-control form-control-sm" v-model="currentUser.role"> | |
34 <option disabled value="">Please select one</option> | |
35 <option value="sys_admin">Sysadmin</option> | |
36 <option value="waterway_admin">Waterway Admin</option> | |
37 <option value="waterway_user">Waterway User</option> | |
38 </select> | |
39 </div> | |
40 <div class="form-group row"> | |
41 <label for="password">Password</label> | |
42 <input type="password" v-on:change="validatePassword" class="form-control form-control-sm" id="password" aria-describedby="passwordHelp" v-model="password"> | |
43 <div v-show="errors.password" class="text-danger"><small><i class="fa fa-warning"></i> {{ errors.password }}</small></div> | |
44 </div> | |
45 <div class="form-group row"> | |
46 <label for="passwordre">Retype Password</label> | |
47 <input type="password" v-on:change="validatePassword" class="form-control form-control-sm" id="passwordre" aria-describedby="passwordreHelp" v-model="passwordre"> | |
48 <div v-show="errors.passwordre" class="text-danger"><small><i class="fa fa-warning"></i> {{ errors.passwordre }}</small></div> | |
49 </div> | |
17 </div> | 50 </div> |
18 <div class="form-group row"> | 51 <div> |
19 <label for="email">Email address</label> | 52 <button type="submit" :disabled="submitted" class="btn btn-info pull-right">Submit</button> |
20 <input type="email" class="form-control form-control-sm" id="email" aria-describedby="emailHelp" v-model="currentUser.email"> | |
21 </div> | 53 </div> |
22 <div class="form-group row"> | |
23 <label for="role">Role</label> | |
24 <select class="form-control form-control-sm" v-model="currentUser.role"> | |
25 <option disabled value="">Please select one</option> | |
26 <option value="sys_admin">Sysadmin</option> | |
27 <option value="waterway_admin">Waterway Admin</option> | |
28 <option value="waterway_user">Waterway User</option> | |
29 </select> | |
30 </div> | |
31 <button type="submit" class="btn btn-primary pull-right">Submit</button> | |
32 </form> | 54 </form> |
33 </div> | 55 </div> |
34 </div> | 56 </div> |
35 </div> | 57 </div> |
36 </template> | 58 </template> |
37 | 59 |
38 <style lang="scss"> | 60 <style lang="scss"> |
39 @import "../assets/application.scss"; | 61 @import "../assets/application.scss"; |
40 | 62 |
63 .formfields { | |
64 width: 10vw; | |
65 } | |
66 | |
41 .userdetails { | 67 .userdetails { |
42 margin-top: $large-offset; | 68 margin-top: $large-offset; |
43 width: 30vw; | 69 width: 53vw; |
44 margin-right: auto; | 70 margin-right: auto; |
45 height: 100%; | 71 height: 100%; |
46 } | 72 } |
47 | 73 |
48 form { | 74 form { |
49 width: 20vw; | 75 margin-left: $offset; |
50 margin: auto; | 76 font-size: 0.9rem; |
51 } | 77 } |
52 | 78 |
53 .shadow { | 79 .shadow { |
54 box-shadow: $basic-shadow-light !important; | 80 box-shadow: $basic-shadow-light !important; |
55 } | 81 } |
59 | 85 |
60 export default { | 86 export default { |
61 name: "userdetail", | 87 name: "userdetail", |
62 data() { | 88 data() { |
63 return { | 89 return { |
90 password: "", | |
91 passwordre: "", | |
64 currentUser: {}, | 92 currentUser: {}, |
65 path: null | 93 path: null, |
94 submitted: false, | |
95 errors: { | |
96 email: "", | |
97 country: "", | |
98 password: "", | |
99 passwordre: "" | |
100 } | |
66 }; | 101 }; |
67 }, | 102 }, |
68 mounted() { | 103 mounted() { |
69 this.currentUser = { ...this.user }; | 104 this.currentUser = { ...this.user }; |
70 this.path = this.user.name; | 105 this.path = this.user.name; |
76 } | 111 } |
77 }, | 112 }, |
78 computed: { | 113 computed: { |
79 user() { | 114 user() { |
80 return this.$store.getters["usermanagement/currentUser"]; | 115 return this.$store.getters["usermanagement/currentUser"]; |
116 }, | |
117 validationErrors() { | |
118 const errorMessages = this.errors; | |
119 return ( | |
120 errorMessages.email || | |
121 errorMessages.country || | |
122 errorMessages.password || | |
123 errorMessages.passwordre | |
124 ); | |
81 } | 125 } |
82 }, | 126 }, |
83 methods: { | 127 methods: { |
128 closeDetailview() { | |
129 this.$store.commit("usermanagement/clearCurrentUser"); | |
130 this.$store.commit("usermanagement/setUserDetailsInvisible"); | |
131 }, | |
132 validateCountry(event) { | |
133 if (event.target.value !== "") { | |
134 this.errors.country = ""; | |
135 } else { | |
136 this.errors.country = "Please choose a valid country"; | |
137 } | |
138 }, | |
139 validatePassword() { | |
140 if (this.password !== this.passwordre) { | |
141 this.errors.passwordre = "Passwords do not match!"; | |
142 } else { | |
143 this.errors.passwordre = ""; | |
144 } | |
145 if ( | |
146 // rules according to issue 70 | |
147 this.password.length < 8 || | |
148 /\W/.test(this.password) == false || | |
149 /\d/.test(this.password) == false | |
150 ) { | |
151 this.errors.password = | |
152 "Password should at least be 8 char long including 1 digit and 1 special char like $"; | |
153 } else { | |
154 this.errors.password = ""; | |
155 } | |
156 }, | |
157 validateEmailaddress(event) { | |
158 if ( | |
159 /* cf. types.go */ | |
160 // eslint-disable-next-line | |
161 /(?:[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( | |
162 event.target.value | |
163 ) | |
164 ) { | |
165 this.errors.email = ""; | |
166 } else { | |
167 this.errors.email = "invalid email"; | |
168 } | |
169 }, | |
84 save() { | 170 save() { |
171 if (this.validationErrors) return; | |
172 if (this.password) this.currentUser.password = this.password; | |
173 this.submitted = true; | |
85 this.$store | 174 this.$store |
86 .dispatch("usermanagement/saveCurrentUser", { | 175 .dispatch("usermanagement/saveCurrentUser", { |
87 path: this.user.user, | 176 path: this.user.user, |
88 user: this.currentUser | 177 user: this.currentUser |
89 }) | 178 }) |
90 .then(() => { | 179 .then(() => { |
91 this.$store.commit("usermanagement/clearCurrentUser"); | 180 this.submitted = false; |
92 this.$store.dispatch("usermanagement/loadUsers").catch(error => { | 181 this.$store.dispatch("usermanagement/loadUsers").catch(error => { |
93 const { status, data } = error.response; | 182 const { status, data } = error.response; |
94 app.$toast.error({ | 183 app.$toast.error({ |
95 title: "Backend Error", | 184 title: "Backend Error", |
96 message: `${status}: ${data}` | 185 message: `${status}: ${data}` |
97 }); | 186 }); |
98 }); | 187 }); |
99 }) | 188 }) |
100 .catch(error => { | 189 .catch(error => { |
190 this.submitted = false; | |
101 const { status, data } = error.response; | 191 const { status, data } = error.response; |
102 app.$toast.error({ | 192 app.$toast.error({ |
103 title: "Error while saving user", | 193 title: "Error while saving user", |
104 message: `${status}: ${data}` | 194 message: `${status}: ${data}` |
105 }); | 195 }); |