feat: improve error handling of login fields

This commit is contained in:
kolaente 2021-11-28 17:06:56 +01:00 committed by Dominik Pschenitschni
parent 1d916e7e03
commit 66d5e851e8
No known key found for this signature in database
GPG key ID: B257AC0149F43A77

View file

@ -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>