frontend/src/views/user/Login.vue
konrad 1935af83c3 Allow setting api url from the login screen (#264)
Cleanup

Use the http factory everywhere instead of the created element

Use the current domain if the api path is relative to the frontend host

Format

Prevent setting an empty url

Fix styling

Add changing api url

Add change url component

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/frontend#264
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-10-11 10:13:35 +00:00

166 lines
4.2 KiB
Vue

<template>
<div>
<h2 class="title has-text-centered">Login</h2>
<div class="box">
<div class="notification is-success has-text-centered" v-if="confirmedEmailSuccess">
You successfully confirmed your email! You can log in now.
</div>
<api-config/>
<form @submit.prevent="submit" id="loginform">
<div class="field">
<label class="label" for="username">Username</label>
<div class="control">
<input
class="input" id="username"
name="username"
placeholder="e.g. frederick"
ref="username"
required
type="text"
v-focus
/>
</div>
</div>
<div class="field">
<label class="label" for="password">Password</label>
<div class="control">
<input
class="input"
id="password"
name="password"
placeholder="e.g. ••••••••••••"
ref="password"
required
type="password"
/>
</div>
</div>
<div class="field" v-if="needsTotpPasscode">
<label class="label" for="totpPasscode">Two Factor Authentication Code</label>
<div class="control">
<input
class="input"
id="totpPasscode"
placeholder="e.g. 123456"
ref="totpPasscode"
required
type="text"
v-focus
/>
</div>
</div>
<div class="field is-grouped login-buttons">
<div class="control is-expanded">
<button class="button is-primary" type="submit" v-bind:class="{ 'is-loading': loading}">Login
</button>
<router-link :to="{ name: 'user.register' }" class="button" v-if="registrationEnabled">Register
</router-link>
</div>
<div class="control">
<router-link :to="{ name: 'user.password-reset.request' }" class="reset-password-link">Reset
your
password
</router-link>
</div>
</div>
<div class="notification is-danger" v-if="errorMessage">
{{ errorMessage }}
</div>
</form>
<legal/>
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
import router from '../../router'
import {HTTPFactory} from '@/http-common'
import message from '../../message'
import {ERROR_MESSAGE, LOADING} from '@/store/mutation-types'
import legal from '../../components/misc/legal'
import ApiConfig from '@/components/misc/api-config'
export default {
components: {
ApiConfig,
legal,
},
data() {
return {
confirmedEmailSuccess: false,
}
},
beforeMount() {
const HTTP = HTTPFactory()
// Try to verify the email
// FIXME: Why is this here? Can we find a better place for this?
let emailVerifyToken = localStorage.getItem('emailConfirmToken')
if (emailVerifyToken) {
const cancel = message.setLoading(this)
HTTP.post(`user/confirm`, {token: emailVerifyToken})
.then(() => {
localStorage.removeItem('emailConfirmToken')
this.confirmedEmailSuccess = true
cancel()
})
.catch(e => {
cancel()
this.$store.commit(ERROR_MESSAGE, e.response.data.message)
})
}
// Check if the user is already logged in, if so, redirect him to the homepage
if (this.authenticated) {
router.push({name: 'home'})
}
},
created() {
this.setTitle('Login')
},
computed: mapState({
registrationEnabled: state => state.config.registrationEnabled,
loading: LOADING,
errorMessage: ERROR_MESSAGE,
needsTotpPasscode: state => state.auth.needsTotpPasscode,
authenticated: state => state.auth.authenticated,
}),
methods: {
submit() {
this.$store.commit(ERROR_MESSAGE, '')
// Some browsers prevent Vue bindings from working with autofilled values.
// To work around this, we're manually getting the values here instead of relying on vue bindings.
// For more info, see https://kolaente.dev/vikunja/frontend/issues/78
const credentials = {
username: this.$refs.username.value,
password: this.$refs.password.value,
}
if (this.needsTotpPasscode) {
credentials.totpPasscode = this.$refs.totpPasscode.value
}
this.$store.dispatch('auth/login', credentials)
.then(() => {
router.push({name: 'home'})
})
.catch(() => {
})
},
},
}
</script>
<style scoped>
.button {
margin: 0 0.4em 0 0;
}
.reset-password-link {
display: inline-block;
padding-top: 5px;
}
</style>