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>