feat: improve error handling of login fields
This commit is contained in:
parent
1d916e7e03
commit
66d5e851e8
1 changed files with 40 additions and 5 deletions
|
@ -21,14 +21,18 @@
|
||||||
v-focus
|
v-focus
|
||||||
@keyup.enter="submit"
|
@keyup.enter="submit"
|
||||||
tabindex="1"
|
tabindex="1"
|
||||||
|
@focusout="validateField('username')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="help is-danger" v-if="!usernameValid">
|
||||||
|
{{ $t('user.auth.usernameRequired') }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="label-with-link">
|
<div class="label-with-link">
|
||||||
<label class="label" for="password">{{ $t('user.auth.password') }}</label>
|
<label class="label" for="password">{{ $t('user.auth.password') }}</label>
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'user.password-reset.request' }"
|
:to="{ name: 'user.password-reset.request' }"
|
||||||
class="reset-password-link"
|
class="reset-password-link"
|
||||||
tabindex="6"
|
tabindex="6"
|
||||||
>
|
>
|
||||||
|
@ -43,12 +47,19 @@
|
||||||
:placeholder="$t('user.auth.passwordPlaceholder')"
|
:placeholder="$t('user.auth.passwordPlaceholder')"
|
||||||
ref="password"
|
ref="password"
|
||||||
required
|
required
|
||||||
type="password"
|
:type="passwordFieldType"
|
||||||
autocomplete="current-password"
|
autocomplete="current-password"
|
||||||
@keyup.enter="submit"
|
@keyup.enter="submit"
|
||||||
tabindex="2"
|
tabindex="2"
|
||||||
|
@focusout="validateField('password')"
|
||||||
/>
|
/>
|
||||||
|
<a @click="togglePasswordFieldType" class="password-field-type-toggle">
|
||||||
|
<icon :icon="passwordFieldType === 'password' ? 'eye' : 'eye-slash'"/>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="help is-danger" v-if="!passwordValid">
|
||||||
|
{{ $t('user.auth.passwordRequired') }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="field" v-if="needsTotpPasscode">
|
<div class="field" v-if="needsTotpPasscode">
|
||||||
<label class="label" for="totpPasscode">{{ $t('user.auth.totpTitle') }}</label>
|
<label class="label" for="totpPasscode">{{ $t('user.auth.totpTitle') }}</label>
|
||||||
|
@ -106,6 +117,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {useDebounceFn} from '@vueuse/core'
|
||||||
import {mapState} from 'vuex'
|
import {mapState} from 'vuex'
|
||||||
|
|
||||||
import {HTTPFactory} from '@/http-common'
|
import {HTTPFactory} from '@/http-common'
|
||||||
|
@ -123,6 +135,9 @@ export default {
|
||||||
return {
|
return {
|
||||||
confirmedEmailSuccess: false,
|
confirmedEmailSuccess: false,
|
||||||
errorMessage: '',
|
errorMessage: '',
|
||||||
|
usernameValid: true,
|
||||||
|
passwordValid: true,
|
||||||
|
passwordFieldType: 'password',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
|
@ -175,6 +190,13 @@ export default {
|
||||||
localAuthEnabled: state => state.config.auth.local.enabled,
|
localAuthEnabled: state => state.config.auth.local.enabled,
|
||||||
openidConnect: state => state.config.auth.openidConnect,
|
openidConnect: state => state.config.auth.openidConnect,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
validateField() {
|
||||||
|
// using computed so that debounced function definition stays
|
||||||
|
return useDebounceFn((field) => {
|
||||||
|
this[`${field}Valid`] = this.$refs[field].value !== ''
|
||||||
|
}, 100)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setLoading() {
|
setLoading() {
|
||||||
|
@ -187,6 +209,12 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
togglePasswordFieldType() {
|
||||||
|
this.passwordFieldType = this.passwordFieldType === 'password'
|
||||||
|
? 'text'
|
||||||
|
: 'password'
|
||||||
|
},
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
this.errorMessage = ''
|
this.errorMessage = ''
|
||||||
// Some browsers prevent Vue bindings from working with autofilled values.
|
// Some browsers prevent Vue bindings from working with autofilled values.
|
||||||
|
@ -205,7 +233,7 @@ export default {
|
||||||
await this.$store.dispatch('auth/login', credentials)
|
await this.$store.dispatch('auth/login', credentials)
|
||||||
this.$store.commit('auth/needsTotpPasscode', false)
|
this.$store.commit('auth/needsTotpPasscode', false)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.response && e.response.data.code === 1017 && !credentials.totpPasscode) {
|
if (e.response?.data.code === 1017 && !this.credentials.totpPasscode) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,9 +270,16 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: .5rem;
|
margin-bottom: .5rem;
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.password-field-type-toggle {
|
||||||
|
position: absolute;
|
||||||
|
top: .5rem;
|
||||||
|
right: 1rem;
|
||||||
|
color: var(--grey-400);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue