1<template> 2 <b-container fluid="xl"> 3 <page-title /> 4 5 <b-row> 6 <b-col md="8" lg="8" xl="6"> 7 <page-section 8 :section-title="$t('pageProfileSettings.profileInfoTitle')" 9 > 10 <dl> 11 <dt>{{ $t('pageProfileSettings.username') }}</dt> 12 <dd> 13 {{ username }} 14 </dd> 15 </dl> 16 </page-section> 17 </b-col> 18 </b-row> 19 20 <b-form @submit.prevent="submitForm"> 21 <b-row> 22 <b-col sm="8" md="6" xl="3"> 23 <page-section 24 :section-title="$t('pageProfileSettings.changePassword')" 25 > 26 <b-form-group 27 id="input-group-0" 28 :label="$t('pageProfileSettings.currentPassword')" 29 label-for="input-0" 30 > 31 <input-password-toggle> 32 <b-form-input 33 id="old-password" 34 v-model="form.currentPassword" 35 type="password" 36 data-test-id="profileSettings-input-ocurrentPassword" 37 class="form-control-with-button" 38 /> 39 </input-password-toggle> 40 </b-form-group> 41 <b-form-group 42 id="input-group-1" 43 :label="$t('pageProfileSettings.newPassword')" 44 label-for="input-1" 45 > 46 <b-form-text id="password-help-block"> 47 {{ 48 $t('pageUserManagement.modal.passwordMustBeBetween', { 49 min: passwordRequirements.minLength, 50 max: passwordRequirements.maxLength, 51 }) 52 }} 53 </b-form-text> 54 <input-password-toggle> 55 <b-form-input 56 id="password" 57 v-model="form.newPassword" 58 type="password" 59 aria-describedby="password-help-block" 60 :state="getValidationState($v.form.newPassword)" 61 data-test-id="profileSettings-input-newPassword" 62 class="form-control-with-button" 63 @input="$v.form.newPassword.$touch()" 64 /> 65 <b-form-invalid-feedback role="alert"> 66 <template 67 v-if=" 68 !$v.form.newPassword.minLength || 69 !$v.form.newPassword.maxLength 70 " 71 > 72 {{ 73 $t('pageProfileSettings.newPassLabelTextInfo', { 74 min: passwordRequirements.minLength, 75 max: passwordRequirements.maxLength, 76 }) 77 }} 78 </template> 79 </b-form-invalid-feedback> 80 </input-password-toggle> 81 </b-form-group> 82 <b-form-group 83 id="input-group-2" 84 :label="$t('pageProfileSettings.confirmPassword')" 85 label-for="input-2" 86 > 87 <input-password-toggle> 88 <b-form-input 89 id="password-confirmation" 90 v-model="form.confirmPassword" 91 type="password" 92 :state="getValidationState($v.form.confirmPassword)" 93 data-test-id="profileSettings-input-confirmPassword" 94 class="form-control-with-button" 95 @input="$v.form.confirmPassword.$touch()" 96 /> 97 <b-form-invalid-feedback role="alert"> 98 <template v-if="!$v.form.confirmPassword.sameAsPassword"> 99 {{ $t('pageProfileSettings.passwordsDoNotMatch') }} 100 </template> 101 </b-form-invalid-feedback> 102 </input-password-toggle> 103 </b-form-group> 104 </page-section> 105 </b-col> 106 </b-row> 107 <page-section :section-title="$t('pageProfileSettings.timezoneDisplay')"> 108 <p>{{ $t('pageProfileSettings.timezoneDisplayDesc') }}</p> 109 <b-row> 110 <b-col md="9" lg="8" xl="9"> 111 <b-form-group :label="$t('pageProfileSettings.timezone')"> 112 <b-form-radio 113 v-model="form.isUtcDisplay" 114 :value="true" 115 data-test-id="profileSettings-radio-defaultUTC" 116 > 117 {{ $t('pageProfileSettings.defaultUTC') }} 118 </b-form-radio> 119 <b-form-radio 120 v-model="form.isUtcDisplay" 121 :value="false" 122 data-test-id="profileSettings-radio-browserOffset" 123 > 124 {{ 125 $t('pageProfileSettings.browserOffset', { 126 timezone, 127 }) 128 }} 129 </b-form-radio> 130 </b-form-group> 131 </b-col> 132 </b-row> 133 </page-section> 134 <b-button 135 variant="primary" 136 type="submit" 137 data-test-id="profileSettings-button-saveSettings" 138 > 139 {{ $t('global.action.saveSettings') }} 140 </b-button> 141 </b-form> 142 </b-container> 143</template> 144 145<script> 146import BVToastMixin from '@/components/Mixins/BVToastMixin'; 147import InputPasswordToggle from '@/components/Global/InputPasswordToggle'; 148import { maxLength, minLength, sameAs } from '@vuelidate/validators'; 149import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; 150import LocalTimezoneLabelMixin from '@/components/Mixins/LocalTimezoneLabelMixin'; 151import PageTitle from '@/components/Global/PageTitle'; 152import PageSection from '@/components/Global/PageSection'; 153import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; 154import { useVuelidate } from '@vuelidate/core'; 155 156export default { 157 name: 'ProfileSettings', 158 components: { InputPasswordToggle, PageSection, PageTitle }, 159 mixins: [ 160 BVToastMixin, 161 LocalTimezoneLabelMixin, 162 LoadingBarMixin, 163 VuelidateMixin, 164 ], 165 setup() { 166 return { 167 v$: useVuelidate(), 168 }; 169 }, 170 data() { 171 return { 172 form: { 173 newPassword: '', 174 confirmPassword: '', 175 currentPassword: '', 176 isUtcDisplay: this.$store.getters['global/isUtcDisplay'], 177 }, 178 }; 179 }, 180 computed: { 181 username() { 182 return this.$store.getters['global/username']; 183 }, 184 passwordRequirements() { 185 return this.$store.getters['userManagement/accountPasswordRequirements']; 186 }, 187 timezone() { 188 return this.localOffset(); 189 }, 190 }, 191 created() { 192 this.startLoader(); 193 this.$store 194 .dispatch('userManagement/getAccountSettings') 195 .finally(() => this.endLoader()); 196 }, 197 validations() { 198 return { 199 form: { 200 newPassword: { 201 minLength: minLength(this.passwordRequirements.minLength), 202 maxLength: maxLength(this.passwordRequirements.maxLength), 203 }, 204 confirmPassword: { 205 sameAsPassword: sameAs('newPassword'), 206 }, 207 }, 208 }; 209 }, 210 methods: { 211 saveNewPasswordInputData() { 212 this.$v.form.confirmPassword.$touch(); 213 this.$v.form.newPassword.$touch(); 214 if (this.$v.$invalid) return; 215 let userData = { 216 originalUsername: this.username, 217 password: this.form.newPassword, 218 }; 219 220 this.$store 221 .dispatch('userManagement/updateUser', userData) 222 .then((message) => { 223 (this.form.newPassword = ''), 224 (this.form.confirmPassword = ''), 225 (this.form.currentPassword = ''); 226 this.$v.$reset(); 227 this.successToast(message); 228 this.$store.dispatch('authentication/logout'); 229 }) 230 .catch(({ message }) => this.errorToast(message)); 231 }, 232 saveTimeZonePrefrenceData() { 233 localStorage.setItem('storedUtcDisplay', this.form.isUtcDisplay); 234 this.$store.commit('global/setUtcTime', this.form.isUtcDisplay); 235 this.successToast( 236 this.$t('pageProfileSettings.toast.successUpdatingTimeZone'), 237 ); 238 }, 239 submitForm() { 240 if ( 241 this.form.confirmPassword && 242 this.form.newPassword && 243 this.form.currentPassword 244 ) { 245 this.confirmAuthenticate(); 246 } 247 if ( 248 this.$store.getters['global/isUtcDisplay'] != this.form.isUtcDisplay 249 ) { 250 this.saveTimeZonePrefrenceData(); 251 } 252 }, 253 confirmAuthenticate() { 254 this.$v.form.newPassword.$touch(); 255 if (this.$v.$invalid) return; 256 257 const username = this.username; 258 const password = this.form.currentPassword; 259 260 this.$store 261 .dispatch('authentication/login', { username, password }) 262 .then(() => { 263 this.saveNewPasswordInputData(); 264 }) 265 .catch(() => { 266 this.$v.$reset(); 267 this.errorToast( 268 this.$t('pageProfileSettings.toast.wrongCredentials'), 269 ); 270 }); 271 }, 272 }, 273}; 274</script> 275