diff --git a/server/controllers/LibraryController.js b/server/controllers/LibraryController.js index f42a023d4c..f22bcfa6c4 100644 --- a/server/controllers/LibraryController.js +++ b/server/controllers/LibraryController.js @@ -39,6 +39,30 @@ const authorFilters = require('../utils/queries/authorFilters') class LibraryController { constructor() {} + /** + * GET: /api/libraries/stats + * Get stats for all libraries and respond with JSON + * @param {import('express').Request} req + * @param {import('express').Response} res + */ + async allStats(req, res) { + try { + const allLibrariesIds = await Database.libraryModel.getAllLibraryIds(); + const allStats = []; + + for (let i = 0; i < allLibrariesIds.length; i++) { + const library = await Database.libraryModel.getOldById(allLibrariesIds[i]); + req.library = library + const libraryStats = await libraryHelpers.getLibraryStats(req); + allStats.push({ library: library, stats: libraryStats }); + } + + res.json(allStats); + } catch (error) { + res.status(500).json({ error: error.message }); + } + } + /** * POST: /api/libraries * Create a new library @@ -940,39 +964,12 @@ class LibraryController { * @param {Response} res */ async stats(req, res) { - const stats = { - largestItems: await libraryItemFilters.getLargestItems(req.library.id, 10) - } - - if (req.library.mediaType === 'book') { - const authors = await authorFilters.getAuthorsWithCount(req.library.id, 10) - const genres = await libraryItemsBookFilters.getGenresWithCount(req.library.id) - const bookStats = await libraryItemsBookFilters.getBookLibraryStats(req.library.id) - const longestBooks = await libraryItemsBookFilters.getLongestBooks(req.library.id, 10) - - stats.totalAuthors = await authorFilters.getAuthorsTotalCount(req.library.id) - stats.authorsWithCount = authors - stats.totalGenres = genres.length - stats.genresWithCount = genres - stats.totalItems = bookStats.totalItems - stats.longestItems = longestBooks - stats.totalSize = bookStats.totalSize - stats.totalDuration = bookStats.totalDuration - stats.numAudioTracks = bookStats.numAudioFiles - } else { - const genres = await libraryItemsPodcastFilters.getGenresWithCount(req.library.id) - const podcastStats = await libraryItemsPodcastFilters.getPodcastLibraryStats(req.library.id) - const longestPodcasts = await libraryItemsPodcastFilters.getLongestPodcasts(req.library.id, 10) - - stats.totalGenres = genres.length - stats.genresWithCount = genres - stats.totalItems = podcastStats.totalItems - stats.longestItems = longestPodcasts - stats.totalSize = podcastStats.totalSize - stats.totalDuration = podcastStats.totalDuration - stats.numAudioTracks = podcastStats.numAudioFiles - } - res.json(stats) + try { + const stats = await libraryHelpers.getLibraryStats(req); + res.json(stats); + } catch (error) { + res.status(500).json({ error: error.message }); + } } /** diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index 235d25cd5f..3436dea1e0 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -68,6 +68,7 @@ class ApiRouter { this.router.get(/^\/libraries/, this.apiCacheManager.middleware) this.router.post('/libraries', LibraryController.create.bind(this)) this.router.get('/libraries', LibraryController.findAll.bind(this)) + this.router.get('/libraries/stats', LibraryController.allStats.bind(this)) this.router.get('/libraries/:id', LibraryController.middleware.bind(this), LibraryController.findOne.bind(this)) this.router.patch('/libraries/:id', LibraryController.middleware.bind(this), LibraryController.update.bind(this)) this.router.delete('/libraries/:id', LibraryController.middleware.bind(this), LibraryController.delete.bind(this)) diff --git a/server/utils/libraryHelpers.js b/server/utils/libraryHelpers.js index 664bd6e301..5777dfa63d 100644 --- a/server/utils/libraryHelpers.js +++ b/server/utils/libraryHelpers.js @@ -1,6 +1,10 @@ const { createNewSortInstance } = require('../libs/fastSort') const Database = require('../Database') const { getTitlePrefixAtEnd, isNullOrNaN, getTitleIgnorePrefix } = require('../utils/index') +const libraryItemsBookFilters = require('../utils/queries/libraryItemsBookFilters') +const authorFilters = require('../utils/queries/authorFilters') +const libraryItemFilters = require('../utils/queries/libraryItemFilters') +const libraryItemsPodcastFilters = require('../utils/queries/libraryItemsPodcastFilters') const naturalSort = createNewSortInstance({ comparer: new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }).compare }) @@ -78,6 +82,48 @@ module.exports = { return filteredLibraryItems }, + /** + * Helper method to get stats for a specific library + * @param {import('express').Request} req + * @returns {Promise} stats + */ + async getLibraryStats(req) { + const stats = { + largestItems: await libraryItemFilters.getLargestItems(req.library.id, 10) + }; + + if (req.library.mediaType === 'book') { + const authors = await authorFilters.getAuthorsWithCount(req.library.id, 10) + const genres = await libraryItemsBookFilters.getGenresWithCount(req.library.id) + const bookStats = await libraryItemsBookFilters.getBookLibraryStats(req.library.id) + const longestBooks = await libraryItemsBookFilters.getLongestBooks(req.library.id, 10) + + stats.totalAuthors = await authorFilters.getAuthorsTotalCount(req.library.id) + stats.authorsWithCount = authors; + stats.totalGenres = genres.length; + stats.genresWithCount = genres; + stats.totalItems = bookStats.totalItems; + stats.longestItems = longestBooks; + stats.totalSize = bookStats.totalSize; + stats.totalDuration = bookStats.totalDuration; + stats.numAudioTracks = bookStats.numAudioFiles; + } else { + const genres = await libraryItemsPodcastFilters.getGenresWithCount(req.library.id) + const podcastStats = await libraryItemsPodcastFilters.getPodcastLibraryStats(req.library.id) + const longestPodcasts = await libraryItemsPodcastFilters.getLongestPodcasts(req.library.id, 10) + + stats.totalGenres = genres.length; + stats.genresWithCount = genres; + stats.totalItems = podcastStats.totalItems; + stats.longestItems = longestPodcasts; + stats.totalSize = podcastStats.totalSize; + stats.totalDuration = podcastStats.totalDuration; + stats.numAudioTracks = podcastStats.numAudioFiles; + } + + return stats; + }, + /** * * @param {*} payload