mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Adds fetching book data on upload
This commit is contained in:
		
							parent
							
								
									aa933df525
								
							
						
					
					
						commit
						3cc900ffbf
					
				| @ -8,6 +8,12 @@ | ||||
|       <span class="text-base text-white text-opacity-80 font-mono material-icons">close</span> | ||||
|     </div> | ||||
| 
 | ||||
|     <div v-if="!isPodcast" | ||||
|       class="w-8 h-8 bg-bg border border-white border-opacity-10 flex items-center justify-center rounded-full hover:bg-primary cursor-pointer" | ||||
|       @click="fetchMetadata"> | ||||
|       <span class="text-base text-white text-opacity-80 font-mono material-icons">refresh</span> | ||||
|     </div> | ||||
| 
 | ||||
|     <template v-if="!uploadSuccess && !uploadFailed"> | ||||
|       <widgets-alert v-if="error" type="error"> | ||||
|         <p class="text-base">{{ error }}</p> | ||||
| @ -48,8 +54,8 @@ | ||||
|       <p class="text-base">{{ $strings.MessageUploaderItemFailed }}</p> | ||||
|     </widgets-alert> | ||||
| 
 | ||||
|     <div v-if="isUploading" class="absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 flex items-center justify-center z-20"> | ||||
|       <ui-loading-indicator :text="$strings.MessageUploading" /> | ||||
|     <div v-if="isNonInteractable" class="absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 flex items-center justify-center z-20"> | ||||
|       <ui-loading-indicator :text="nonInteractionLabel" /> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| @ -61,10 +67,11 @@ export default { | ||||
|   props: { | ||||
|     item: { | ||||
|       type: Object, | ||||
|       default: () => {} | ||||
|       default: () => { } | ||||
|     }, | ||||
|     mediaType: String, | ||||
|     processing: Boolean | ||||
|     processing: Boolean, | ||||
|     provider: String | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
| @ -76,7 +83,8 @@ export default { | ||||
|       error: '', | ||||
|       isUploading: false, | ||||
|       uploadFailed: false, | ||||
|       uploadSuccess: false | ||||
|       uploadSuccess: false, | ||||
|       isFetchingMetadata: false | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
| @ -94,6 +102,16 @@ export default { | ||||
|       } else { | ||||
|         return this.itemData.title | ||||
|       } | ||||
|     }, | ||||
|     isNonInteractable() { | ||||
|       return this.isUploading || this.isFetchingMetadata | ||||
|     }, | ||||
|     nonInteractionLabel() { | ||||
|       if (this.isUploading) { | ||||
|         return this.$strings.MessageUploading | ||||
|       } else if (this.isFetchingMetadata) { | ||||
|         return this.$strings.LabelFetchingMetadata | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
| @ -105,6 +123,30 @@ export default { | ||||
|     titleUpdated() { | ||||
|       this.error = '' | ||||
|     }, | ||||
|     async fetchMetadata() { | ||||
|       if (!this.itemData.title.trim().length) { | ||||
|         return | ||||
|       } | ||||
| 
 | ||||
|       this.isFetchingMetadata = true | ||||
| 
 | ||||
|       try { | ||||
|         const searchQueryString = `title=${this.itemData.title}&author=${this.itemData.author}&provider=${this.provider}` | ||||
|         const [bestCandidate, ..._rest] = await this.$axios.$get(`/api/search/books?${searchQueryString}`) | ||||
| 
 | ||||
|         this.itemData = { | ||||
|           ...this.itemData, | ||||
|           title: bestCandidate?.title, | ||||
|           author: bestCandidate?.author, | ||||
|           series: (bestCandidate?.series || [])[0]?.series | ||||
|         } | ||||
|       } catch (e) { | ||||
|         console.error('Failed', e) | ||||
|         // TODO: do something with the error? | ||||
|       } finally { | ||||
|         this.isFetchingMetadata = false | ||||
|       } | ||||
|     }, | ||||
|     getData() { | ||||
|       if (!this.itemData.title) { | ||||
|         this.error = 'Must have a title' | ||||
|  | ||||
| @ -14,6 +14,14 @@ | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <div v-if="!selectedLibraryIsPodcast" class="flex items-center py-2"> | ||||
|         <ui-toggle-switch v-model="fetchMetadata.enabled" /> | ||||
|         <p class="pl-4 text-base">{{ $strings.LabelAutoFetchMetadata }}</p> | ||||
|         <div class="flex-grow ml-4"> | ||||
|           <ui-dropdown v-model="fetchMetadata.provider" :items="providers" :label="$strings.LabelProvider" :disabled="!fetchMetadata.enabled" /> | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <widgets-alert v-if="error" type="error"> | ||||
|         <p class="text-lg">{{ error }}</p> | ||||
|       </widgets-alert> | ||||
| @ -61,9 +69,16 @@ | ||||
|       </widgets-alert> | ||||
| 
 | ||||
|       <!-- Item Upload cards --> | ||||
|       <template v-for="item in items"> | ||||
|         <cards-item-upload-card :ref="`itemCard-${item.index}`" :key="item.index" :media-type="selectedLibraryMediaType" :item="item" :processing="processing" @remove="removeItem(item)" /> | ||||
|       </template> | ||||
|       <cards-item-upload-card  | ||||
|         v-for="item in items" | ||||
|         :key="item.index" | ||||
|         :ref="`itemCard-${item.index}`" | ||||
|         :media-type="selectedLibraryMediaType" | ||||
|         :item="item" | ||||
|         :provider="fetchMetadata.provider" | ||||
|         :processing="processing" | ||||
|         @remove="removeItem(item)" | ||||
|       /> | ||||
| 
 | ||||
|       <!-- Upload/Reset btns --> | ||||
|       <div v-show="items.length" class="flex justify-end pb-8 pt-4"> | ||||
| @ -92,13 +107,18 @@ export default { | ||||
|       selectedLibraryId: null, | ||||
|       selectedFolderId: null, | ||||
|       processing: false, | ||||
|       uploadFinished: false | ||||
|       uploadFinished: false, | ||||
|       fetchMetadata: { | ||||
|         enabled: false, | ||||
|         provider: 'google' | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     selectedLibrary(newVal) { | ||||
|       if (newVal && !this.selectedFolderId) { | ||||
|         this.setDefaultFolder() | ||||
|         this.setMetadataProvider() | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
| @ -133,6 +153,13 @@ export default { | ||||
|     selectedLibraryIsPodcast() { | ||||
|       return this.selectedLibraryMediaType === 'podcast' | ||||
|     }, | ||||
|     providers() { | ||||
|       if (this.selectedLibraryIsPodcast) return this.$store.state.scanners.podcastProviders | ||||
|       return this.$store.state.scanners.providers | ||||
|     }, | ||||
|     canFetchMetadata() { | ||||
|       return !this.selectedLibraryIsPodcast && this.fetchMetadata.enabled | ||||
|     }, | ||||
|     selectedFolder() { | ||||
|       if (!this.selectedLibrary) return null | ||||
|       return this.selectedLibrary.folders.find((fold) => fold.id === this.selectedFolderId) | ||||
| @ -160,12 +187,16 @@ export default { | ||||
|         } | ||||
|       } | ||||
|       this.setDefaultFolder() | ||||
|       this.setMetadataProvider() | ||||
|     }, | ||||
|     setDefaultFolder() { | ||||
|       if (!this.selectedFolderId && this.selectedLibrary && this.selectedLibrary.folders.length) { | ||||
|         this.selectedFolderId = this.selectedLibrary.folders[0].id | ||||
|       } | ||||
|     }, | ||||
|     setMetadataProvider() { | ||||
|       this.fetchMetadata.provider = this.$store.getters['libraries/getLibraryProvider'](this.selectedLibraryId) | ||||
|     }, | ||||
|     removeItem(item) { | ||||
|       this.items = this.items.filter((b) => b.index !== item.index) | ||||
|       if (!this.items.length) { | ||||
| @ -213,27 +244,49 @@ export default { | ||||
|       var items = e.dataTransfer.items || [] | ||||
| 
 | ||||
|       var itemResults = await this.uploadHelpers.getItemsFromDrop(items, this.selectedLibraryMediaType) | ||||
|       this.setResults(itemResults) | ||||
|       this.onItemsSelected(itemResults) | ||||
|     }, | ||||
|     inputChanged(e) { | ||||
|       if (!e.target || !e.target.files) return | ||||
|       var _files = Array.from(e.target.files) | ||||
|       if (_files && _files.length) { | ||||
|         var itemResults = this.uploadHelpers.getItemsFromPicker(_files, this.selectedLibraryMediaType) | ||||
|         this.setResults(itemResults) | ||||
|         this.onItemsSelected(itemResults) | ||||
|       } | ||||
|     }, | ||||
|     setResults(itemResults) { | ||||
|     onItemsSelected(itemResults) { | ||||
|       if (this.itemSelectionSuccessful(itemResults)) { | ||||
|         // setTimeout ensures the new item ref is attached before this method is called | ||||
|         setTimeout(this.attemptMetadataFetch, 0) | ||||
|       } | ||||
|     }, | ||||
|     itemSelectionSuccessful(itemResults) { | ||||
|       console.log('Upload results', itemResults) | ||||
| 
 | ||||
|       if (itemResults.error) { | ||||
|         this.error = itemResults.error | ||||
|         this.items = [] | ||||
|         this.ignoredFiles = [] | ||||
|       } else { | ||||
|         return false | ||||
|       } | ||||
| 
 | ||||
|       this.error = '' | ||||
|       this.items = itemResults.items | ||||
|       this.ignoredFiles = itemResults.ignoredFiles | ||||
|       return true | ||||
|     }, | ||||
|     attemptMetadataFetch() { | ||||
|       if (!this.canFetchMetadata) { | ||||
|         return false | ||||
|       } | ||||
|       console.log('Upload results', itemResults) | ||||
| 
 | ||||
|       this.items.forEach((item) => { | ||||
|         let itemRef = this.$refs[`itemCard-${item.index}`] | ||||
| 
 | ||||
|         if (itemRef?.length) { | ||||
|           itemRef[0].fetchMetadata(this.fetchMetadata.provider) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     updateItemCardStatus(index, status) { | ||||
|       var ref = this.$refs[`itemCard-${index}`] | ||||
| @ -346,6 +399,8 @@ export default { | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.selectedLibraryId = this.$store.state.libraries.currentLibraryId | ||||
|     this.setMetadataProvider() | ||||
| 
 | ||||
|     this.setDefaultFolder() | ||||
|     window.addEventListener('dragenter', this.dragenter) | ||||
|     window.addEventListener('dragleave', this.dragleave) | ||||
|  | ||||
| @ -194,6 +194,7 @@ | ||||
|   "LabelAuthorLastFirst": "Author (Last, First)", | ||||
|   "LabelAuthors": "Authors", | ||||
|   "LabelAutoDownloadEpisodes": "Auto Download Episodes", | ||||
|   "LabelAutoFetchMetadata": "Auto Fetch Metadata", | ||||
|   "LabelBackToUser": "Back to User", | ||||
|   "LabelBackupLocation": "Backup Location", | ||||
|   "LabelBackupsEnableAutomaticBackups": "Enable automatic backups", | ||||
| @ -259,6 +260,7 @@ | ||||
|   "LabelExample": "Example", | ||||
|   "LabelExplicit": "Explicit", | ||||
|   "LabelFeedURL": "Feed URL", | ||||
|   "LabelFetchingMetadata": "Fetching Metadata", | ||||
|   "LabelFile": "File", | ||||
|   "LabelFileBirthtime": "File Birthtime", | ||||
|   "LabelFileModified": "File Modified", | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user