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 }; 96 }, 97 computed: { 98 authError() { 99 return this.$store.getters['authentication/authError']; 100 } 101 }, 102 validations: { 103 userInfo: { 104 username: { 105 required 106 }, 107 password: { 108 required 109 } 110 } 111 }, 112 methods: { 113 login: function() { 114 this.$v.$touch(); 115 if (this.$v.$invalid) return; 116 this.disableSubmitButton = true; 117 const username = this.userInfo.username; 118 const password = this.userInfo.password; 119 this.$store 120 .dispatch('authentication/login', { username, password }) 121 .then(() => { 122 localStorage.setItem('storedLanguage', i18n.locale); 123 localStorage.setItem('storedUsername', username); 124 this.$store.commit('global/setUsername', username); 125 this.$store.commit('global/setLanguagePreference', i18n.locale); 126 return this.$store.dispatch( 127 'authentication/checkPasswordChangeRequired', 128 username 129 ); 130 }) 131 .then(passwordChangeRequired => { 132 if (passwordChangeRequired) { 133 this.$router.push('/change-password'); 134 } else { 135 this.$router.push('/'); 136 } 137 }) 138 .catch(error => console.log(error)) 139 .finally(() => (this.disableSubmitButton = false)); 140 } 141 } 142}; 143</script> 144 145<style lang="scss" scoped> 146.login-form { 147 max-width: 360px; 148} 149</style> 150