From 7d66f1eec952202e4996ba569235e515e75df28d Mon Sep 17 00:00:00 2001 From: advplyr Date: Sun, 13 Mar 2022 19:34:31 -0500 Subject: [PATCH] New data model edit tracks page, match, quick match, clean out old files --- client/components/app/Appbar.vue | 3 - client/components/app/BookListRow.vue | 6 +- .../components/app/BookShelfCategorized.vue | 2 +- client/components/app/ConfigSideNav.vue | 6 +- client/components/cards/BookMatchCard.vue | 2 +- client/components/cards/LazyBookCard.vue | 16 +- client/components/covers/BookCover.vue | 2 +- client/components/covers/GroupCover.vue | 2 +- client/components/covers/HoverBookCover.vue | 2 +- client/components/modals/EditModal.vue | 4 +- .../modals/UserCollectionsModal.vue | 35 +- .../modals/collections/UserCollectionItem.vue | 5 +- .../components/modals/edit-tabs/Authors.vue | 4 +- client/components/modals/edit-tabs/Cover.vue | 25 +- .../components/modals/edit-tabs/Details.vue | 14 +- client/components/modals/edit-tabs/Match.vue | 14 +- client/components/readers/Reader.vue | 14 +- client/components/tables/AudioFilesTable.vue | 2 +- client/components/tables/TracksTable.vue | 2 +- client/components/tables/UsersTable.vue | 3 - client/components/widgets/ItemDetailsEdit.vue | 13 +- client/layouts/default.vue | 11 +- client/pages/account.vue | 6 +- client/pages/audiobook/_id/edit.vue | 280 ---------- client/pages/audiobook/_id/index.vue | 494 ------------------ client/pages/batch/index.vue | 8 +- client/pages/collection/_id.vue | 6 +- client/pages/config.vue | 6 +- client/pages/config/index.vue | 27 +- client/pages/config/log.vue | 6 +- client/pages/index.vue | 6 +- client/pages/item/_id/edit.vue | 96 +--- client/pages/item/_id/index.vue | 44 +- .../pages/library/_library/authors/index.vue | 6 +- .../pages/library/_library/bookshelf/_id.vue | 6 +- client/pages/library/_library/index.vue | 6 +- .../pages/library/_library/podcast/search.vue | 6 +- client/pages/library/_library/search.vue | 6 +- client/pages/library/_library/series/_id.vue | 6 +- client/pages/upload/index.vue | 6 +- client/players/CastPlayer.js | 2 +- client/plugins/chromecast.js | 4 +- client/store/audiobooks.js | 135 ----- client/store/globals.js | 19 +- client/store/index.js | 1 - client/store/libraries.js | 5 - server/ApiController.js | 21 +- server/Server.js | 2 - server/controllers/BookController.js | 279 ---------- server/controllers/LibraryController.js | 2 +- server/controllers/LibraryItemController.js | 32 ++ server/controllers/MeController.js | 26 +- server/objects/User.js | 6 +- server/objects/entities/Book.js | 22 + server/objects/files/LibraryFile.js | 1 + server/objects/metadata/BookMetadata.js | 4 +- server/providers/Audible.js | 2 +- server/providers/GoogleBooks.js | 2 +- server/providers/OpenLibrary.js | 2 +- server/providers/iTunes.js | 2 +- server/scanner/AudioFileScanner.js | 6 +- server/scanner/Scanner.js | 64 ++- server/utils/abmetadataGenerator.js | 2 +- server/utils/dbMigration.js | 2 +- server/utils/ffmpegHelpers.js | 2 +- server/utils/nfoGenerator.js | 2 +- server/utils/parseOpfMetadata.js | 2 +- server/utils/scandir.js | 26 +- 68 files changed, 354 insertions(+), 1529 deletions(-) delete mode 100644 client/pages/audiobook/_id/edit.vue delete mode 100644 client/pages/audiobook/_id/index.vue delete mode 100644 client/store/audiobooks.js delete mode 100644 server/controllers/BookController.js diff --git a/client/components/app/Appbar.vue b/client/components/app/Appbar.vue index 21d25832..6ad9553d 100644 --- a/client/components/app/Appbar.vue +++ b/client/components/app/Appbar.vue @@ -103,9 +103,6 @@ export default { userAudiobooks() { return this.$store.state.user.user.audiobooks || {} }, - selectedSeries() { - return this.$store.state.audiobooks.selectedSeries - }, userCanUpdate() { return this.$store.getters['user/getUserCanUpdate'] }, diff --git a/client/components/app/BookListRow.vue b/client/components/app/BookListRow.vue index 192582da..03f90470 100644 --- a/client/components/app/BookListRow.vue +++ b/client/components/app/BookListRow.vue @@ -11,7 +11,7 @@ - +

{{ book.book.title }}: {{ book.book.subtitle }}

@@ -24,7 +24,7 @@

{{ seriesText }}

-

{{ book.book.publishYear }}

+

{{ book.book.publishedYear }}

{{ book.book.description }}

@@ -148,7 +148,7 @@ export default { this.$store.commit('showEReader', this.book) }, downloadClick() { - this.$store.commit('showEditModalOnTab', { audiobook: this.book, tab: 'download' }) + this.$store.commit('showEditModalOnTab', { libraryItem: this.book, tab: 'download' }) }, toggleRead() { var updatePayload = { diff --git a/client/components/app/BookShelfCategorized.vue b/client/components/app/BookShelfCategorized.vue index 21b04907..ad5efa29 100644 --- a/client/components/app/BookShelfCategorized.vue +++ b/client/components/app/BookShelfCategorized.vue @@ -11,7 +11,7 @@

Audiobookshelf is empty!

Configure Scanner - Scan Audiobooks + Scan Library
diff --git a/client/components/app/ConfigSideNav.vue b/client/components/app/ConfigSideNav.vue index 7443800d..f2574fc2 100644 --- a/client/components/app/ConfigSideNav.vue +++ b/client/components/app/ConfigSideNav.vue @@ -9,7 +9,7 @@
-
+

v{{ $config.version }}

Update available: {{ latestVersion }}
@@ -109,8 +109,8 @@ export default { githubTagUrl() { return this.versionData.githubTagUrl }, - streamAudiobook() { - return this.$store.state.streamAudiobook + streamLibraryItem() { + return this.$store.state.streamLibraryItem } }, methods: { diff --git a/client/components/cards/BookMatchCard.vue b/client/components/cards/BookMatchCard.vue index ca9c83ca..1d35ab3b 100644 --- a/client/components/cards/BookMatchCard.vue +++ b/client/components/cards/BookMatchCard.vue @@ -6,7 +6,7 @@

{{ book.title }}

-

{{ book.publishYear }}

+

{{ book.publishedYear }}

{{ book.author }}

diff --git a/client/components/cards/LazyBookCard.vue b/client/components/cards/LazyBookCard.vue index b6f6a8a3..0fc37f57 100644 --- a/client/components/cards/LazyBookCard.vue +++ b/client/components/cards/LazyBookCard.vue @@ -149,7 +149,7 @@ export default { return '/book_placeholder.jpg' }, bookCoverSrc() { - return this.store.getters['audiobooks/getLibraryItemCoverSrc'](this._libraryItem, this.placeholderUrl) + return this.store.getters['globals/getLibraryItemCoverSrc'](this._libraryItem, this.placeholderUrl) }, libraryItemId() { return this._libraryItem.id @@ -418,7 +418,7 @@ export default { toast.error(`Failed to mark as ${updatePayload.isRead ? 'Read' : 'Not Read'}`) }) }, - audiobookScanComplete(result) { + itemScanComplete(result) { this.rescanning = false var toast = this.$toast || this.$nuxt.$toast if (!result) { @@ -433,23 +433,23 @@ export default { }, rescan() { this.rescanning = true - this._socket.once('audiobook_scan_complete', this.audiobookScanComplete) - this._socket.emit('scan_libraryItem', this.libraryItemId) + this._socket.once('item_scan_complete', this.itemScanComplete) + this._socket.emit('scan_item', this.libraryItemId) }, showEditModalTracks() { // More menu func - this.store.commit('showEditModalOnTab', { audiobook: this.audiobook, tab: 'tracks' }) + this.store.commit('showEditModalOnTab', { libraryItem: this.audiobook, tab: 'tracks' }) }, showEditModalMatch() { // More menu func - this.store.commit('showEditModalOnTab', { audiobook: this.audiobook, tab: 'match' }) + this.store.commit('showEditModalOnTab', { libraryItem: this.audiobook, tab: 'match' }) }, showEditModalDownload() { // More menu func - this.store.commit('showEditModalOnTab', { audiobook: this.audiobook, tab: 'download' }) + this.store.commit('showEditModalOnTab', { libraryItem: this.audiobook, tab: 'download' }) }, openCollections() { - this.store.commit('setSelectedAudiobook', this.audiobook) + this.store.commit('setSelectedLibraryItem', this.audiobook) this.store.commit('globals/setShowUserCollectionsModal', true) }, createMoreMenu() { diff --git a/client/components/covers/BookCover.vue b/client/components/covers/BookCover.vue index b5efade4..38449b3c 100644 --- a/client/components/covers/BookCover.vue +++ b/client/components/covers/BookCover.vue @@ -99,7 +99,7 @@ export default { fullCoverUrl() { if (!this.libraryItem) return null var store = this.$store || this.$nuxt.$store - return store.getters['audiobooks/getLibraryItemCoverSrc'](this.libraryItem, this.placeholderUrl) + return store.getters['globals/getLibraryItemCoverSrc'](this.libraryItem, this.placeholderUrl) }, cover() { return this.media.coverPath || this.placeholderUrl diff --git a/client/components/covers/GroupCover.vue b/client/components/covers/GroupCover.vue index 88c31501..8af50fd0 100644 --- a/client/components/covers/GroupCover.vue +++ b/client/components/covers/GroupCover.vue @@ -63,7 +63,7 @@ export default { }, methods: { getCoverUrl(book) { - return this.store.getters['audiobooks/getLibraryItemCoverSrc'](book, '') + return this.store.getters['globals/getLibraryItemCoverSrc'](book, '') }, async buildCoverImg(coverData, bgCoverWidth, offsetLeft, zIndex, forceCoverBg = false) { var src = coverData.coverUrl diff --git a/client/components/covers/HoverBookCover.vue b/client/components/covers/HoverBookCover.vue index 1bed83db..7171061e 100644 --- a/client/components/covers/HoverBookCover.vue +++ b/client/components/covers/HoverBookCover.vue @@ -22,7 +22,7 @@ export default { return '/book_placeholder.jpg' }, fullCoverUrl() { - return this.$store.getters['audiobooks/getLibraryItemCoverSrc'](this.audiobook, this.placeholderUrl) + return this.$store.getters['globals/getLibraryItemCoverSrc'](this.audiobook, this.placeholderUrl) }, hasCover() { return !!this.audiobook.book.cover diff --git a/client/components/modals/EditModal.vue b/client/components/modals/EditModal.vue index 61fa48f5..f6b06ce8 100644 --- a/client/components/modals/EditModal.vue +++ b/client/components/modals/EditModal.vue @@ -169,7 +169,7 @@ export default { if (this.currentBookshelfIndex - 1 < 0) return var prevBookId = this.bookshelfBookIds[this.currentBookshelfIndex - 1] this.processing = true - var prevBook = await this.$axios.$get(`/api/books/${prevBookId}`).catch((error) => { + var prevBook = await this.$axios.$get(`/api/items/${prevBookId}`).catch((error) => { var errorMsg = error.response && error.response.data ? error.response.data : 'Failed to fetch book' this.$toast.error(errorMsg) return null @@ -186,7 +186,7 @@ export default { if (this.currentBookshelfIndex >= this.bookshelfBookIds.length - 1) return this.processing = true var nextBookId = this.bookshelfBookIds[this.currentBookshelfIndex + 1] - var nextBook = await this.$axios.$get(`/api/books/${nextBookId}`).catch((error) => { + var nextBook = await this.$axios.$get(`/api/items/${nextBookId}`).catch((error) => { var errorMsg = error.response && error.response.data ? error.response.data : 'Failed to fetch book' this.$toast.error(errorMsg) return null diff --git a/client/components/modals/UserCollectionsModal.vue b/client/components/modals/UserCollectionsModal.vue index 9cbedf98..2160a64d 100644 --- a/client/components/modals/UserCollectionsModal.vue +++ b/client/components/modals/UserCollectionsModal.vue @@ -15,7 +15,7 @@
@@ -50,7 +50,7 @@ export default { this.loadCollections() this.newCollectionName = '' } else { - this.$store.commit('setSelectedAudiobook', null) + this.$store.commit('setSelectedLibraryItem', null) } } }, @@ -65,15 +65,18 @@ export default { }, title() { if (this.showBatchUserCollectionModal) { - return `${this.selectedBookIds.length} Books Selected` + return `${this.selectedBookIds.length} Items Selected` } - return this.selectedAudiobook ? this.selectedAudiobook.book.title : '' + return this.selectedLibraryItem ? this.selectedLibraryItem.media.metadata.title : '' }, - selectedAudiobook() { - return this.$store.state.selectedAudiobook + bookCoverAspectRatio() { + return this.$store.getters['getBookCoverAspectRatio'] }, - selectedAudiobookId() { - return this.selectedAudiobook ? this.selectedAudiobook.id : null + selectedLibraryItem() { + return this.$store.state.selectedLibraryItem + }, + selectedLibraryItemId() { + return this.selectedLibraryItem ? this.selectedLibraryItem.id : null }, collections() { return this.$store.state.user.collections || [] @@ -87,7 +90,7 @@ export default { var collectionBookIds = c.books.map((b) => b.id) includesBook = !this.selectedBookIds.find((id) => !collectionBookIds.includes(id)) } else { - includesBook = !!c.books.find((b) => b.id === this.selectedAudiobookId) + includesBook = !!c.books.find((b) => b.id === this.selectedLibraryItemId) } return { @@ -112,7 +115,7 @@ export default { this.$store.dispatch('user/loadUserCollections') }, removeFromCollection(collection) { - if (!this.selectedAudiobookId && !this.selectedBookIds.length) return + if (!this.selectedLibraryItemId && !this.selectedBookIds.length) return this.processing = true if (this.showBatchUserCollectionModal) { @@ -132,7 +135,7 @@ export default { } else { // Remove single book this.$axios - .$delete(`/api/collections/${collection.id}/book/${this.selectedAudiobookId}`) + .$delete(`/api/collections/${collection.id}/book/${this.selectedLibraryItemId}`) .then((updatedCollection) => { console.log(`Book removed from collection`, updatedCollection) this.$toast.success('Book removed from collection') @@ -146,7 +149,7 @@ export default { } }, addToCollection(collection) { - if (!this.selectedAudiobookId && !this.selectedBookIds.length) return + if (!this.selectedLibraryItemId && !this.selectedBookIds.length) return this.processing = true if (this.showBatchUserCollectionModal) { @@ -164,10 +167,10 @@ export default { this.processing = false }) } else { - if (!this.selectedAudiobookId) return + if (!this.selectedLibraryItemId) return this.$axios - .$post(`/api/collections/${collection.id}/book`, { id: this.selectedAudiobookId }) + .$post(`/api/collections/${collection.id}/book`, { id: this.selectedLibraryItemId }) .then((updatedCollection) => { console.log(`Book added to collection`, updatedCollection) this.$toast.success('Book added to collection') @@ -181,12 +184,12 @@ export default { } }, submitCreateCollection() { - if (!this.newCollectionName || (!this.selectedAudiobookId && !this.selectedBookIds.length)) { + if (!this.newCollectionName || (!this.selectedLibraryItemId && !this.selectedBookIds.length)) { return } this.processing = true - var books = this.showBatchUserCollectionModal ? this.selectedBookIds : [this.selectedAudiobookId] + var books = this.showBatchUserCollectionModal ? this.selectedBookIds : [this.selectedLibraryItemId] var newCollection = { books: books, libraryId: this.currentLibraryId, diff --git a/client/components/modals/collections/UserCollectionItem.vue b/client/components/modals/collections/UserCollectionItem.vue index d7655484..c79efda7 100644 --- a/client/components/modals/collections/UserCollectionItem.vue +++ b/client/components/modals/collections/UserCollectionItem.vue @@ -4,7 +4,7 @@
- +
- + Manage Tracks
diff --git a/client/components/tables/UsersTable.vue b/client/components/tables/UsersTable.vue index f1ed44c2..89b3232e 100644 --- a/client/components/tables/UsersTable.vue +++ b/client/components/tables/UsersTable.vue @@ -76,9 +76,6 @@ export default { currentUserId() { return this.$store.state.user.user.id }, - userStream() { - return this.$store.state.streamAudiobook - }, usersOnline() { var usermap = {} this.$store.state.users.users.forEach((u) => (usermap[u.id] = { online: true, stream: u.stream })) diff --git a/client/components/widgets/ItemDetailsEdit.vue b/client/components/widgets/ItemDetailsEdit.vue index aa529972..959a7012 100644 --- a/client/components/widgets/ItemDetailsEdit.vue +++ b/client/components/widgets/ItemDetailsEdit.vue @@ -17,7 +17,7 @@
- +
@@ -108,7 +108,7 @@ export default { authors: [], narrators: [], series: [], - publishYear: null, + publishedYear: null, publisher: null, language: null, isbn: null, @@ -173,6 +173,13 @@ export default { this.forceBlur() return this.checkForChanges() }, + getTitleAndAuthorName() { + this.forceBlur() + return { + title: this.details.title, + author: (this.details.authors || []).map((au) => au.name).join(', ') + } + }, mapBatchDetails(batchDetails) { for (const key in batchDetails) { if (key === 'tags') { @@ -317,7 +324,7 @@ export default { this.details.narrators = [...(this.mediaMetadata.narrators || [])] this.details.genres = [...(this.mediaMetadata.genres || [])] this.details.series = (this.mediaMetadata.series || []).map((se) => ({ ...se })) - this.details.publishYear = this.mediaMetadata.publishYear + this.details.publishedYear = this.mediaMetadata.publishedYear this.details.publisher = this.mediaMetadata.publisher || null this.details.language = this.mediaMetadata.language || null this.details.isbn = this.mediaMetadata.isbn || null diff --git a/client/layouts/default.vue b/client/layouts/default.vue index 123e5f0e..24355601 100644 --- a/client/layouts/default.vue +++ b/client/layouts/default.vue @@ -35,9 +35,6 @@ export default { if (this.$store.state.selectedLibraryItems) { this.$store.commit('setSelectedLibraryItems', []) } - if (this.$store.state.audiobooks.keywordFilter) { - this.$store.commit('audiobooks/setKeywordFilter', '') - } } }, computed: { @@ -282,12 +279,6 @@ export default { if (!download || !download.audiobookId) { return console.error('Invalid download object', download) } - - // var audiobook = this.$store.getters['audiobooks/getAudiobook'](download.audiobookId) - // if (!audiobook) { - // return console.error('Audiobook not found for download', download) - // } - // this.$store.commit('showEditModalOnTab', { audiobook, tab: 'download' }) }, downloadStarted(download) { download.status = this.$constants.DownloadStatus.PENDING @@ -495,7 +486,7 @@ export default { } // Playing audiobook - if (this.$store.state.streamAudiobook && Object.values(this.$hotkeys.AudioPlayer).includes(name)) { + if (this.$store.state.streamLibraryItem && Object.values(this.$hotkeys.AudioPlayer).includes(name)) { this.$eventBus.$emit('player-hotkey', name) e.preventDefault() } diff --git a/client/pages/account.vue b/client/pages/account.vue index d6640242..4ce7d1bb 100644 --- a/client/pages/account.vue +++ b/client/pages/account.vue @@ -1,5 +1,5 @@