mirror of
https://github.com/gotson/komga.git
synced 2025-12-21 07:56:57 +01:00
remove browser authentication popup
add startup and login views moved data loading from components to Startup.vue add logout feature change library name loading to lazy loading
This commit is contained in:
parent
ca3ef08939
commit
c6ac232fdf
9 changed files with 196 additions and 59 deletions
|
|
@ -112,7 +112,7 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
async created () {
|
||||
this.libraryName = await this.getLibraryName()
|
||||
this.libraryName = await this.getLibraryNameLazy(this.libraryId)
|
||||
},
|
||||
mounted () {
|
||||
// fill series skeletons if an index is provided, so scroll position can be restored
|
||||
|
|
@ -226,13 +226,6 @@ export default Vue.extend({
|
|||
this.series.splice(page.number * page.size, page.size, ...page.content)
|
||||
this.pagesState[page.number] = LoadState.Loaded
|
||||
},
|
||||
async getLibraryName (): Promise<string> {
|
||||
if (this.libraryId !== 0) {
|
||||
return (await this.$komgaLibraries.getLibrary(this.libraryId)).name
|
||||
} else {
|
||||
return 'All libraries'
|
||||
}
|
||||
},
|
||||
getLibraryNameLazy (libraryId: any): string {
|
||||
if (libraryId !== 0) {
|
||||
return (this.$store.getters.getLibraryById(libraryId)).name
|
||||
|
|
|
|||
|
|
@ -98,13 +98,6 @@ export default Vue.extend({
|
|||
this.dialogReset(val)
|
||||
}
|
||||
},
|
||||
async mounted () {
|
||||
try {
|
||||
await this.$store.dispatch('getLibraries')
|
||||
} catch (e) {
|
||||
this.showSnack(e.message)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
libraries (): LibraryDto[] {
|
||||
return this.$store.state.komgaLibraries.libraries
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ export default {
|
|||
install (Vue: typeof _Vue) {
|
||||
Vue.prototype.$http = axios.create({
|
||||
baseURL: process.env.VUE_APP_KOMGA_API_URL ? process.env.VUE_APP_KOMGA_API_URL : window.location.origin,
|
||||
withCredentials: true
|
||||
withCredentials: true,
|
||||
headers: { 'X-Requested-With': 'XMLHttpRequest' }
|
||||
} as AxiosRequestConfig)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ const vuexModule: Module<any, any> = {
|
|||
users: [] as UserWithSharedLibrariesDto[]
|
||||
},
|
||||
getters: {
|
||||
meAdmin: state => state.me.hasOwnProperty('roles') && state.me.roles.includes('ADMIN')
|
||||
meAdmin: state => state.me.hasOwnProperty('roles') && state.me.roles.includes('ADMIN'),
|
||||
authenticated: state => state.me.hasOwnProperty('id')
|
||||
},
|
||||
mutations: {
|
||||
setMe (state, user: UserDto) {
|
||||
|
|
@ -22,6 +23,16 @@ const vuexModule: Module<any, any> = {
|
|||
}
|
||||
},
|
||||
actions: {
|
||||
async getMeWithAuth ({ commit }, { login, password }: { login: string, password: string }) {
|
||||
commit('setMe', await service.getMeWithAuth(login, password))
|
||||
},
|
||||
async logout ({ commit }) {
|
||||
try {
|
||||
await service.getMeWithAuth('', '')
|
||||
} catch (e) {
|
||||
}
|
||||
commit('setMe', {})
|
||||
},
|
||||
async getMe ({ commit }) {
|
||||
commit('setMe', await service.getMe())
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ const adminGuard = (to: any, from: any, next: any) => {
|
|||
else next()
|
||||
}
|
||||
|
||||
export default new Router({
|
||||
const router = new Router({
|
||||
mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
routes: [
|
||||
|
|
@ -75,12 +75,20 @@ export default new Router({
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/startup',
|
||||
name: 'startup',
|
||||
component: () => import(/* webpackChunkName: "startup" */ './views/Startup.vue')
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: () => import(/* webpackChunkName: "login" */ './views/Login.vue')
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
name:
|
||||
'notfound',
|
||||
component:
|
||||
() => import(/* webpackChunkName: "notfound" */ './views/PageNotFound.vue')
|
||||
name: 'notfound',
|
||||
component: () => import(/* webpackChunkName: "notfound" */ './views/PageNotFound.vue')
|
||||
}
|
||||
],
|
||||
scrollBehavior (to, from, savedPosition) {
|
||||
|
|
@ -93,3 +101,10 @@ export default new Router({
|
|||
}
|
||||
}
|
||||
})
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (to.name !== 'startup' && to.name !== 'login' && !lStore.getters.authenticated) next({ name: 'startup' })
|
||||
else next()
|
||||
})
|
||||
|
||||
export default router
|
||||
|
|
|
|||
|
|
@ -9,6 +9,31 @@ export default class KomgaUsersService {
|
|||
this.http = http
|
||||
}
|
||||
|
||||
async getMeWithAuth (login: string, password: string): Promise<UserDto> {
|
||||
try {
|
||||
return (await this.http.get(
|
||||
`${API_USERS}/me`,
|
||||
{
|
||||
auth: {
|
||||
username: login,
|
||||
password: password
|
||||
}
|
||||
}
|
||||
)).data
|
||||
} catch (e) {
|
||||
let msg = 'An error occurred while trying to login'
|
||||
if (e.response) {
|
||||
if (e.response.status === 401) {
|
||||
msg = 'Invalid authentication'
|
||||
}
|
||||
}
|
||||
if (e.response.data.message) {
|
||||
msg += `: ${e.response.data.message}`
|
||||
}
|
||||
throw new Error(msg)
|
||||
}
|
||||
}
|
||||
|
||||
async getMe (): Promise<UserDto> {
|
||||
try {
|
||||
return (await this.http.get(`${API_USERS}/me`)).data
|
||||
|
|
|
|||
|
|
@ -96,14 +96,14 @@
|
|||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<!-- <v-list-item @click="logout">-->
|
||||
<!-- <v-list-item-icon>-->
|
||||
<!-- <v-icon>mdi-power</v-icon>-->
|
||||
<!-- </v-list-item-icon>-->
|
||||
<!-- <v-list-item-content>-->
|
||||
<!-- <v-list-item-title>Log out</v-list-item-title>-->
|
||||
<!-- </v-list-item-content>-->
|
||||
<!-- </v-list-item>-->
|
||||
<v-list-item @click="logout">
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-power</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>Log out</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
|
||||
|
|
@ -114,20 +114,6 @@
|
|||
<library-delete-dialog v-model="modalDeleteLibrary"
|
||||
:library="libraryToDelete">
|
||||
</library-delete-dialog>
|
||||
|
||||
<v-snackbar
|
||||
v-model="snackbar"
|
||||
bottom
|
||||
color="error"
|
||||
>
|
||||
{{ snackText }}
|
||||
<v-btn
|
||||
text
|
||||
@click="snackbar = false"
|
||||
>
|
||||
Close
|
||||
</v-btn>
|
||||
</v-snackbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -142,9 +128,7 @@ export default Vue.extend({
|
|||
drawerVisible: true,
|
||||
modalAddLibrary: false,
|
||||
modalDeleteLibrary: false,
|
||||
libraryToDelete: {} as LibraryDto,
|
||||
snackbar: false,
|
||||
snackText: ''
|
||||
libraryToDelete: {} as LibraryDto
|
||||
}),
|
||||
computed: {
|
||||
libraries (): LibraryDto[] {
|
||||
|
|
@ -165,27 +149,17 @@ export default Vue.extend({
|
|||
return []
|
||||
}
|
||||
},
|
||||
async mounted () {
|
||||
try {
|
||||
await this.$store.dispatch('getMe')
|
||||
await this.$store.dispatch('getLibraries')
|
||||
} catch (e) {
|
||||
this.showSnack(e.message)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleDrawer () {
|
||||
this.drawerVisible = !this.drawerVisible
|
||||
},
|
||||
showSnack (message: string) {
|
||||
this.snackText = message
|
||||
this.snackbar = true
|
||||
},
|
||||
promptDeleteLibrary (library: LibraryDto) {
|
||||
this.libraryToDelete = library
|
||||
this.modalDeleteLibrary = true
|
||||
},
|
||||
logout () {
|
||||
this.$store.dispatch('logout')
|
||||
this.$router.push({ name: 'login' })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
95
komga-webui/src/views/Login.vue
Normal file
95
komga-webui/src/views/Login.vue
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
<template>
|
||||
<div class="ma-3">
|
||||
<v-row align="center" justify="center">
|
||||
<v-img src="../assets/logo.svg"
|
||||
max-width="400"
|
||||
/>
|
||||
</v-row>
|
||||
|
||||
<form novalidate @submit.prevent="performLogin">
|
||||
<v-row justify="center">
|
||||
<v-col cols="3" xs="12">
|
||||
<v-text-field v-model="form.login"
|
||||
label="Login"
|
||||
autocomplete="username"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row justify="center">
|
||||
<v-col cols="3" xs="12">
|
||||
<v-text-field v-model="form.password"
|
||||
label="Password"
|
||||
type="password"
|
||||
autocomplete="current-password"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row justify="center">
|
||||
<v-col cols="3" xs="12">
|
||||
<v-btn color="primary"
|
||||
type="submit"
|
||||
>Login
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</form>
|
||||
|
||||
<v-snackbar
|
||||
v-model="snackbar"
|
||||
bottom
|
||||
color="error"
|
||||
>
|
||||
{{ snackText }}
|
||||
<v-btn
|
||||
text
|
||||
@click="snackbar = false"
|
||||
>
|
||||
Close
|
||||
</v-btn>
|
||||
</v-snackbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'Login',
|
||||
data: () => ({
|
||||
form: {
|
||||
login: '',
|
||||
password: ''
|
||||
},
|
||||
snackbar: false,
|
||||
snackText: ''
|
||||
}),
|
||||
methods: {
|
||||
async performLogin () {
|
||||
try {
|
||||
await this.$store.dispatch(
|
||||
'getMeWithAuth',
|
||||
{
|
||||
login: this.form.login,
|
||||
password: this.form.password
|
||||
})
|
||||
|
||||
await this.$store.dispatch('getLibraries')
|
||||
|
||||
this.$router.push({ name: 'home' })
|
||||
} catch (e) {
|
||||
this.showSnack(e.message)
|
||||
}
|
||||
},
|
||||
showSnack (message: string) {
|
||||
this.snackText = message
|
||||
this.snackbar = true
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
30
komga-webui/src/views/Startup.vue
Normal file
30
komga-webui/src/views/Startup.vue
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<div class="ma-3">
|
||||
<v-row align="center" justify="center">
|
||||
<v-img src="../assets/logo.svg"
|
||||
max-width="400"
|
||||
/>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'Startup',
|
||||
async mounted () {
|
||||
try {
|
||||
await this.$store.dispatch('getMe')
|
||||
await this.$store.dispatch('getLibraries')
|
||||
this.$router.push({ name: 'home' })
|
||||
} catch (e) {
|
||||
this.$router.push({ name: 'login' })
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
Loading…
Reference in a new issue