From ad4dad1c29565fd9d45be6e04e84e6219ed3ab5a Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 28 Oct 2021 14:41:42 -0500 Subject: [PATCH] Add: experimental match tab with google books search #59, Add: isbn field for books #59 --- client/components/cards/BookMatchCard.vue | 6 +- client/components/modals/EditModal.vue | 20 ++- client/components/modals/edit-tabs/Match.vue | 166 ++++++++++++++++--- client/components/ui/Checkbox.vue | 33 ++++ client/components/ui/Dropdown.vue | 9 +- client/components/ui/TextInput.vue | 1 + client/components/ui/TextInputWithLabel.vue | 2 +- client/components/ui/TextareaInput.vue | 7 +- client/components/ui/TextareaWithLabel.vue | 5 +- client/package.json | 2 +- package.json | 2 +- server/ApiController.js | 25 ++- server/BookFinder.js | 17 +- server/Scanner.js | 1 - server/objects/Audiobook.js | 4 + server/objects/Book.js | 5 +- server/providers/GoogleBooks.js | 50 ++++++ server/providers/OpenLibrary.js | 11 +- 18 files changed, 311 insertions(+), 55 deletions(-) create mode 100644 client/components/ui/Checkbox.vue create mode 100644 server/providers/GoogleBooks.js diff --git a/client/components/cards/BookMatchCard.vue b/client/components/cards/BookMatchCard.vue index ea3b0660..eeeae4cd 100644 --- a/client/components/cards/BookMatchCard.vue +++ b/client/components/cards/BookMatchCard.vue @@ -6,11 +6,11 @@

{{ book.title }}

-

{{ book.year || book.first_publish_date }}

+

{{ book.publishYear }}

{{ book.author }}

-

+

{{ book.description }}

@@ -53,7 +53,7 @@ export default { } }, mounted() { - this.selectedCover = this.bookCovers.length ? this.bookCovers[0] : null + this.selectedCover = this.bookCovers.length ? this.bookCovers[0] : this.book.cover || null } } \ No newline at end of file diff --git a/client/components/modals/EditModal.vue b/client/components/modals/EditModal.vue index aaa44f10..9dffa71e 100644 --- a/client/components/modals/EditModal.vue +++ b/client/components/modals/EditModal.vue @@ -20,7 +20,7 @@
- +
@@ -44,11 +44,6 @@ export default { title: 'Cover', component: 'modals-edit-tabs-cover' }, - // { - // id: 'match', - // title: 'Match', - // component: 'modals-edit-tabs-match' - // }, { id: 'tracks', title: 'Tracks', @@ -68,6 +63,11 @@ export default { id: 'download', title: 'Download', component: 'modals-edit-tabs-download' + }, + { + id: 'match', + title: 'Match', + component: 'modals-edit-tabs-match' } ] } @@ -123,12 +123,16 @@ export default { userCanDownload() { return this.$store.getters['user/getUserCanDownload'] }, + showExperimentalFeatures() { + return this.$store.state.showExperimentalFeatures + }, availableTabs() { if (!this.userCanUpdate && !this.userCanDownload) return [] return this.tabs.filter((tab) => { if (tab.id === 'download' && this.isMissing) return false if ((tab.id === 'download' || tab.id === 'tracks') && this.userCanDownload) return true if (tab.id !== 'download' && tab.id !== 'tracks' && this.userCanUpdate) return true + if (tab.id === 'match' && this.showExperimentalFeatures) return true return false }) }, @@ -194,7 +198,9 @@ export default { } }, selectTab(tab) { - this.selectedTab = tab + if (this.availableTabs.find((t) => t.id === tab)) { + this.selectedTab = tab + } }, audiobookUpdated() { if (!this.show) this.fetchOnShow = true diff --git a/client/components/modals/edit-tabs/Match.vue b/client/components/modals/edit-tabs/Match.vue index 74bd806e..d2f5ab13 100644 --- a/client/components/modals/edit-tabs/Match.vue +++ b/client/components/modals/edit-tabs/Match.vue @@ -1,15 +1,17 @@ +
+
+
+ arrow_back +
+

