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'; 155import { useI18n } from 'vue-i18n'; 156import i18n from '@/i18n'; 157 158export default { 159 name: 'ProfileSettings', 160 components: { InputPasswordToggle, PageSection, PageTitle }, 161 mixins: [ 162 BVToastMixin, 163 LocalTimezoneLabelMixin, 164 LoadingBarMixin, 165 VuelidateMixin, 166 ], 167 setup() { 168 return { 169 v$: useVuelidate(), 170 }; 171 }, 172 data() { 173 return { 174 $t: useI18n().t, 175 form: { 176 newPassword: '', 177 confirmPassword: '', 178 currentPassword: '', 179 isUtcDisplay: this.$store.getters['global/isUtcDisplay'], 180 }, 181 }; 182 }, 183 computed: { 184 username() { 185 return this.$store.getters['global/username']; 186 }, 187 passwordRequirements() { 188 return this.$store.getters['userManagement/accountPasswordRequirements']; 189 }, 190 timezone() { 191 return this.localOffset(); 192 }, 193 }, 194 created() { 195 this.startLoader(); 196 this.$store 197 .dispatch('userManagement/getAccountSettings') 198 .finally(() => this.endLoader()); 199 }, 200 validations() { 201 return { 202 form: { 203 newPassword: { 204 minLength: minLength(this.passwordRequirements.minLength), 205 maxLength: maxLength(this.passwordRequirements.maxLength), 206 }, 207 confirmPassword: { 208 sameAsPassword: sameAs('newPassword'), 209 }, 210 }, 211 }; 212 }, 213 methods: { 214 saveNewPasswordInputData() { 215 this.v$.form.confirmPassword.$touch(); 216 this.v$.form.newPassword.$touch(); 217 if (this.v$.$invalid) return; 218 let userData = { 219 originalUsername: this.username, 220 password: this.form.newPassword, 221 }; 222 223 this.$store 224 .dispatch('userManagement/updateUser', userData) 225 .then((message) => { 226 (this.form.newPassword = ''), 227 (this.form.confirmPassword = ''), 228 (this.form.currentPassword = ''); 229 this.v$.$reset(); 230 this.successToast(message); 231 this.$store.dispatch('authentication/logout'); 232 }) 233 .catch(({ message }) => this.errorToast(message)); 234 }, 235 saveTimeZonePrefrenceData() { 236 localStorage.setItem('storedUtcDisplay', this.form.isUtcDisplay); 237 this.$store.commit('global/setUtcTime', this.form.isUtcDisplay); 238 this.successToast( 239 i18n.global.t('pageProfileSettings.toast.successUpdatingTimeZone'), 240 ); 241 }, 242 submitForm() { 243 if ( 244 this.form.confirmPassword && 245 this.form.newPassword && 246 this.form.currentPassword 247 ) { 248 this.confirmAuthenticate(); 249 } 250 if ( 251 this.$store.getters['global/isUtcDisplay'] != this.form.isUtcDisplay 252 ) { 253 this.saveTimeZonePrefrenceData(); 254 } 255 }, 256 confirmAuthenticate() { 257 this.v$.form.newPassword.$touch(); 258 if (this.v$.$invalid) return; 259 260 const username = this.username; 261 const password = this.form.currentPassword; 262 263 this.$store 264 .dispatch('authentication/login', { username, password }) 265 .then(() => { 266 this.saveNewPasswordInputData(); 267 }) 268 .catch(() => { 269 this.v$.$reset(); 270 this.errorToast( 271 i18n.global.t('pageProfileSettings.toast.wrongCredentials'), 272 ); 273 }); 274 }, 275 }, 276}; 277</script> 278