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.$invalid || 69 v$.form.newPassword.maxLength.$invalid 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 99 v-if="v$.form.confirmPassword.sameAsPassword.$invalid" 100 > 101 {{ $t('pageProfileSettings.passwordsDoNotMatch') }} 102 </template> 103 </b-form-invalid-feedback> 104 </input-password-toggle> 105 </b-form-group> 106 </page-section> 107 </b-col> 108 </b-row> 109 <page-section :section-title="$t('pageProfileSettings.timezoneDisplay')"> 110 <p>{{ $t('pageProfileSettings.timezoneDisplayDesc') }}</p> 111 <b-row> 112 <b-col md="9" lg="8" xl="9"> 113 <b-form-group :label="$t('pageProfileSettings.timezone')"> 114 <b-form-radio 115 v-model="form.isUtcDisplay" 116 :value="true" 117 data-test-id="profileSettings-radio-defaultUTC" 118 > 119 {{ $t('pageProfileSettings.defaultUTC') }} 120 </b-form-radio> 121 <b-form-radio 122 v-model="form.isUtcDisplay" 123 :value="false" 124 data-test-id="profileSettings-radio-browserOffset" 125 > 126 {{ 127 $t('pageProfileSettings.browserOffset', { 128 timezone, 129 }) 130 }} 131 </b-form-radio> 132 </b-form-group> 133 </b-col> 134 </b-row> 135 </page-section> 136 <b-button 137 variant="primary" 138 type="submit" 139 data-test-id="profileSettings-button-saveSettings" 140 > 141 {{ $t('global.action.saveSettings') }} 142 </b-button> 143 </b-form> 144 </b-container> 145</template> 146 147<script> 148import BVToastMixin from '@/components/Mixins/BVToastMixin'; 149import InputPasswordToggle from '@/components/Global/InputPasswordToggle'; 150import { maxLength, minLength, sameAs } from '@vuelidate/validators'; 151import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; 152import LocalTimezoneLabelMixin from '@/components/Mixins/LocalTimezoneLabelMixin'; 153import PageTitle from '@/components/Global/PageTitle'; 154import PageSection from '@/components/Global/PageSection'; 155import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; 156import { useVuelidate } from '@vuelidate/core'; 157import { useI18n } from 'vue-i18n'; 158import i18n from '@/i18n'; 159 160export default { 161 name: 'ProfileSettings', 162 components: { InputPasswordToggle, PageSection, PageTitle }, 163 mixins: [ 164 BVToastMixin, 165 LocalTimezoneLabelMixin, 166 LoadingBarMixin, 167 VuelidateMixin, 168 ], 169 setup() { 170 return { 171 v$: useVuelidate(), 172 }; 173 }, 174 data() { 175 return { 176 $t: useI18n().t, 177 form: { 178 newPassword: '', 179 confirmPassword: '', 180 currentPassword: '', 181 isUtcDisplay: this.$store.getters['global/isUtcDisplay'], 182 }, 183 }; 184 }, 185 computed: { 186 username() { 187 return this.$store.getters['global/username']; 188 }, 189 passwordRequirements() { 190 return this.$store.getters['userManagement/accountPasswordRequirements']; 191 }, 192 timezone() { 193 return this.localOffset(); 194 }, 195 }, 196 created() { 197 this.startLoader(); 198 this.$store 199 .dispatch('userManagement/getAccountSettings') 200 .finally(() => this.endLoader()); 201 }, 202 validations() { 203 return { 204 form: { 205 newPassword: { 206 minLength: minLength(this.passwordRequirements.minLength), 207 maxLength: maxLength(this.passwordRequirements.maxLength), 208 }, 209 confirmPassword: { 210 sameAsPassword: sameAs('newPassword'), 211 }, 212 }, 213 }; 214 }, 215 methods: { 216 saveNewPasswordInputData() { 217 this.v$.form.confirmPassword.$touch(); 218 this.v$.form.newPassword.$touch(); 219 if (this.v$.$invalid) return; 220 let userData = { 221 originalUsername: this.username, 222 password: this.form.newPassword, 223 }; 224 225 this.$store 226 .dispatch('userManagement/updateUser', userData) 227 .then((message) => { 228 (this.form.newPassword = ''), 229 (this.form.confirmPassword = ''), 230 (this.form.currentPassword = ''); 231 this.v$.$reset(); 232 this.successToast(message); 233 this.$store.dispatch('authentication/logout'); 234 }) 235 .catch(({ message }) => this.errorToast(message)); 236 }, 237 saveTimeZonePrefrenceData() { 238 localStorage.setItem('storedUtcDisplay', this.form.isUtcDisplay); 239 this.$store.commit('global/setUtcTime', this.form.isUtcDisplay); 240 this.successToast( 241 i18n.global.t('pageProfileSettings.toast.successUpdatingTimeZone'), 242 ); 243 }, 244 submitForm() { 245 if ( 246 this.form.confirmPassword && 247 this.form.newPassword && 248 this.form.currentPassword 249 ) { 250 this.confirmAuthenticate(); 251 } 252 if ( 253 this.$store.getters['global/isUtcDisplay'] != this.form.isUtcDisplay 254 ) { 255 this.saveTimeZonePrefrenceData(); 256 } 257 }, 258 confirmAuthenticate() { 259 this.v$.form.newPassword.$touch(); 260 if (this.v$.$invalid) return; 261 262 const username = this.username; 263 const password = this.form.currentPassword; 264 265 this.$store 266 .dispatch('authentication/login', { username, password }) 267 .then(() => { 268 this.saveNewPasswordInputData(); 269 }) 270 .catch(() => { 271 this.v$.$reset(); 272 this.errorToast( 273 i18n.global.t('pageProfileSettings.toast.wrongCredentials'), 274 ); 275 }); 276 }, 277 }, 278}; 279</script> 280