Update Book Details

+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ Update +
+
+
@@ -41,9 +88,30 @@ export default { searchTitle: null, searchAuthor: null, lastSearch: null, - provider: 'best', + providers: [ + { + text: 'Google Books', + value: 'google' + }, + { + text: 'Open Library', + value: 'openlibrary' + } + ], + provider: 'google', searchResults: [], - hasSearched: false + hasSearched: false, + selectedMatch: null, + selectedMatchUsage: { + title: true, + subtitle: true, + cover: true, + author: true, + description: true, + isbn: true, + publisher: true, + publishYear: true + } } }, watch: { @@ -95,6 +163,18 @@ export default { this.hasSearched = true }, init() { + this.selectedMatch = null + this.selectedMatchUsage = { + title: true, + subtitle: true, + cover: true, + author: true, + description: true, + isbn: true, + publisher: true, + publishYear: true + } + if (this.audiobook.id !== this.audiobookId) { this.searchResults = [] this.hasSearched = false @@ -107,31 +187,63 @@ export default { return } this.searchTitle = this.audiobook.book.title - this.searchAuthor = this.audiobook.book.author || '' + this.searchAuthor = this.audiobook.book.authorFL || '' }, - async selectMatch(match) { + selectMatch(match) { + this.selectedMatch = match + }, + buildMatchUpdatePayload() { + var updatePayload = {} + for (const key in this.selectedMatchUsage) { + if (this.selectedMatchUsage[key] && this.selectedMatch[key]) { + updatePayload[key] = this.selectedMatch[key] + } + } + return updatePayload + }, + async submitMatchUpdate() { + var updatePayload = this.buildMatchUpdatePayload() + if (!Object.keys(updatePayload).length) { + return + } this.isProcessing = true - const updatePayload = { - book: {} + + if (updatePayload.cover) { + var coverPayload = { + url: updatePayload.cover + } + var success = await this.$axios.$post(`/api/audiobook/${this.audiobook.id}/cover`, coverPayload).catch((error) => { + console.error('Failed to update', error) + return false + }) + if (success) { + this.$toast.success('Book Cover Updated') + } else { + this.$toast.error('Book Cover Failed to Update') + } + console.log('Updated cover') + delete updatePayload.cover } - if (match.cover) { - updatePayload.book.cover = match.cover + + if (Object.keys(updatePayload).length) { + var bookUpdatePayload = { + book: updatePayload + } + var success = await this.$axios.$patch(`/api/audiobook/${this.audiobook.id}`, bookUpdatePayload).catch((error) => { + console.error('Failed to update', error) + return false + }) + if (success) { + this.$toast.success('Book Details Updated') + this.selectedMatch = null + this.$emit('selectTab', 'details') + } else { + this.$toast.error('Book Details Failed to Update') + } + } else { + this.selectedMatch = null } - if (match.title) { - updatePayload.book.title = match.title - } - if (match.description) { - updatePayload.book.description = match.description - } - var updatedAudiobook = await this.$axios.$patch(`/api/audiobook/${this.audiobook.id}`, updatePayload).catch((error) => { - console.error('Failed to update', error) - return false - }) this.isProcessing = false - if (updatedAudiobook) { - this.$toast.success('Update Successful') - this.$emit('close') - } } } } diff --git a/client/components/ui/Checkbox.vue b/client/components/ui/Checkbox.vue new file mode 100644 index 00000000..8c137120 --- /dev/null +++ b/client/components/ui/Checkbox.vue @@ -0,0 +1,33 @@ + + + \ No newline at end of file diff --git a/client/components/ui/Dropdown.vue b/client/components/ui/Dropdown.vue index 0d6d2f08..ddc80be9 100644 --- a/client/components/ui/Dropdown.vue +++ b/client/components/ui/Dropdown.vue @@ -1,9 +1,9 @@