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-1" 28 :label="$t('pageProfileSettings.newPassword')" 29 label-for="input-1" 30 > 31 <b-form-text id="password-help-block"> 32 {{ 33 $t('pageLocalUserManagement.modal.passwordMustBeBetween', { 34 min: passwordRequirements.minLength, 35 max: passwordRequirements.maxLength 36 }) 37 }} 38 </b-form-text> 39 <input-password-toggle> 40 <b-form-input 41 id="password" 42 v-model="form.newPassword" 43 type="password" 44 aria-describedby="password-help-block" 45 :state="getValidationState($v.form.newPassword)" 46 @input="$v.form.newPassword.$touch()" 47 /> 48 <b-form-invalid-feedback role="alert"> 49 <template 50 v-if=" 51 !$v.form.newPassword.minLength || 52 !$v.form.newPassword.maxLength 53 " 54 > 55 {{ 56 $t('pageProfileSettings.newPassLabelTextInfo', { 57 min: passwordRequirements.minLength, 58 max: passwordRequirements.maxLength 59 }) 60 }} 61 </template> 62 </b-form-invalid-feedback> 63 </input-password-toggle> 64 </b-form-group> 65 <b-form-group 66 id="input-group-2" 67 :label="$t('pageProfileSettings.confirmPassword')" 68 label-for="input-2" 69 > 70 <input-password-toggle> 71 <b-form-input 72 id="password-confirmation" 73 v-model="form.confirmPassword" 74 type="password" 75 :state="getValidationState($v.form.confirmPassword)" 76 @input="$v.form.confirmPassword.$touch()" 77 /> 78 <b-form-invalid-feedback role="alert"> 79 <template v-if="!$v.form.confirmPassword.sameAsPassword"> 80 {{ $t('pageProfileSettings.passwordsDoNotMatch') }} 81 </template> 82 </b-form-invalid-feedback> 83 </input-password-toggle> 84 </b-form-group> 85 </page-section> 86 </b-col> 87 </b-row> 88 <page-section :section-title="$t('pageProfileSettings.timezoneDisplay')"> 89 <p>{{ $t('pageProfileSettings.timezoneDisplayDesc') }}</p> 90 <b-row> 91 <b-col md="9" lg="8" xl="9"> 92 <b-form-group :label="$t('pageProfileSettings.timezone')"> 93 <b-form-radio 94 v-model="form.isUtcDisplay" 95 :value="true" 96 @change="$v.form.isUtcDisplay.$touch()" 97 > 98 {{ $t('pageProfileSettings.defaultUTC') }} 99 </b-form-radio> 100 <b-form-radio 101 v-model="form.isUtcDisplay" 102 :value="false" 103 @change="$v.form.isUtcDisplay.$touch()" 104 > 105 {{ 106 $t('pageProfileSettings.browserOffset', { 107 timezone 108 }) 109 }} 110 </b-form-radio> 111 </b-form-group> 112 </b-col> 113 </b-row> 114 </page-section> 115 <b-button variant="primary" type="submit"> 116 {{ $t('global.action.saveSettings') }} 117 </b-button> 118 </b-form> 119 </b-container> 120</template> 121 122<script> 123import i18n from '@/i18n'; 124import BVToastMixin from '@/components/Mixins/BVToastMixin'; 125import InputPasswordToggle from '@/components/Global/InputPasswordToggle'; 126import { format } from 'date-fns-tz'; 127import { 128 maxLength, 129 minLength, 130 required, 131 sameAs 132} from 'vuelidate/lib/validators'; 133import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; 134import PageTitle from '@/components/Global/PageTitle'; 135import PageSection from '@/components/Global/PageSection'; 136import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; 137 138export default { 139 name: 'ProfileSettings', 140 components: { InputPasswordToggle, PageSection, PageTitle }, 141 mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin], 142 data() { 143 return { 144 form: { 145 newPassword: '', 146 confirmPassword: '', 147 isUtcDisplay: this.$store.getters['global/isUtcDisplay'] 148 } 149 }; 150 }, 151 computed: { 152 username() { 153 return this.$store.getters['global/username']; 154 }, 155 passwordRequirements() { 156 return this.$store.getters['localUsers/accountPasswordRequirements']; 157 }, 158 timezone() { 159 const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; 160 const shortTz = this.$options.filters.shortTimeZone(new Date()); 161 const pattern = `'${shortTz}' O`; 162 return format(new Date(), pattern, { timezone }).replace('GMT', 'UTC'); 163 } 164 }, 165 created() { 166 this.startLoader(); 167 this.$store 168 .dispatch('localUsers/getAccountSettings') 169 .finally(() => this.endLoader()); 170 }, 171 validations() { 172 return { 173 form: { 174 isUtcDisplay: { required }, 175 newPassword: { 176 minLength: minLength(this.passwordRequirements.minLength), 177 maxLength: maxLength(this.passwordRequirements.maxLength) 178 }, 179 confirmPassword: { 180 sameAsPassword: sameAs('newPassword') 181 } 182 } 183 }; 184 }, 185 methods: { 186 saveNewPasswordInputData() { 187 this.$v.form.confirmPassword.$touch(); 188 this.$v.form.newPassword.$touch(); 189 if (this.$v.$invalid) return; 190 let userData = { 191 originalUsername: this.username, 192 password: this.form.newPassword 193 }; 194 195 this.$store 196 .dispatch('localUsers/updateUser', userData) 197 .then(message => { 198 (this.form.newPassword = ''), (this.form.confirmPassword = ''); 199 this.$v.$reset(); 200 this.successToast(message); 201 }) 202 .catch(({ message }) => this.errorToast(message)); 203 }, 204 saveTimeZonePrefrenceData() { 205 localStorage.setItem('storedUtcDisplay', this.form.isUtcDisplay); 206 this.$store.commit('global/setUtcTime', this.form.isUtcDisplay); 207 this.successToast( 208 i18n.t('pageProfileSettings.toast.successSaveSettings') 209 ); 210 }, 211 submitForm() { 212 if (this.form.confirmPassword || this.form.newPassword) { 213 this.saveNewPasswordInputData(); 214 } 215 if (this.$v.form.isUtcDisplay.$anyDirty) { 216 this.saveTimeZonePrefrenceData(); 217 } 218 } 219 } 220}; 221</script> 222