feat(webui): metadata import settings per library

ability to edit libraries
move library add dialog to global instance

closes #199
This commit is contained in:
Gauthier Roebroeck 2020-07-03 15:03:43 +08:00
parent 6824212514
commit 521cc42858
16 changed files with 434 additions and 195 deletions

View file

@ -19,6 +19,11 @@
@deleted="collectionDeleted"
/>
<library-edit-dialog
v-model="editLibraryDialog"
:library="editLibrary"
/>
<library-delete-dialog
v-model="deleteLibraryDialog"
:library="deleteLibrary"
@ -43,7 +48,11 @@
<script lang="ts">
import CollectionAddToDialog from '@/components/dialogs/CollectionAddToDialog.vue'
import CollectionDeleteDialog from '@/components/dialogs/CollectionDeleteDialog.vue'
import CollectionEditDialog from '@/components/dialogs/CollectionEditDialog.vue'
import EditBooksDialog from '@/components/dialogs/EditBooksDialog.vue'
import EditSeriesDialog from '@/components/dialogs/EditSeriesDialog.vue'
import LibraryDeleteDialog from '@/components/dialogs/LibraryDeleteDialog.vue'
import LibraryEditDialog from '@/components/dialogs/LibraryEditDialog.vue'
import {
BOOK_CHANGED,
bookToEventBookChanged,
@ -57,9 +66,6 @@ import {
seriesToEventSeriesChanged,
} from '@/types/events'
import Vue from 'vue'
import EditBooksDialog from '@/components/dialogs/EditBooksDialog.vue'
import EditSeriesDialog from '@/components/dialogs/EditSeriesDialog.vue'
import CollectionEditDialog from '@/components/dialogs/CollectionEditDialog.vue'
export default Vue.extend({
name: 'Dialogs',
@ -67,6 +73,7 @@ export default Vue.extend({
CollectionAddToDialog,
CollectionEditDialog,
CollectionDeleteDialog,
LibraryEditDialog,
LibraryDeleteDialog,
EditBooksDialog,
EditSeriesDialog,
@ -105,6 +112,17 @@ export default Vue.extend({
deleteCollection (): CollectionDto {
return this.$store.state.deleteCollection
},
editLibraryDialog: {
get (): boolean {
return this.$store.state.editLibraryDialog
},
set (val) {
this.$store.dispatch('dialogEditLibraryDisplay', val)
},
},
editLibrary (): LibraryDto | undefined {
return this.$store.state.editLibrary
},
deleteLibraryDialog: {
get (): boolean {
return this.$store.state.deleteLibraryDialog

View file

@ -1,170 +0,0 @@
<template>
<div>
<v-dialog v-model="modalAddLibrary"
:fullscreen="this.$vuetify.breakpoint.xsOnly"
:hide-overlay="this.$vuetify.breakpoint.xsOnly"
max-width="450"
>
<v-card>
<v-toolbar class="hidden-sm-and-up">
<v-btn icon @click="dialogCancel">
<v-icon>mdi-close</v-icon>
</v-btn>
<v-toolbar-title>{{ dialogTitle }}</v-toolbar-title>
<v-spacer/>
<v-toolbar-items>
<v-btn text color="primary" @click="dialogConfirm">{{ confirmText }}</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-card-title class="hidden-xs-only">{{ dialogTitle }}</v-card-title>
<v-card-text>
<form novalidate>
<v-container fluid>
<v-row>
<v-col>
<v-text-field v-model="form.name"
label="Name"
:error-messages="getErrors('name')"
@input="$v.form.name.$touch()"
@blur="$v.form.name.$touch()"
/>
</v-col>
</v-row>
<v-row>
<v-col cols="8">
<file-browser-dialog
v-model="modalFileBrowser"
:path.sync="form.path"
confirm-text="Choose"
dialog-title="Library's root folder"
/>
<v-text-field v-model="form.path"
label="Root folder"
:error-messages="getErrors('path')"
@input="$v.form.path.$touch()"
@blur="$v.form.path.$touch()"
/>
</v-col>
<v-col cols="4">
<v-btn @click="modalFileBrowser = true">Browse</v-btn>
</v-col>
</v-row>
</v-container>
</form>
</v-card-text>
<v-card-actions class="hidden-xs-only">
<v-spacer/>
<v-btn text @click="dialogCancel">Cancel</v-btn>
<v-btn text class="primary--text" @click="dialogConfirm">{{ confirmText }}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<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 FileBrowserDialog from '@/components/dialogs/FileBrowserDialog.vue'
import Vue from 'vue'
import { required } from 'vuelidate/lib/validators'
export default Vue.extend({
name: 'LibraryAddDialog',
components: { FileBrowserDialog },
data: () => {
return {
modalAddLibrary: true,
modalFileBrowser: false,
snackbar: false,
snackText: '',
dialogTitle: 'Add Library',
confirmText: 'Add',
form: {
name: '',
path: '',
},
validationFieldNames: new Map([]),
}
},
watch: {
modalAddLibrary (val) {
!val && this.dialogCancel()
},
},
validations: {
form: {
name: { required },
path: { required },
},
},
methods: {
getErrors (fieldName: string) {
const errors = []
const field = this.$v.form!![fieldName] as any
if (field && field.$invalid && field.$dirty) {
const properName = this.validationFieldNames.has(fieldName)
? this.validationFieldNames.get(fieldName) : fieldName.charAt(0).toUpperCase() + fieldName.substring(1)
errors.push(`${properName} is required.`)
}
return errors
},
showSnack (message: string) {
this.snackText = message
this.snackbar = true
},
dialogCancel () {
this.$router.back()
},
dialogConfirm () {
this.addLibrary()
},
validateLibrary () {
this.$v.$touch()
if (!this.$v.$invalid) {
return {
name: this.form.name,
root: this.form.path,
}
}
return null
},
async addLibrary () {
const library = this.validateLibrary()
if (library) {
try {
await this.$store.dispatch('postLibrary', library)
this.$router.push({ name: 'home' })
} catch (e) {
this.showSnack(e.message)
}
}
},
},
})
</script>
<style scoped>
</style>

View file

@ -0,0 +1,276 @@
<template>
<div>
<v-dialog v-model="modal"
:fullscreen="this.$vuetify.breakpoint.xsOnly"
:hide-overlay="this.$vuetify.breakpoint.xsOnly"
max-width="600"
>
<form novalidate>
<v-card>
<v-toolbar class="hidden-sm-and-up">
<v-btn icon @click="dialogClose">
<v-icon>mdi-close</v-icon>
</v-btn>
<v-toolbar-title>{{ dialogTitle }}</v-toolbar-title>
<v-spacer/>
<v-toolbar-items>
<v-btn text color="primary" @click="dialogConfirm">{{ confirmText }}</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-card-title class="hidden-xs-only">{{ dialogTitle }}</v-card-title>
<v-tabs :vertical="$vuetify.breakpoint.smAndUp" v-model="tab">
<v-tab class="justify-start">
<v-icon left class="hidden-xs-only">mdi-bookshelf</v-icon>
General
</v-tab>
<v-tab class="justify-start">
<v-icon left class="hidden-xs-only">mdi-tune</v-icon>
Options
</v-tab>
<!-- Tab: General -->
<v-tab-item>
<v-card flat>
<v-container fluid>
<v-row>
<v-col>
<v-text-field v-model="form.name"
label="Name"
:error-messages="getErrors('name')"
@input="$v.form.name.$touch()"
@blur="$v.form.name.$touch()"
/>
</v-col>
</v-row>
<v-row>
<v-col cols="8">
<file-browser-dialog
v-model="modalFileBrowser"
:path.sync="form.path"
confirm-text="Choose"
dialog-title="Library's root folder"
/>
<v-text-field v-model="form.path"
label="Root folder"
:error-messages="getErrors('path')"
@input="$v.form.path.$touch()"
@blur="$v.form.path.$touch()"
/>
</v-col>
<v-col cols="4">
<v-btn @click="modalFileBrowser = true">Browse</v-btn>
</v-col>
</v-row>
</v-container>
</v-card>
</v-tab-item>
<!-- Tab: Options -->
<v-tab-item>
<v-card flat>
<v-container fluid>
<v-row>
<v-col>
<span class="subtitle-2">Import metadata for CBR/CBZ containing a ComicInfo.xml file</span>
<v-checkbox
v-model="form.importComicInfoBook"
label="Book metadata"
hide-details
/>
<v-checkbox
v-model="form.importComicInfoSeries"
label="Series title"
hide-details
/>
<!-- <v-checkbox-->
<!-- v-model="form.importComicInfoCollection"-->
<!-- label="Collections"-->
<!-- hide-details-->
<!-- />-->
</v-col>
</v-row>
<v-row>
<v-col>
<span class="subtitle-2">Import metadata from EPUB files</span>
<v-checkbox
v-model="form.importEpubBook"
label="Book metadata"
hide-details
/>
<v-checkbox
v-model="form.importEpubSeries"
label="Series title"
hide-details
/>
</v-col>
</v-row>
</v-container>
</v-card>
</v-tab-item>
</v-tabs>
<v-card-actions class="hidden-xs-only">
<v-spacer/>
<v-btn text @click="dialogClose">Cancel</v-btn>
<v-btn text class="primary--text" @click="dialogConfirm">{{ confirmText }}</v-btn>
</v-card-actions>
</v-card>
</form>
</v-dialog>
<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 FileBrowserDialog from '@/components/dialogs/FileBrowserDialog.vue'
import { LIBRARY_ADDED, LIBRARY_CHANGED, libraryToEventLibraryChanged } from '@/types/events'
import Vue from 'vue'
import { required } from 'vuelidate/lib/validators'
export default Vue.extend({
name: 'LibraryEditDialog',
components: { FileBrowserDialog },
data: () => {
return {
modal: false,
modalFileBrowser: false,
snackbar: false,
snackText: '',
tab: 0,
form: {
name: '',
path: '',
importComicInfoBook: true,
importComicInfoSeries: true,
importComicInfoCollection: true,
importEpubBook: true,
importEpubSeries: true,
},
validationFieldNames: new Map([]),
}
},
computed: {
dialogTitle (): string {
return this.library ? 'Edit Library' : 'Add Library'
},
confirmText (): string {
return this.library ? 'Edit' : 'Add'
},
},
props: {
value: Boolean,
library: {
type: Object as () => LibraryDto,
required: false,
},
},
watch: {
value (val) {
this.modal = val
},
modal (val) {
if (val) this.dialogReset(this.library)
else this.dialogClose()
},
},
validations: {
form: {
name: { required },
path: { required },
},
},
methods: {
getErrors (fieldName: string) {
const errors = []
const field = this.$v.form!![fieldName] as any
if (field && field.$invalid && field.$dirty) {
const properName = this.validationFieldNames.has(fieldName)
? this.validationFieldNames.get(fieldName) : fieldName.charAt(0).toUpperCase() + fieldName.substring(1)
errors.push(`${properName} is required.`)
}
return errors
},
showSnack (message: string) {
this.snackText = message
this.snackbar = true
},
dialogClose () {
this.$emit('input', false)
this.tab = 0
},
dialogConfirm () {
this.addLibrary()
},
dialogReset (library?: LibraryDto) {
this.form.name = library ? library.name : ''
this.form.path = library ? library.root : ''
this.form.importComicInfoBook = library ? library.importComicInfoBook : true
this.form.importComicInfoSeries = library ? library.importComicInfoSeries : true
this.form.importComicInfoCollection = library ? library.importComicInfoCollection : true
this.form.importEpubBook = library ? library.importEpubBook : true
this.form.importEpubSeries = library ? library.importEpubSeries : true
this.$v.$reset()
},
validateLibrary () {
this.$v.$touch()
console.log(this.form)
if (!this.$v.$invalid) {
return {
name: this.form.name,
root: this.form.path,
importComicInfoBook: this.form.importComicInfoBook,
importComicInfoSeries: this.form.importComicInfoSeries,
importComicInfoCollection: this.form.importComicInfoCollection,
importEpubBook: this.form.importEpubBook,
importEpubSeries: this.form.importEpubSeries,
}
}
return null
},
async addLibrary () {
const library = this.validateLibrary()
if (library) {
console.log(library)
try {
if (this.library) {
await this.$store.dispatch('updateLibrary', { libraryId: this.library.id, library: library })
this.$eventHub.$emit(LIBRARY_CHANGED, libraryToEventLibraryChanged(this.library))
} else {
await this.$store.dispatch('postLibrary', library)
this.$eventHub.$emit(LIBRARY_ADDED)
}
this.dialogClose()
} catch (e) {
this.showSnack(e.message)
}
} else {
this.tab = 0
}
},
},
})
</script>
<style scoped>
</style>

View file

@ -16,6 +16,9 @@
<v-list-item @click="refreshMetadata">
<v-list-item-title>Refresh metadata</v-list-item-title>
</v-list-item>
<v-list-item @click="edit">
<v-list-item-title>Edit</v-list-item-title>
</v-list-item>
<v-list-item @click="promptDeleteLibrary"
class="list-warning">
<v-list-item-title>Delete</v-list-item-title>
@ -50,6 +53,9 @@ export default Vue.extend({
refreshMetadata () {
this.$komgaLibraries.refreshMetadata(this.library)
},
edit () {
this.$store.dispatch('dialogEditLibrary', this.library)
},
promptDeleteLibrary () {
this.$store.dispatch('dialogDeleteLibrary', this.library)
},

View file

@ -25,11 +25,15 @@ const vuexModule: Module<any, any> = {
},
async postLibrary ({ dispatch }, library) {
await service.postLibrary(library)
dispatch('getLibraries')
await dispatch('getLibraries')
},
async updateLibrary ({ dispatch }, { libraryId, library }) {
await service.updateLibrary(libraryId, library)
await dispatch('getLibraries')
},
async deleteLibrary ({ dispatch }, library) {
await service.deleteLibrary(library)
dispatch('getLibraries')
await dispatch('getLibraries')
},
},
}

View file

@ -28,12 +28,6 @@ const router = new Router({
redirect: { name: 'dashboard' },
component: () => import(/* webpackChunkName: "home" */ './views/Home.vue'),
children: [
{
path: '/libraries/add',
name: 'addlibrary',
beforeEnter: adminGuard,
component: () => import(/* webpackChunkName: "addlibrary" */ './components/dialogs/LibraryAddDialog.vue'),
},
{
path: '/welcome',
name: 'welcome',

View file

@ -3,7 +3,7 @@ import { AxiosInstance } from 'axios'
const API_LIBRARIES = '/api/v1/libraries'
export default class KomgaLibrariesService {
private http: AxiosInstance;
private http: AxiosInstance
constructor (http: AxiosInstance) {
this.http = http
@ -45,6 +45,18 @@ export default class KomgaLibrariesService {
}
}
async updateLibrary (libraryId: number, library: LibraryUpdateDto) {
try {
await this.http.put(`${API_LIBRARIES}/${libraryId}`, library)
} catch (e) {
let msg = `An error occurred while trying to update library '${libraryId}'`
if (e.response.data.message) {
msg += `: ${e.response.data.message}`
}
throw new Error(msg)
}
}
async deleteLibrary (library: LibraryDto) {
try {
await this.http.delete(`${API_LIBRARIES}/${library.id}`)

View file

@ -11,6 +11,8 @@ export default new Vuex.Store({
editCollectionDialog: false,
deleteCollection: {} as CollectionDto,
deleteCollectionDialog: false,
editLibrary: {} as LibraryDto | undefined,
editLibraryDialog: false,
deleteLibrary: {} as LibraryDto,
deleteLibraryDialog: false,
updateBooks: {} as BookDto | BookDto[],
@ -34,6 +36,12 @@ export default new Vuex.Store({
setDeleteCollection (state, collection) {
state.deleteCollection = collection
},
setEditLibrary (state, library) {
state.editLibrary = library
},
setEditLibraryDialog (state, dialog) {
state.editLibraryDialog = dialog
},
setDeleteCollectionDialog (state, dialog) {
state.deleteCollectionDialog = dialog
},
@ -78,6 +86,17 @@ export default new Vuex.Store({
dialogDeleteCollectionDisplay ({ commit }, value) {
commit('setDeleteCollectionDialog', value)
},
dialogAddLibrary ({ commit }) {
commit('setEditLibrary', undefined)
commit('setEditLibraryDialog', true)
},
dialogEditLibrary ({ commit }, value) {
commit('setEditLibrary', value)
commit('setEditLibraryDialog', true)
},
dialogEditLibraryDisplay ({ commit }, value) {
commit('setEditLibraryDialog', value)
},
dialogDeleteLibrary ({ commit }, library) {
commit('setDeleteLibrary', library)
commit('setDeleteLibraryDialog', true)

View file

@ -16,6 +16,14 @@ interface EventCollectionDeleted {
id: number
}
interface EventLibraryAdded {
id: number
}
interface EventLibraryChanged {
id: number
}
interface EventLibraryDeleted {
id: number
}

View file

@ -2,6 +2,8 @@ export const BOOK_CHANGED = 'book-changed'
export const SERIES_CHANGED = 'series-changed'
export const COLLECTION_DELETED = 'collection-deleted'
export const COLLECTION_CHANGED = 'collection-changed'
export const LIBRARY_ADDED = 'library-added'
export const LIBRARY_CHANGED = 'library-changed'
export const LIBRARY_DELETED = 'library-deleted'
export function bookToEventBookChanged (book: BookDto): EventBookChanged {
@ -30,6 +32,18 @@ export function collectionToEventCollectionDeleted (collection: CollectionDto):
} as EventCollectionDeleted
}
export function libraryToEventLibraryAdded (library: LibraryDto): EventLibraryAdded {
return {
id: library.id,
} as EventLibraryAdded
}
export function libraryToEventLibraryChanged (library: LibraryDto): EventLibraryChanged {
return {
id: library.id,
} as EventLibraryChanged
}
export function libraryToEventLibraryDeleted (library: LibraryDto): EventLibraryDeleted {
return {
id: library.id,

View file

@ -1,10 +1,30 @@
interface LibraryCreationDto {
name: string,
root: string
root: string,
importComicInfoBook: boolean,
importComicInfoSeries: boolean,
importComicInfoCollection: boolean,
importEpubBook: boolean,
importEpubSeries: boolean
}
interface LibraryUpdateDto {
name: string,
root: string,
importComicInfoBook: boolean,
importComicInfoSeries: boolean,
importComicInfoCollection: boolean,
importEpubBook: boolean,
importEpubSeries: boolean
}
interface LibraryDto {
id: number,
name: string,
root: string
root: string,
importComicInfoBook: boolean,
importComicInfoSeries: boolean,
importComicInfoCollection: boolean,
importEpubBook: boolean,
importEpubSeries: boolean
}

View file

@ -38,12 +38,12 @@
<script lang="ts">
import Badge from '@/components/Badge.vue'
import ItemBrowser from '@/components/ItemBrowser.vue'
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
import LibraryNavigation from '@/components/LibraryNavigation.vue'
import PageSizeSelect from '@/components/PageSizeSelect.vue'
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
import { COLLECTION_CHANGED } from '@/types/events'
import ItemBrowser from '@/components/ItemBrowser.vue'
import LibraryNavigation from '@/components/LibraryNavigation.vue'
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
import PageSizeSelect from '@/components/PageSizeSelect.vue'
import { COLLECTION_CHANGED, LIBRARY_CHANGED } from '@/types/events'
import Vue from 'vue'
const cookiePageSize = 'pagesize'
@ -78,9 +78,11 @@ export default Vue.extend({
},
created () {
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCollections)
this.$eventHub.$on(LIBRARY_CHANGED, this.reloadLibrary)
},
beforeDestroy () {
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCollections)
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary)
},
mounted () {
if (this.$cookies.isKey(cookiePageSize)) {
@ -166,6 +168,11 @@ export default Vue.extend({
reloadCollections () {
this.loadLibrary(this.libraryId)
},
reloadLibrary (event: EventLibraryChanged) {
if (event.id === this.libraryId) {
this.loadLibrary(this.libraryId)
}
},
async loadLibrary (libraryId: number) {
this.library = this.getLibraryLazy(libraryId)
await this.loadPage(libraryId, this.page)

View file

@ -82,7 +82,7 @@ import SortMenuButton from '@/components/SortMenuButton.vue'
import { parseQueryFilter, parseQuerySort } from '@/functions/query-params'
import { ReadStatus } from '@/types/enum-books'
import { SeriesStatus } from '@/types/enum-series'
import { COLLECTION_CHANGED, LIBRARY_DELETED, SERIES_CHANGED } from '@/types/events'
import { COLLECTION_CHANGED, LIBRARY_CHANGED, LIBRARY_DELETED, SERIES_CHANGED } from '@/types/events'
import Vue from 'vue'
const cookiePageSize = 'pagesize'
@ -154,11 +154,13 @@ export default Vue.extend({
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCollections)
this.$eventHub.$on(SERIES_CHANGED, this.reloadSeries)
this.$eventHub.$on(LIBRARY_DELETED, this.libraryDeleted)
this.$eventHub.$on(LIBRARY_CHANGED, this.reloadLibrary)
},
beforeDestroy () {
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCollections)
this.$eventHub.$off(SERIES_CHANGED, this.reloadSeries)
this.$eventHub.$off(LIBRARY_DELETED, this.libraryDeleted)
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary)
},
mounted () {
if (this.$cookies.isKey(cookiePageSize)) {
@ -282,6 +284,11 @@ export default Vue.extend({
this.loadPage(this.libraryId, this.page, this.sortActive)
}
},
reloadLibrary (event: EventLibraryChanged) {
if (this.libraryId === 0 || event.id === this.libraryId) {
this.loadLibrary(this.libraryId)
}
},
async loadLibrary (libraryId: number) {
this.library = this.getLibraryLazy(libraryId)

View file

@ -134,12 +134,12 @@ export default Vue.extend({
}
},
created () {
this.$eventHub.$on(LIBRARY_DELETED, this.loadAll)
this.$eventHub.$on(LIBRARY_DELETED, this.libraryDeleted)
this.$eventHub.$on(SERIES_CHANGED, this.loadAll)
this.$eventHub.$on(BOOK_CHANGED, this.loadAll)
},
beforeDestroy () {
this.$eventHub.$off(LIBRARY_DELETED, this.loadAll)
this.$eventHub.$off(LIBRARY_DELETED, this.libraryDeleted)
this.$eventHub.$off(SERIES_CHANGED, this.loadAll)
this.$eventHub.$off(BOOK_CHANGED, this.loadAll)
},
@ -167,6 +167,13 @@ export default Vue.extend({
},
},
methods: {
libraryDeleted () {
if (this.$store.state.komgaLibraries.libraries.length === 0) {
this.$router.push({ name: 'welcome' })
} else {
this.loadAll()
}
},
loadAll () {
this.loadNewSeries()
this.loadUpdatedSeries()

View file

@ -42,7 +42,7 @@
<v-list-item-title>Libraries</v-list-item-title>
</v-list-item-content>
<v-list-item-action v-if="isAdmin">
<v-btn icon :to="{name: 'addlibrary'}" exact>
<v-btn icon @click.stop.capture.prevent="addLibrary">
<v-icon>mdi-plus</v-icon>
</v-btn>
</v-list-item-action>
@ -127,7 +127,6 @@ export default Vue.extend({
data: function () {
return {
drawerVisible: this.$vuetify.breakpoint.lgAndUp,
modalAddLibrary: false,
info: {} as ActuatorInfo,
}
},
@ -152,6 +151,9 @@ export default Vue.extend({
this.$store.dispatch('logout')
this.$router.push({ name: 'login' })
},
addLibrary () {
this.$store.dispatch('dialogAddLibrary')
},
},
})
</script>

View file

@ -9,13 +9,14 @@
<div class="text-center">
<h1 class="headline mt-4">Welcome to Komga</h1>
<p class="body-1">No libraries have been added yet!</p>
<v-btn color="primary" :to="{name: 'addlibrary'}" v-if="isAdmin">Add library</v-btn>
<v-btn color="primary" @click="addLibrary" v-if="isAdmin">Add library</v-btn>
</div>
</v-row>
</div>
</template>
<script lang="ts">
import { LIBRARY_ADDED } from '@/types/events'
import Vue from 'vue'
export default Vue.extend({
@ -25,11 +26,25 @@ export default Vue.extend({
return this.$store.getters.meAdmin
},
},
created () {
this.$eventHub.$on(LIBRARY_ADDED, this.libraryAdded)
},
beforeDestroy () {
this.$eventHub.$off(LIBRARY_ADDED, this.libraryAdded)
},
mounted () {
if (this.$store.state.komgaLibraries.libraries.length !== 0) {
this.$router.push({ name: 'dashboard' })
}
},
methods: {
libraryAdded () {
this.$router.push({ name: 'dashboard' })
},
addLibrary () {
this.$store.dispatch('dialogAddLibrary')
},
},
})
</script>