Mercurial > gemma
comparison client/src/components/admin/usermanagement/Userdetail.vue @ 1272:bc55ffaeb639
cleaned up client/src directory
better organization of files and directories, better naming, separation of admin and map context
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Thu, 22 Nov 2018 07:07:12 +0100 |
parents | |
children | 2738a6ae9ad8 |
comparison
equal
deleted
inserted
replaced
1268:aca692e73028 | 1272:bc55ffaeb639 |
---|---|
1 <template> | |
2 <div class="userdetails h-100 mt-3 mr-auto shadow fadeIn animated"> | |
3 <div class="card"> | |
4 <div class="card-header shadow-sm text-white bg-info mb-3"> | |
5 {{ this.cardHeader }} | |
6 <span @click="closeDetailview" class="pull-right"> | |
7 <i class="fa fa-close"></i> | |
8 </span> | |
9 </div> | |
10 <div class="card-body"> | |
11 <form @submit.prevent="save" class="ml-3"> | |
12 <div class="formfields"> | |
13 <div v-if="currentUser.isNew" class="form-group row"> | |
14 <label for="user">Username</label> | |
15 <input type="user" :placeholder="userNamePlaceholder" class="form-control form-control-sm" id="user" aria-describedby="userHelp" v-model="currentUser.user"> | |
16 <div v-show="errors.user" class="text-danger"> | |
17 <small> | |
18 <i class="fa fa-warning"></i> {{ errors.user }}</small> | |
19 </div> | |
20 </div> | |
21 <div class="form-group row"> | |
22 <label for="country">Country</label> | |
23 <select class="form-control form-control-sm" v-on:change="validateCountry" v-model="currentUser.country"> | |
24 <option disabled value="">Please select one</option> | |
25 <option v-for="country in countries" v-bind:value="country" v-bind:key="country">{{country}}</option> | |
26 </select> | |
27 <div v-show="errors.country" class="text-danger"> | |
28 <small> | |
29 <i class="fa fa-warning"></i> {{ errors.country }}</small> | |
30 </div> | |
31 </div> | |
32 <div class="form-group row"> | |
33 <label for="email">Email address</label> | |
34 <input type="email" v-on:change="validateEmailaddress" class="form-control form-control-sm" id="email" aria-describedby="emailHelp" v-model="currentUser.email"> | |
35 <div v-show="errors.email" class="text-danger"> | |
36 <small> | |
37 <i class="fa fa-warning"></i> {{ errors.email }}</small> | |
38 </div> | |
39 </div> | |
40 <div class="form-group row"> | |
41 <label for="role">Role</label> | |
42 <select class="form-control form-control-sm" v-on:change="validateRole" v-model="currentUser.role"> | |
43 <option disabled value="">Please select one</option> | |
44 <option value="sys_admin">Sysadmin</option> | |
45 <option value="waterway_admin">Waterway Admin</option> | |
46 <option value="waterway_user">Waterway User</option> | |
47 </select> | |
48 <div v-show="errors.role" class="text-danger"> | |
49 <small> | |
50 <i class="fa fa-warning"></i> {{ errors.role }}</small> | |
51 </div> | |
52 </div> | |
53 <div class="form-group row"> | |
54 <PasswordField @fieldchange="passwordChanged" :placeholder="passwordPlaceholder" :label="passwordLabel" :passworderrors="errors.password"></PasswordField> | |
55 </div> | |
56 <div class="form-group row"> | |
57 <PasswordField @fieldchange="passwordReChanged" :placeholder="passwordRePlaceholder" :label="passwordReLabel" :passworderrors="errors.passwordre"></PasswordField> | |
58 </div> | |
59 </div> | |
60 <div> | |
61 <button type="submit" :disabled="submitted" class="shadow-sm btn btn-info pull-right">Submit</button> | |
62 </div> | |
63 <div v-if="currentUser.role !='waterway_user' " class="form-group row d-flex flex-row justify-content-start mailbutton"> | |
64 <a @click="sendTestMail" class="btn btn-light"><i class="fa fa-telegram"> Send testmail</i></a> | |
65 <div v-if="mailsent">Mail was sent</div> | |
66 </div> | |
67 </form> | |
68 </div> | |
69 </div> | |
70 </div> | |
71 </template> | |
72 | |
73 <style lang="sass" scoped> | |
74 .mailbutton | |
75 width: 12vw | |
76 | |
77 .formfields | |
78 width: 10vw | |
79 | |
80 .userdetails | |
81 min-width: 40vw | |
82 | |
83 form | |
84 font-size: $smaller | |
85 </style> | |
86 | |
87 <script> | |
88 /* | |
89 * This is Free Software under GNU Affero General Public License v >= 3.0 | |
90 * without warranty, see README.md and license for details. | |
91 * | |
92 * SPDX-License-Identifier: AGPL-3.0-or-later | |
93 * License-Filename: LICENSES/AGPL-3.0.txt | |
94 * | |
95 * Copyright (C) 2018 by via donau | |
96 * – Österreichische Wasserstraßen-Gesellschaft mbH | |
97 * Software engineering by Intevation GmbH | |
98 * | |
99 * Author(s): | |
100 * Thomas Junk <thomas.junk@intevation.de> | |
101 */ | |
102 import { HTTP } from "../../../lib/http"; | |
103 import { displayError } from "../../../lib/errors.js"; | |
104 import { mapState } from "vuex"; | |
105 import PasswordField from "./Passwordfield"; | |
106 | |
107 const emptyErrormessages = () => { | |
108 return { | |
109 email: "", | |
110 country: "", | |
111 role: "", | |
112 password: "", | |
113 passwordre: "" | |
114 }; | |
115 }; | |
116 | |
117 const isEmailValid = email => { | |
118 /** | |
119 * | |
120 * For convenience purposes the same regex used as in the go code | |
121 * cf. types.go | |
122 * | |
123 */ | |
124 // eslint-disable-next-line | |
125 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( | |
126 email | |
127 ); | |
128 }; | |
129 | |
130 const violatedPasswordRules = password => { | |
131 return ( | |
132 // rules according to issue 70 | |
133 password.length < 7 || | |
134 /\W/.test(password) == false || | |
135 /\d/.test(password) == false | |
136 ); | |
137 }; | |
138 | |
139 export default { | |
140 name: "userdetail", | |
141 components: { | |
142 PasswordField | |
143 }, | |
144 data() { | |
145 return { | |
146 mailsent: false, | |
147 passwordLabel: "Password", | |
148 passwordReLabel: "Repeat Password", | |
149 passwordPlaceholder: "password", | |
150 passwordRePlaceholder: "password again", | |
151 password: "", | |
152 passwordre: "", | |
153 currentUser: {}, | |
154 path: null, | |
155 submitted: false, | |
156 errors: { | |
157 email: "", | |
158 country: "", | |
159 role: "", | |
160 password: "", | |
161 passwordre: "" | |
162 } | |
163 }; | |
164 }, | |
165 mounted() { | |
166 this.currentUser = { ...this.user }; | |
167 this.path = this.user.name; | |
168 }, | |
169 watch: { | |
170 user() { | |
171 this.currentUser = { ...this.user }; | |
172 this.path = this.user.name; | |
173 this.clearPassword(); | |
174 this.clearErrors(); | |
175 } | |
176 }, | |
177 computed: { | |
178 cardHeader() { | |
179 if (this.currentUser.isNew) return "N.N"; | |
180 return this.currentUser.user; | |
181 }, | |
182 userNamePlaceholder() { | |
183 if (this.currentUser.isNew) return "N.N"; | |
184 return ""; | |
185 }, | |
186 ...mapState("application", ["countries"]), | |
187 user() { | |
188 return this.$store.getters["usermanagement/currentUser"]; | |
189 }, | |
190 isFormValid() { | |
191 return ( | |
192 isEmailValid(this.currentUser.email) && | |
193 this.currentUser.country && | |
194 this.password === this.passwordre && | |
195 (this.password === "" || !violatedPasswordRules(this.password)) | |
196 ); | |
197 } | |
198 }, | |
199 methods: { | |
200 sendTestMail() { | |
201 if (this.mailsent) return; | |
202 HTTP.get("/testmail/" + this.currentUser.user, { | |
203 headers: { | |
204 "X-Gemma-Auth": localStorage.getItem("token"), | |
205 "Content-type": "text/xml; charset=UTF-8" | |
206 } | |
207 }) | |
208 .then(() => { | |
209 this.mailsent = true; | |
210 }) | |
211 .catch(error => { | |
212 this.loginFailed = true; | |
213 this.submitted = false; | |
214 const { status, data } = error.response; | |
215 displayError({ | |
216 title: "Backend Error", | |
217 message: `${status}: ${data.message || data}` | |
218 }); | |
219 }); | |
220 }, | |
221 passwordChanged(value) { | |
222 this.password = value; | |
223 this.validatePassword(); | |
224 }, | |
225 passwordReChanged(value) { | |
226 this.passwordre = value; | |
227 this.validatePassword(); | |
228 }, | |
229 clearErrors() { | |
230 this.errors = emptyErrormessages(); | |
231 }, | |
232 clearPassword() { | |
233 this.password = ""; | |
234 this.passwordre = ""; | |
235 }, | |
236 closeDetailview() { | |
237 this.$store.commit("usermanagement/clearCurrentUser"); | |
238 this.$store.commit("usermanagement/setUserDetailsInvisible"); | |
239 }, | |
240 validateCountry() { | |
241 this.errors.country = this.currentUser.country | |
242 ? "" | |
243 : "Please choose a country"; | |
244 }, | |
245 validateRole() { | |
246 this.errors.role = this.currentUser.role ? "" : "Please choose a role"; | |
247 }, | |
248 validatePassword() { | |
249 this.errors.passwordre = | |
250 this.password === this.passwordre ? "" : "Passwords do not match!"; | |
251 this.errors.password = | |
252 this.password === "" || !violatedPasswordRules(this.password) | |
253 ? "" | |
254 : "Password should at least be 8 char long including 1 digit and 1 special char like $"; | |
255 }, | |
256 validateEmailaddress() { | |
257 this.errors.email = isEmailValid(this.currentUser.email) | |
258 ? "" | |
259 : "invalid email"; | |
260 }, | |
261 validate() { | |
262 this.validateCountry(); | |
263 this.validateRole(); | |
264 this.validatePassword(); | |
265 this.validateEmailaddress(); | |
266 }, | |
267 save() { | |
268 this.validate(); | |
269 if (!this.isFormValid) return; | |
270 if (this.password) this.currentUser.password = this.password; | |
271 this.submitted = true; | |
272 this.$store | |
273 .dispatch("usermanagement/saveCurrentUser", { | |
274 path: this.user.user, | |
275 user: this.currentUser | |
276 }) | |
277 .then(() => { | |
278 this.submitted = false; | |
279 this.$store.dispatch("usermanagement/loadUsers").catch(error => { | |
280 const { status, data } = error.response; | |
281 displayError({ | |
282 title: "Backend Error", | |
283 message: `${status}: ${data.message || data}` | |
284 }); | |
285 }); | |
286 }) | |
287 .catch(error => { | |
288 this.submitted = false; | |
289 const { status, data } = error.response; | |
290 displayError({ | |
291 title: "Error while saving user", | |
292 message: `${status}: ${data.message || data}` | |
293 }); | |
294 }); | |
295 } | |
296 } | |
297 }; | |
298 </script> |