diff --git a/client/components/app/BookShelfCategorized.vue b/client/components/app/BookShelfCategorized.vue index 266f7798..8f395298 100644 --- a/client/components/app/BookShelfCategorized.vue +++ b/client/components/app/BookShelfCategorized.vue @@ -217,10 +217,34 @@ export default { this.libraryItemUpdated(li) }) }, + authorUpdated(author) { + this.shelves.forEach((shelf) => { + if (shelf.type == 'authors') { + shelf.entities = shelf.entities.map((ent) => { + if (ent.id === author.id) { + return { + ...ent, + ...author + } + } + return ent + }) + } + }) + }, + authorRemoved(author) { + this.shelves.forEach((shelf) => { + if (shelf.type == 'authors') { + shelf.entities = shelf.entities.filter((ent) => ent.id != author.id) + } + }) + }, initListeners() { this.$store.commit('user/addSettingsListener', { id: 'bookshelf', meth: this.settingsUpdated }) if (this.$root.socket) { + this.$root.socket.on('author_updated', this.authorUpdated) + this.$root.socket.on('author_removed', this.authorRemoved) this.$root.socket.on('item_updated', this.libraryItemUpdated) this.$root.socket.on('item_added', this.libraryItemAdded) this.$root.socket.on('item_removed', this.libraryItemRemoved) @@ -234,6 +258,8 @@ export default { this.$store.commit('user/removeSettingsListener', 'bookshelf') if (this.$root.socket) { + this.$root.socket.off('author_updated', this.authorUpdated) + this.$root.socket.off('author_removed', this.authorRemoved) this.$root.socket.off('item_updated', this.libraryItemUpdated) this.$root.socket.off('item_added', this.libraryItemAdded) this.$root.socket.off('item_removed', this.libraryItemRemoved) diff --git a/server/controllers/LibraryController.js b/server/controllers/LibraryController.js index ac71fe68..b41404d9 100644 --- a/server/controllers/LibraryController.js +++ b/server/controllers/LibraryController.js @@ -224,24 +224,6 @@ class LibraryController { res.json(payload) } - // GET: api/libraries/:id/series/:series - async getSeriesForLibrary(req, res) { - if (!req.params.series) { - return res.status(403).send('Invalid series') - } - var libraryItems = this.db.libraryItems.filter(li => { - return li.libraryId === req.library.id && li.book.series === req.params.series - }) - if (!libraryItems.length) { - return res.status(404).send('Series not found') - } - var sortedBooks = libraryHelpers.sortSeriesBooks(libraryItems, false) - res.json({ - results: sortedBooks, - total: libraryItems.length - }) - } - // api/libraries/:id/collections async getCollectionsForLibrary(req, res) { var libraryItems = req.libraryItems @@ -282,7 +264,6 @@ class LibraryController { var minified = req.query.minified === '1' var itemsWithUserProgress = libraryHelpers.getItemsWithUserProgress(req.user, libraryItems) - var categories = [ { id: 'continue-listening', @@ -306,6 +287,56 @@ class LibraryController { return cats.entities.length }) + + // New Series section + // TODO: optimize and move to libraryHelpers + if (!isPodcastLibrary) { + var series = this.db.series.map(se => { + var books = libraryItems.filter(li => li.media.metadata.hasSeries(se.id)) + if (!books.length) return null + books = books.map(b => { + var json = b.toJSONMinified() + json.sequence = b.media.metadata.getSeriesSequence(se.id) + return json + }) + books = naturalSort(books).asc(b => b.sequence) + return { + id: se.id, + name: se.name, + type: 'series', + addedAt: se.addedAt, + books + } + }).filter(se => se).sort((a, b) => a.addedAt - b.addedAt).slice(0, 5) + + if (series.length) { + categories.push({ + id: 'recent-series', + label: 'Recent Series', + type: 'series', + entities: series + }) + } + + var authors = this.db.authors.map(author => { + var books = libraryItems.filter(li => li.media.metadata.hasAuthor(author.id)) + if (!books.length) return null + // books = books.map(b => b.toJSONMinified()) + return { + ...author.toJSON(), + numBooks: books.length + } + }).filter(au => au).sort((a, b) => a.addedAt - b.addedAt).slice(0, 10) + if (authors.length) { + categories.push({ + id: 'newest-authors', + label: 'Newest Authors', + type: 'authors', + entities: authors + }) + } + } + res.json(categories) } diff --git a/server/objects/metadata/BookMetadata.js b/server/objects/metadata/BookMetadata.js index ab01a02a..aea32206 100644 --- a/server/objects/metadata/BookMetadata.js +++ b/server/objects/metadata/BookMetadata.js @@ -125,6 +125,11 @@ class BookMetadata { hasNarrator(narratorName) { return this.narrators.includes(narratorName) } + getSeriesSequence(seriesId) { + var series = this.series.find(se => se.id == seriesId) + if (!series) return null + return series.sequence || '' + } update(payload) { var json = this.toJSON() diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index fb48ac3e..20dc193e 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -59,7 +59,6 @@ class ApiRouter { this.router.get('/libraries/:id/items', LibraryController.middleware.bind(this), LibraryController.getLibraryItems.bind(this)) this.router.get('/libraries/:id/series', LibraryController.middleware.bind(this), LibraryController.getAllSeriesForLibrary.bind(this)) - this.router.get('/libraries/:id/series/:series', LibraryController.middleware.bind(this), LibraryController.getSeriesForLibrary.bind(this)) this.router.get('/libraries/:id/collections', LibraryController.middleware.bind(this), LibraryController.getCollectionsForLibrary.bind(this)) this.router.get('/libraries/:id/personalized', LibraryController.middleware.bind(this), LibraryController.getLibraryUserPersonalized.bind(this)) this.router.get('/libraries/:id/filterdata', LibraryController.middleware.bind(this), LibraryController.getLibraryFilterData.bind(this)) diff --git a/server/utils/libraryHelpers.js b/server/utils/libraryHelpers.js index 42ca72e1..e8990140 100644 --- a/server/utils/libraryHelpers.js +++ b/server/utils/libraryHelpers.js @@ -98,22 +98,21 @@ module.exports = { getSeriesFromBooks(books, minified = false) { var _series = {} books.forEach((libraryItem) => { - if (libraryItem.media.metadata.series && libraryItem.media.metadata.series.length) { - libraryItem.media.metadata.series.forEach((series) => { - var abJson = minified ? libraryItem.toJSONMinified() : libraryItem.toJSONExpanded() - abJson.sequence = series.sequence - if (!_series[series.id]) { - _series[series.id] = { - id: series.id, - name: series.name, - type: 'series', - books: [abJson] - } - } else { - _series[series.id].books.push(abJson) + var bookSeries = libraryItem.media.metadata.series || [] + bookSeries.forEach((series) => { + var abJson = minified ? libraryItem.toJSONMinified() : libraryItem.toJSONExpanded() + abJson.sequence = series.sequence + if (!_series[series.id]) { + _series[series.id] = { + id: series.id, + name: series.name, + type: 'series', + books: [abJson] } - }) - } + } else { + _series[series.id].books.push(abJson) + } + }) }) return Object.values(_series).map((series) => { series.books = naturalSort(series.books).asc(li => li.sequence)