mirror of
https://github.com/gotson/komga.git
synced 2026-02-13 10:53:55 +01:00
feat(webui): add ability to reorder libraries
This commit is contained in:
parent
8c64639884
commit
a2a689f7d5
10 changed files with 429 additions and 265 deletions
134
komga-webui/src/components/ReorderLibraries.vue
Normal file
134
komga-webui/src/components/ReorderLibraries.vue
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
<template>
|
||||
<div>
|
||||
<v-list>
|
||||
<v-list-item class="contrast-1">
|
||||
<v-list-item-content>
|
||||
<v-list-item-title class="text-uppercase">{{ $t('common.reorder') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action class="ma-0">
|
||||
<v-btn icon @click.stop.capture.prevent="dismiss">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item class="text--disabled">
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-home</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t('navigation.home') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<draggable
|
||||
v-model="localItems"
|
||||
v-bind="dragOptions"
|
||||
handle=".handle"
|
||||
>
|
||||
<template v-for="(l, index) in localItems">
|
||||
<v-hover :key="index"
|
||||
v-slot="{ hover }"
|
||||
:disabled="!l.unpinned"
|
||||
>
|
||||
<v-list-item>
|
||||
<v-list-item-icon>
|
||||
<v-icon class="handle">mdi-drag-horizontal-variant</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title class="handle">{{ l.name }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-icon>
|
||||
<v-btn icon v-if="!l.unpinned" @click.stop.capture.prevent="unpin(l.id)" x-small>
|
||||
<v-icon>mdi-pin</v-icon>
|
||||
</v-btn>
|
||||
<v-btn icon v-if="hover && l.unpinned" @click.stop.capture.prevent="pin(l.id)" x-small>
|
||||
<v-icon>mdi-pin-off</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-icon>
|
||||
</v-list-item>
|
||||
</v-hover>
|
||||
</template>
|
||||
</draggable>
|
||||
</v-list>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import draggable from 'vuedraggable'
|
||||
import {LibraryDto} from '@/types/komga-libraries'
|
||||
import {ClientSettingLibraryUpdate} from '@/types/komga-clientsettings'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'ReorderLibraries',
|
||||
components: {draggable},
|
||||
data: () => {
|
||||
return {
|
||||
localItems: [] as LibraryDto[],
|
||||
unwatch: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dragOptions(): any {
|
||||
return {
|
||||
animation: 200,
|
||||
// group: 'item-cards',
|
||||
ghostClass: 'ghost',
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.localItems = this.$store.getters.getLibraries
|
||||
},
|
||||
watch: {
|
||||
localItems: {
|
||||
handler(val: LibraryDto[]) {
|
||||
const newSettings = val.map((it, index) => ({
|
||||
libraryId: it.id,
|
||||
patch: {
|
||||
order: index,
|
||||
},
|
||||
} as ClientSettingLibraryUpdate))
|
||||
|
||||
this.$store.dispatch('updateLibrariesSettings', newSettings)
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
dismiss() {
|
||||
this.$emit('dismiss')
|
||||
},
|
||||
unpin(libraryId: string) {
|
||||
this.$store.dispatch('updateLibrarySetting', {
|
||||
libraryId: libraryId,
|
||||
patch: {
|
||||
unpinned: true,
|
||||
},
|
||||
} as ClientSettingLibraryUpdate)
|
||||
this.localItems.find(it => it.id == libraryId).unpinned = true
|
||||
},
|
||||
pin(libraryId: string) {
|
||||
this.$store.dispatch('updateLibrarySetting', {
|
||||
libraryId: libraryId,
|
||||
patch: {
|
||||
unpinned: false,
|
||||
},
|
||||
} as ClientSettingLibraryUpdate)
|
||||
this.localItems.find(it => it.id == libraryId).unpinned = false
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.handle {
|
||||
cursor: grab !important;
|
||||
}
|
||||
|
||||
.ghost {
|
||||
opacity: 0.5;
|
||||
background: #c8ebfb;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -188,7 +188,7 @@ export default Vue.extend({
|
|||
},
|
||||
computed: {
|
||||
libraries(): LibraryDto[] {
|
||||
return this.$store.getters.getLibraries
|
||||
return this.$store.state.komgaLibraries.libraries
|
||||
},
|
||||
ageRestrictionsAvailable(): any[] {
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -1,19 +1,22 @@
|
|||
<template>
|
||||
<div>
|
||||
<v-menu offset-y v-if="isAdmin">
|
||||
<v-menu offset-y>
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn icon v-on="on" @click.prevent="">
|
||||
<v-icon>mdi-dots-vertical</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list dense>
|
||||
<v-list-item @click="scan(false)">
|
||||
<v-list-item @click="reorder">
|
||||
<v-list-item-title>{{ $t('common.reorder') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="scan(false)" v-if="isAdmin">
|
||||
<v-list-item-title>{{ $t('server.server_management.button_scan_libraries') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="scan(true)" class="list-warning">
|
||||
<v-list-item @click="scan(true)" class="list-warning" v-if="isAdmin">
|
||||
<v-list-item-title>{{ $t('server.server_management.button_scan_libraries_deep') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="confirmEmptyTrash = true">
|
||||
<v-list-item @click="confirmEmptyTrash = true" v-if="isAdmin">
|
||||
<v-list-item-title>{{ $t('server.server_management.button_empty_trash') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
|
@ -31,7 +34,6 @@
|
|||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import ConfirmationDialog from '@/components/dialogs/ConfirmationDialog.vue'
|
||||
import {LibraryDto} from '@/types/komga-libraries'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'LibrariesActionsMenu',
|
||||
|
|
@ -47,6 +49,9 @@ export default Vue.extend({
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
reorder() {
|
||||
this.$emit('reorder')
|
||||
},
|
||||
scan(scanDeep: boolean) {
|
||||
this.$store.state.komgaLibraries.libraries.forEach(library => {
|
||||
this.$komgaLibraries.scanLibrary(library, scanDeep)
|
||||
|
|
|
|||
|
|
@ -269,6 +269,7 @@
|
|||
"readlist": "Read List",
|
||||
"readlists": "Read Lists",
|
||||
"remember-me": "Remember me",
|
||||
"reorder": "Reorder",
|
||||
"required": "Required",
|
||||
"reset_filters": "Reset filters",
|
||||
"roles": "Roles",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const vuexModule: Module<any, any> = {
|
|||
const settings = getters.getClientSettingsLibraries
|
||||
return state.libraries
|
||||
.map((it: LibraryDto) => Object.assign({}, it, settings[it.id]))
|
||||
.sort((a: LibraryDto, b: LibraryDto) => a.name.toLowerCase() > b.name.toLowerCase())
|
||||
.sort((a: LibraryDto, b: LibraryDto) => a.order > b.order)
|
||||
},
|
||||
getLibraryById: (state, getters) => (id: number) => {
|
||||
return getters.getLibraries.find((l: any) => l.id === id)
|
||||
|
|
|
|||
|
|
@ -55,6 +55,17 @@ const vuexModule: Module<any, any> = {
|
|||
await service.updateClientSettingUser(newSettings)
|
||||
dispatch('getClientSettingsUser')
|
||||
},
|
||||
async updateLibrariesSettings({dispatch, getters}, updates: ClientSettingLibraryUpdate[]) {
|
||||
const all = getters.getClientSettingsLibraries
|
||||
updates.forEach(u => all[u.libraryId] = Object.assign({}, all[u.libraryId], u.patch))
|
||||
|
||||
const newSettings = {} as Record<string, ClientSettingUserUpdateDto>
|
||||
newSettings[CLIENT_SETTING.WEBUI_LIBRARIES] = {
|
||||
value: JSON.stringify(all),
|
||||
}
|
||||
await service.updateClientSettingUser(newSettings)
|
||||
dispatch('getClientSettingsUser')
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ export default Vue.extend({
|
|||
},
|
||||
async resetParams(route: any, collectionId: string) {
|
||||
// load dynamic filters
|
||||
this.$set(this.filterOptions, 'library', this.$store.getters.getLibraries.map((x: LibraryDto) => ({
|
||||
this.$set(this.filterOptions, 'library', this.$store.state.komgaLibraries.libraries.map((x: LibraryDto) => ({
|
||||
name: x.name,
|
||||
value: x.id,
|
||||
})))
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ export default Vue.extend({
|
|||
},
|
||||
async resetParams(route: any, readListId: string) {
|
||||
// load dynamic filters
|
||||
this.$set(this.filterOptions, 'library', this.$store.getters.getLibraries.map((x: LibraryDto) => ({
|
||||
this.$set(this.filterOptions, 'library', this.$store.state.komgaLibraries.libraries.map((x: LibraryDto) => ({
|
||||
name: x.name,
|
||||
value: x.id,
|
||||
})))
|
||||
|
|
|
|||
|
|
@ -52,67 +52,46 @@
|
|||
|
||||
<v-divider/>
|
||||
|
||||
<v-list nav shaped dense>
|
||||
<v-list-item :to="{name: 'dashboard'}">
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-home</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t('navigation.home') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-slide-x-transition hide-on-leave>
|
||||
<reorder-libraries v-if="showReorder" @dismiss="showReorder = false"/>
|
||||
</v-slide-x-transition>
|
||||
|
||||
<!-- LIBRARIES -->
|
||||
<v-list-item :to="{name:'libraries', params: {libraryId: LIBRARIES_ALL}}">
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-book-multiple</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t('navigation.libraries') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action v-if="isAdmin" class="ma-0">
|
||||
<v-btn icon @click.stop.capture.prevent="addLibrary">
|
||||
<v-icon>mdi-plus</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
<v-list-item-action v-if="isAdmin" class="ma-0">
|
||||
<libraries-actions-menu/>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
<template v-if="!showReorder">
|
||||
<v-list nav shaped dense>
|
||||
<v-list-item :to="{name: 'dashboard'}">
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-home</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t('navigation.home') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<!-- PINNED LIBRARIES -->
|
||||
<v-list-item v-for="(l, index) in librariesPinned"
|
||||
:key="index"
|
||||
:to="{name:'libraries', params: {libraryId: l.id}}"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ l.name }}</v-list-item-title>
|
||||
<v-list-item-subtitle
|
||||
v-if="l.unavailable"
|
||||
class="error--text caption"
|
||||
>{{ $t('common.unavailable') }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action class="ma-0">
|
||||
<library-actions-menu :library="l"/>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
<!-- LIBRARIES -->
|
||||
<v-list-item :to="{name:'libraries', params: {libraryId: LIBRARIES_ALL}}">
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-book-multiple</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t('navigation.libraries') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action v-if="isAdmin" class="ma-0">
|
||||
<v-btn icon @click.stop.capture.prevent="addLibrary">
|
||||
<v-icon>mdi-plus</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
<v-list-item-action class="ma-0">
|
||||
<libraries-actions-menu @reorder="showReorder = true"/>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
|
||||
<!-- UNPINNED LIBRARIES -->
|
||||
<v-list-group no-action
|
||||
sub-group
|
||||
v-if="librariesUnpinned.length > 0"
|
||||
>
|
||||
<template v-slot:activator>
|
||||
<v-list-item-title>{{ $t('common.more') }}</v-list-item-title>
|
||||
</template>
|
||||
|
||||
<v-list-item v-for="(l, index) in librariesUnpinned"
|
||||
<!-- PINNED LIBRARIES -->
|
||||
<v-list-item v-for="(l, index) in librariesPinned"
|
||||
:key="index"
|
||||
:to="{name:'libraries', params: {libraryId: l.id}}"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ l.name }}</v-list-item-title>
|
||||
<v-list-item-subtitle
|
||||
|
|
@ -125,218 +104,246 @@
|
|||
<library-actions-menu :library="l"/>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
|
||||
<!-- IMPORT -->
|
||||
<v-list-group v-if="isAdmin"
|
||||
prepend-icon="mdi-import"
|
||||
no-action
|
||||
v-model="expandImport"
|
||||
>
|
||||
<template v-slot:activator>
|
||||
<v-list-item-title>{{ $t('book_import.title') }}</v-list-item-title>
|
||||
</template>
|
||||
|
||||
<v-list-item :to="{name: 'import-books'}">
|
||||
<v-list-item-title>{{ $t('common.books') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'import-readlist'}">
|
||||
<v-list-item-title>{{ $t('common.readlist') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
|
||||
<!-- MEDIA MANAGEMENT -->
|
||||
<v-list-group v-if="isAdmin"
|
||||
no-action
|
||||
v-model="expandMediaManagement"
|
||||
>
|
||||
<template v-slot:prependIcon>
|
||||
<v-badge
|
||||
dot
|
||||
inline
|
||||
:value="$store.state.booksToCheck"
|
||||
color="accent"
|
||||
>
|
||||
<v-icon>mdi-book-cog</v-icon>
|
||||
</v-badge>
|
||||
</template>
|
||||
<template v-slot:activator>
|
||||
<v-list-item-title>{{ $t('common.media') }}</v-list-item-title>
|
||||
</template>
|
||||
|
||||
<v-list-item :to="{name: 'media-analysis'}">
|
||||
<v-badge
|
||||
dot
|
||||
inline
|
||||
:value="$store.state.booksToCheck"
|
||||
color="accent"
|
||||
>
|
||||
<v-list-item-title>{{ $t('media_analysis.media_analysis') }}</v-list-item-title>
|
||||
</v-badge>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'missing-posters'}">
|
||||
<v-list-item-title>{{ $t('missing_posters.title') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'duplicate-files'}">
|
||||
<v-list-item-title>{{ $t('duplicates.title') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<!-- UNPINNED LIBRARIES -->
|
||||
<v-list-group no-action
|
||||
sub-group
|
||||
v-model="expandDuplicatePages"
|
||||
v-if="librariesUnpinned.length > 0"
|
||||
v-model="expandUnpinned"
|
||||
>
|
||||
<template v-slot:activator>
|
||||
<v-list-item-title>{{ $t('duplicate_pages.title') }}</v-list-item-title>
|
||||
<v-list-item-title>{{ $t('common.more') }}</v-list-item-title>
|
||||
</template>
|
||||
|
||||
<v-list-item :to="{name: 'settings-duplicate-pages-known'}">
|
||||
<v-list-item-title>{{ $t('duplicate_pages.known') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'settings-duplicate-pages-unknown'}">
|
||||
<v-list-item-title>{{ $t('duplicate_pages.new') }}</v-list-item-title>
|
||||
<v-list-item v-for="(l, index) in librariesUnpinned"
|
||||
:key="index"
|
||||
:to="{name:'libraries', params: {libraryId: l.id}}"
|
||||
>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ l.name }}</v-list-item-title>
|
||||
<v-list-item-subtitle
|
||||
v-if="l.unavailable"
|
||||
class="error--text caption"
|
||||
>{{ $t('common.unavailable') }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action class="ma-0">
|
||||
<library-actions-menu :library="l"/>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
</v-list-group>
|
||||
|
||||
<v-list-item :to="{name: 'history'}" v-if="isAdmin">
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-clock-time-four-outline</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t('history.title') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<!-- SETTINGS -->
|
||||
<v-list-group v-if="isAdmin"
|
||||
no-action
|
||||
v-model="expandSettings"
|
||||
>
|
||||
<template v-slot:prependIcon>
|
||||
<v-badge
|
||||
dot
|
||||
inline
|
||||
:value="$store.getters.getUnreadAnnouncementsCount()"
|
||||
color="info"
|
||||
>
|
||||
<v-icon>mdi-cog</v-icon>
|
||||
</v-badge>
|
||||
</template>
|
||||
<template v-slot:activator>
|
||||
<v-list-item-title>{{ $t('server.tab_title') }}</v-list-item-title>
|
||||
</template>
|
||||
|
||||
<v-list-item :to="{name: 'settings-users'}">
|
||||
<v-list-item-title>{{ $t('users.users') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'settings-server'}">
|
||||
<v-list-item-title>{{ $t('common.settings') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'settings-ui'}">
|
||||
<v-list-item-title>{{ $t('common.ui') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'metrics'}">
|
||||
<v-list-item-title>{{ $t('metrics.title') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'announcements'}">
|
||||
<v-badge
|
||||
dot
|
||||
inline
|
||||
:value="$store.getters.getUnreadAnnouncementsCount()"
|
||||
color="info"
|
||||
>
|
||||
<v-list-item-title>{{ $t('announcements.tab_title') }}</v-list-item-title>
|
||||
</v-badge>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'updates'}">
|
||||
<v-badge
|
||||
dot
|
||||
inline
|
||||
:value="$store.getters.isLatestVersion() == 0"
|
||||
color="warning"
|
||||
>
|
||||
<v-list-item-title>{{ $t('server.updates') }}</v-list-item-title>
|
||||
</v-badge>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
|
||||
<!-- ACCOUNT -->
|
||||
<v-list-group prepend-icon="mdi-account"
|
||||
no-action
|
||||
v-model="expandAccount"
|
||||
>
|
||||
<template v-slot:activator>
|
||||
<v-list-item-title>{{ $t('account_settings.my_account') }}</v-list-item-title>
|
||||
</template>
|
||||
|
||||
<v-list-item :to="{name: 'account-me'}">
|
||||
<v-list-item-title>{{ $t('account_settings.details') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'account-api-keys'}">
|
||||
<v-list-item-title>{{ $t('users.api_keys') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'account-settings-ui'}">
|
||||
<v-list-item-title>{{ $t('common.ui') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'account-activity'}">
|
||||
<v-list-item-title>{{ $t('users.authentication_activity') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
|
||||
<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>{{ $t('navigation.logout') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
<v-divider/>
|
||||
|
||||
<v-list dense class="mt-2">
|
||||
<v-list-item>
|
||||
<v-list-item-icon>
|
||||
<v-icon>{{ themeIcon }}</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-select
|
||||
class="py-2"
|
||||
dense
|
||||
v-model="theme"
|
||||
:items="themes"
|
||||
:label="$t('home.theme')"
|
||||
></v-select>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-translate</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-select
|
||||
dense
|
||||
class="py-2"
|
||||
v-model="locale"
|
||||
:items="locales"
|
||||
:label="$t('home.translation')"
|
||||
<!-- IMPORT -->
|
||||
<v-list-group v-if="isAdmin"
|
||||
prepend-icon="mdi-import"
|
||||
no-action
|
||||
v-model="expandImport"
|
||||
>
|
||||
</v-select>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
<template v-slot:activator>
|
||||
<v-list-item-title>{{ $t('book_import.title') }}</v-list-item-title>
|
||||
</template>
|
||||
|
||||
<v-spacer/>
|
||||
<v-list-item :to="{name: 'import-books'}">
|
||||
<v-list-item-title>{{ $t('common.books') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'import-readlist'}">
|
||||
<v-list-item-title>{{ $t('common.readlist') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
|
||||
<!-- MEDIA MANAGEMENT -->
|
||||
<v-list-group v-if="isAdmin"
|
||||
no-action
|
||||
v-model="expandMediaManagement"
|
||||
>
|
||||
<template v-slot:prependIcon>
|
||||
<v-badge
|
||||
dot
|
||||
inline
|
||||
:value="$store.state.booksToCheck"
|
||||
color="accent"
|
||||
>
|
||||
<v-icon>mdi-book-cog</v-icon>
|
||||
</v-badge>
|
||||
</template>
|
||||
<template v-slot:activator>
|
||||
<v-list-item-title>{{ $t('common.media') }}</v-list-item-title>
|
||||
</template>
|
||||
|
||||
<v-list-item :to="{name: 'media-analysis'}">
|
||||
<v-badge
|
||||
dot
|
||||
inline
|
||||
:value="$store.state.booksToCheck"
|
||||
color="accent"
|
||||
>
|
||||
<v-list-item-title>{{ $t('media_analysis.media_analysis') }}</v-list-item-title>
|
||||
</v-badge>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'missing-posters'}">
|
||||
<v-list-item-title>{{ $t('missing_posters.title') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'duplicate-files'}">
|
||||
<v-list-item-title>{{ $t('duplicates.title') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-group no-action
|
||||
sub-group
|
||||
v-model="expandDuplicatePages"
|
||||
>
|
||||
<template v-slot:activator>
|
||||
<v-list-item-title>{{ $t('duplicate_pages.title') }}</v-list-item-title>
|
||||
</template>
|
||||
|
||||
<v-list-item :to="{name: 'settings-duplicate-pages-known'}">
|
||||
<v-list-item-title>{{ $t('duplicate_pages.known') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'settings-duplicate-pages-unknown'}">
|
||||
<v-list-item-title>{{ $t('duplicate_pages.new') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
</v-list-group>
|
||||
|
||||
<v-list-item :to="{name: 'history'}" v-if="isAdmin">
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-clock-time-four-outline</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t('history.title') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<!-- SETTINGS -->
|
||||
<v-list-group v-if="isAdmin"
|
||||
no-action
|
||||
v-model="expandSettings"
|
||||
>
|
||||
<template v-slot:prependIcon>
|
||||
<v-badge
|
||||
dot
|
||||
inline
|
||||
:value="$store.getters.getUnreadAnnouncementsCount()"
|
||||
color="info"
|
||||
>
|
||||
<v-icon>mdi-cog</v-icon>
|
||||
</v-badge>
|
||||
</template>
|
||||
<template v-slot:activator>
|
||||
<v-list-item-title>{{ $t('server.tab_title') }}</v-list-item-title>
|
||||
</template>
|
||||
|
||||
<v-list-item :to="{name: 'settings-users'}">
|
||||
<v-list-item-title>{{ $t('users.users') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'settings-server'}">
|
||||
<v-list-item-title>{{ $t('common.settings') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'settings-ui'}">
|
||||
<v-list-item-title>{{ $t('common.ui') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'metrics'}">
|
||||
<v-list-item-title>{{ $t('metrics.title') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'announcements'}">
|
||||
<v-badge
|
||||
dot
|
||||
inline
|
||||
:value="$store.getters.getUnreadAnnouncementsCount()"
|
||||
color="info"
|
||||
>
|
||||
<v-list-item-title>{{ $t('announcements.tab_title') }}</v-list-item-title>
|
||||
</v-badge>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'updates'}">
|
||||
<v-badge
|
||||
dot
|
||||
inline
|
||||
:value="$store.getters.isLatestVersion() == 0"
|
||||
color="warning"
|
||||
>
|
||||
<v-list-item-title>{{ $t('server.updates') }}</v-list-item-title>
|
||||
</v-badge>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
|
||||
<!-- ACCOUNT -->
|
||||
<v-list-group prepend-icon="mdi-account"
|
||||
no-action
|
||||
v-model="expandAccount"
|
||||
>
|
||||
<template v-slot:activator>
|
||||
<v-list-item-title>{{ $t('account_settings.my_account') }}</v-list-item-title>
|
||||
</template>
|
||||
|
||||
<v-list-item :to="{name: 'account-me'}">
|
||||
<v-list-item-title>{{ $t('account_settings.details') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'account-api-keys'}">
|
||||
<v-list-item-title>{{ $t('users.api_keys') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'account-settings-ui'}">
|
||||
<v-list-item-title>{{ $t('common.ui') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name: 'account-activity'}">
|
||||
<v-list-item-title>{{ $t('users.authentication_activity') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
|
||||
<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>{{ $t('navigation.logout') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
<v-divider/>
|
||||
|
||||
<v-list dense class="mt-2">
|
||||
<v-list-item>
|
||||
<v-list-item-icon>
|
||||
<v-icon>{{ themeIcon }}</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-select
|
||||
class="py-2"
|
||||
dense
|
||||
v-model="theme"
|
||||
:items="themes"
|
||||
:label="$t('home.theme')"
|
||||
></v-select>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-translate</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-select
|
||||
dense
|
||||
class="py-2"
|
||||
v-model="locale"
|
||||
:items="locales"
|
||||
:label="$t('home.translation')"
|
||||
>
|
||||
</v-select>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
<v-spacer/>
|
||||
</template>
|
||||
|
||||
<template v-slot:append>
|
||||
<div v-if="isAdmin && !$_.isEmpty($store.state.actuatorInfo)"
|
||||
|
|
@ -375,10 +382,12 @@ import {MediaStatus} from '@/types/enum-books'
|
|||
import {LibraryDto} from '@/types/komga-libraries'
|
||||
import {BookSearch, SearchConditionAnyOfBook, SearchConditionMediaStatus, SearchOperatorIs} from '@/types/komga-search'
|
||||
import LibrariesActionsMenu from '@/components/menus/LibrariesActionsMenu.vue'
|
||||
import ReorderLibraries from '@/components/ReorderLibraries.vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'HomeView',
|
||||
components: {
|
||||
ReorderLibraries,
|
||||
LibrariesActionsMenu,
|
||||
ToasterNotification,
|
||||
LibraryActionsMenu,
|
||||
|
|
@ -395,6 +404,8 @@ export default Vue.extend({
|
|||
expandMediaManagement: false,
|
||||
expandImport: false,
|
||||
expandAccount: false,
|
||||
expandUnpinned: false,
|
||||
showReorder: false,
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
|
|
@ -486,6 +497,8 @@ export default Vue.extend({
|
|||
this.expandImport = to.path.includes('/import/')
|
||||
this.expandDuplicatePages = to.path.includes('/duplicate-pages/')
|
||||
this.expandAccount = to.path.includes('/account/')
|
||||
if (this.librariesUnpinned.some(it => it.id === to.params.libraryId)) this.expandUnpinned = true
|
||||
else if (this.librariesPinned.some(it => it.id === to.params.libraryId)) this.expandUnpinned = false
|
||||
},
|
||||
toggleDrawer() {
|
||||
this.drawerVisible = !this.drawerVisible
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ export default Vue.extend({
|
|||
},
|
||||
computed: {
|
||||
filterLibrariesOptions(): object[] {
|
||||
return this.$store.getters.getLibraries.map(x => ({
|
||||
return this.$store.state.komgaLibraries.libraries.map(x => ({
|
||||
text: x.name,
|
||||
value: x.id,
|
||||
}))
|
||||
|
|
|
|||
Loading…
Reference in a new issue