mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-27 11:41:36 +00:00
merge upstream
This commit is contained in:
commit
61bf30e08a
89 changed files with 2963 additions and 1805 deletions
|
|
@ -39,20 +39,6 @@
|
|||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <form @submit.prevent="submitSearchForm">
|
||||
<div class="flex items-center justify-start -mx-1 py-2 mt-2">
|
||||
<div class="flex-grow px-1">
|
||||
<ui-text-input-with-label v-model="searchTitle" label="Search Title" placeholder="Search" :disabled="processing" />
|
||||
</div>
|
||||
<div class="flex-grow px-1">
|
||||
<ui-text-input-with-label v-model="searchAuthor" label="Author" :disabled="processing" />
|
||||
</div>
|
||||
<div class="w-24 px-1">
|
||||
<ui-btn type="submit" class="mt-5 w-full" :padding-x="0">Search</ui-btn>
|
||||
</div>
|
||||
</div>
|
||||
</form> -->
|
||||
</div>
|
||||
</div>
|
||||
<form @submit.prevent="submitSearchForm">
|
||||
|
|
|
|||
|
|
@ -72,6 +72,10 @@
|
|||
<ui-btn v-if="isRootUser" :loading="savingMetadata" color="bg" type="button" class="h-full" small @click.stop.prevent="saveMetadata">Save Metadata</ui-btn>
|
||||
</ui-tooltip>
|
||||
|
||||
<ui-tooltip :disabled="!!quickMatching" :text="`(Root User Only) Populate empty book details & cover with first book result from '${libraryProvider}'. Does not overwrite details.`" direction="bottom" class="mr-4">
|
||||
<ui-btn v-if="isRootUser" :loading="quickMatching" color="bg" type="button" class="h-full" small @click.stop.prevent="quickMatch">Quick Match</ui-btn>
|
||||
</ui-tooltip>
|
||||
|
||||
<ui-tooltip :disabled="!!libraryScan" text="(Root User Only) Rescan audiobook including metadata" direction="bottom" class="mr-4">
|
||||
<ui-btn v-if="isRootUser" :loading="rescanning" :disabled="!!libraryScan" color="bg" type="button" class="h-full" small @click.stop.prevent="rescan">Re-Scan</ui-btn>
|
||||
</ui-tooltip>
|
||||
|
|
@ -113,7 +117,8 @@ export default {
|
|||
resettingProgress: false,
|
||||
isScrollable: false,
|
||||
savingMetadata: false,
|
||||
rescanning: false
|
||||
rescanning: false,
|
||||
quickMatching: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -163,12 +168,41 @@ export default {
|
|||
libraryId() {
|
||||
return this.audiobook ? this.audiobook.libraryId : null
|
||||
},
|
||||
libraryProvider() {
|
||||
return this.$store.getters['libraries/getLibraryProvider'](this.libraryId) || 'google'
|
||||
},
|
||||
libraryScan() {
|
||||
if (!this.libraryId) return null
|
||||
return this.$store.getters['scanners/getLibraryScan'](this.libraryId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
quickMatch() {
|
||||
this.quickMatching = true
|
||||
var matchOptions = {
|
||||
provider: this.libraryProvider,
|
||||
title: this.details.title,
|
||||
author: this.details.author !== this.book.author ? this.details.author : null
|
||||
}
|
||||
this.$axios
|
||||
.$post(`/api/books/${this.audiobookId}/match`, matchOptions)
|
||||
.then((res) => {
|
||||
this.quickMatching = false
|
||||
if (res.warning) {
|
||||
this.$toast.warning(res.warning)
|
||||
} else if (res.updated) {
|
||||
this.$toast.success('Audiobook details updated')
|
||||
} else {
|
||||
this.$toast.info('No updates were made')
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
var errMsg = error.response ? error.response.data || '' : ''
|
||||
console.error('Failed to match', error)
|
||||
this.$toast.error(errMsg || 'Failed to match')
|
||||
this.quickMatching = false
|
||||
})
|
||||
},
|
||||
audiobookScanComplete(result) {
|
||||
this.rescanning = false
|
||||
if (!result) {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
<template>
|
||||
<div class="w-full h-full px-4 py-2 mb-12">
|
||||
<div class="flex items-center py-1 mb-2">
|
||||
<span v-show="showDirectoryPicker" class="material-icons text-3xl cursor-pointer hover:text-gray-300" @click="backArrowPress">arrow_back</span>
|
||||
<div class="w-full h-full px-4 py-2 mb-4">
|
||||
<div v-show="showDirectoryPicker" class="flex items-center py-1 mb-2">
|
||||
<span class="material-icons text-3xl cursor-pointer hover:text-gray-300" @click="backArrowPress">arrow_back</span>
|
||||
<p class="px-4 text-xl">{{ title }}</p>
|
||||
</div>
|
||||
|
||||
<div v-if="!showDirectoryPicker" class="w-full h-full py-4">
|
||||
<ui-text-input-with-label v-model="name" label="Library Name" />
|
||||
<div class="flex flex-wrap -mx-1">
|
||||
<div class="w-full md:w-2/3 px-1">
|
||||
<ui-text-input-with-label v-model="name" label="Library Name" />
|
||||
</div>
|
||||
<div class="w-full md:w-1/3 px-1">
|
||||
<ui-dropdown v-model="provider" :items="providers" label="Metadata Provider" small />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full py-4">
|
||||
<p class="px-1 text-sm font-semibold">Folders</p>
|
||||
|
|
@ -26,7 +33,17 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<modals-libraries-folder-chooser v-else :paths="folderPaths" @select="selectFolder" />
|
||||
|
||||
<div v-if="!showDirectoryPicker">
|
||||
<div class="flex items-center pt-2">
|
||||
<ui-toggle-switch v-if="!globalWatcherDisabled" v-model="disableWatcher" />
|
||||
<ui-toggle-switch v-else disabled :value="false" />
|
||||
<p class="pl-4 text-lg">Disable folder watcher for library</p>
|
||||
</div>
|
||||
<p v-if="globalWatcherDisabled" class="text-xs text-warning">*Watcher is disabled globally in server settings</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -42,8 +59,10 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
name: '',
|
||||
provider: '',
|
||||
folders: [],
|
||||
showDirectoryPicker: false
|
||||
showDirectoryPicker: false,
|
||||
disableWatcher: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -61,7 +80,13 @@ export default {
|
|||
var newfolderpaths = this.folderPaths.join(',')
|
||||
var origfolderpaths = this.library.folders.map((f) => f.fullPath).join(',')
|
||||
|
||||
return newfolderpaths === origfolderpaths && this.name === this.library.name
|
||||
return newfolderpaths === origfolderpaths && this.name === this.library.name && this.provider === this.library.provider && this.disableWatcher === this.library.disableWatcher
|
||||
},
|
||||
providers() {
|
||||
return this.$store.state.scanners.providers
|
||||
},
|
||||
globalWatcherDisabled() {
|
||||
return this.$store.getters['getServerSetting']('scannerDisableWatcher')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -75,7 +100,9 @@ export default {
|
|||
},
|
||||
init() {
|
||||
this.name = this.library ? this.library.name : ''
|
||||
this.provider = this.library ? this.library.provider : ''
|
||||
this.folders = this.library ? this.library.folders.map((p) => ({ ...p })) : []
|
||||
this.disableWatcher = this.library ? !!this.library.disableWatcher : false
|
||||
this.showDirectoryPicker = false
|
||||
},
|
||||
selectFolder(fullPath) {
|
||||
|
|
@ -100,7 +127,9 @@ export default {
|
|||
}
|
||||
var newLibraryPayload = {
|
||||
name: this.name,
|
||||
folders: this.folders
|
||||
provider: this.provider,
|
||||
folders: this.folders,
|
||||
disableWatcher: this.disableWatcher
|
||||
}
|
||||
|
||||
this.$emit('update:processing', true)
|
||||
|
|
@ -132,7 +161,9 @@ export default {
|
|||
}
|
||||
var newLibraryPayload = {
|
||||
name: this.name,
|
||||
folders: this.folders
|
||||
provider: this.provider,
|
||||
folders: this.folders,
|
||||
disableWatcher: this.disableWatcher
|
||||
}
|
||||
|
||||
this.$emit('update:processing', true)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,11 @@
|
|||
</svg>
|
||||
<p class="text-xl font-book pl-4 hover:underline cursor-pointer" @click.stop="$emit('click', library)">{{ library.name }}</p>
|
||||
<div class="flex-grow" />
|
||||
<ui-btn v-show="isHovering && !libraryScan && canScan" small color="bg" @click.stop="scan">Scan</ui-btn>
|
||||
<ui-btn v-show="isHovering && !libraryScan && canScan" small color="success" @click.stop="scan">Scan</ui-btn>
|
||||
<ui-btn v-show="isHovering && !libraryScan && canScan" small color="bg" class="ml-2" @click.stop="forceScan">Force Re-Scan</ui-btn>
|
||||
|
||||
<ui-btn v-show="isHovering && !libraryScan && canScan" small color="bg" class="ml-2" @click.stop="matchAll">Match Books</ui-btn>
|
||||
|
||||
<span v-show="isHovering && !libraryScan && showEdit && canEdit" class="material-icons text-xl text-gray-300 hover:text-gray-50 ml-4 cursor-pointer" @click.stop="editClick">edit</span>
|
||||
<span v-show="!libraryScan && isHovering && showEdit && canDelete && !isDeleting" class="material-icons text-xl text-gray-300 ml-3" :class="isMain ? 'text-opacity-5 cursor-not-allowed' : 'hover:text-gray-50 cursor-pointer'" @click.stop="deleteClick">delete</span>
|
||||
<div v-show="isDeleting" class="text-xl text-gray-300 ml-3 animate-spin">
|
||||
|
|
@ -59,6 +62,18 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
matchAll() {
|
||||
this.$axios
|
||||
.$post(`/api/libraries/${this.library.id}/matchbooks`)
|
||||
.then(() => {
|
||||
console.log('Starting scan for matches')
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed', error)
|
||||
var errorMsg = err.response ? err.response.data : ''
|
||||
this.$toast.error(errorMsg || 'Match all failed')
|
||||
})
|
||||
},
|
||||
editClick() {
|
||||
this.$emit('edit', this.library)
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue