1<template> 2 <b-form 3 class="login-form mx-auto ml-md-5 mb-3" 4 novalidate 5 @submit.prevent="login" 6 > 7 <alert class="login-error mb-4" :show="authError" variant="danger"> 8 <p id="login-error-alert"> 9 {{ $t('pageLogin.alert.message') }} 10 </p> 11 </alert> 12 <b-form-group label-for="language" :label="$t('pageLogin.language')"> 13 <b-form-select 14 id="language" 15 v-model="$i18n.locale" 16 :options="languages" 17 data-test-id="login-select-language" 18 ></b-form-select> 19 </b-form-group> 20 <b-form-group label-for="username" :label="$t('pageLogin.username')"> 21 <b-form-input 22 id="username" 23 v-model="userInfo.username" 24 aria-describedby="login-error-alert username-required" 25 :state="getValidationState($v.userInfo.username)" 26 type="text" 27 autofocus="autofocus" 28 data-test-id="login-input-username" 29 @input="$v.userInfo.username.$touch()" 30 > 31 </b-form-input> 32 <b-form-invalid-feedback id="username-required" role="alert"> 33 <template v-if="!$v.userInfo.username.required"> 34 {{ $t('global.form.fieldRequired') }} 35 </template> 36 </b-form-invalid-feedback> 37 </b-form-group> 38 <div class="login-form__section mb-3"> 39 <label for="password">{{ $t('pageLogin.password') }}</label> 40 <b-form-input 41 id="password" 42 v-model="userInfo.password" 43 aria-describedby="login-error-alert password-required" 44 :state="getValidationState($v.userInfo.password)" 45 type="password" 46 data-test-id="login-input-password" 47 @input="$v.userInfo.password.$touch()" 48 > 49 </b-form-input> 50 <b-form-invalid-feedback id="password-required" role="alert"> 51 <template v-if="!$v.userInfo.password.required"> 52 {{ $t('global.form.fieldRequired') }} 53 </template> 54 </b-form-invalid-feedback> 55 </div> 56 <b-button 57 block 58 class="mt-5" 59 type="submit" 60 variant="primary" 61 data-test-id="login-button-submit" 62 :disabled="disableSubmitButton" 63 >{{ $t('pageLogin.logIn') }}</b-button 64 > 65 </b-form> 66</template> 67 68<script> 69import { required } from 'vuelidate/lib/validators'; 70import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; 71import i18n from '@/i18n'; 72import Alert from '@/components/Global/Alert'; 73 74export default { 75 name: 'Login', 76 components: { Alert }, 77 mixins: [VuelidateMixin], 78 data() { 79 return { 80 userInfo: { 81 username: null, 82 password: null, 83 }, 84 disableSubmitButton: false, 85 languages: [ 86 { 87 value: 'en-US', 88 text: 'English', 89 }, 90 { 91 value: 'es', 92 text: 'Español', 93 }, 94 { 95 value: 'ru-RU', 96 text: 'Русский', 97 }, 98 ], 99 }; 100 }, 101 computed: { 102 authError() { 103 return this.$store.getters['authentication/authError']; 104 }, 105 }, 106 validations: { 107 userInfo: { 108 username: { 109 required, 110 }, 111 password: { 112 required, 113 }, 114 }, 115 }, 116 methods: { 117 login: function () { 118 this.$v.$touch(); 119 if (this.$v.$invalid) return; 120 this.disableSubmitButton = true; 121 const username = this.userInfo.username; 122 const password = this.userInfo.password; 123 this.$store 124 .dispatch('authentication/login', { username, password }) 125 .then(() => { 126 localStorage.setItem('storedLanguage', i18n.locale); 127 localStorage.setItem('storedUsername', username); 128 this.$store.commit('global/setUsername', username); 129 this.$store.commit('global/setLanguagePreference', i18n.locale); 130 return this.$store.dispatch( 131 'authentication/checkPasswordChangeRequired', 132 username 133 ); 134 }) 135 .then((passwordChangeRequired) => { 136 if (passwordChangeRequired) { 137 this.$router.push('/change-password'); 138 } else { 139 this.$router.push('/'); 140 } 141 }) 142 .catch((error) => console.log(error)) 143 .finally(() => (this.disableSubmitButton = false)); 144 }, 145 }, 146}; 147</script> 148 149<style lang="scss" scoped> 150.login-form { 151 max-width: 360px; 152} 153</style> 154