mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-03-01 05:29:41 +00:00
Fixed error for Ratings page and stats page & added controlls to make Rating system and Ratings page optional (admin can turn it on or off for the server)
This commit is contained in:
parent
3a8075a077
commit
e4e2770fbd
10 changed files with 128 additions and 49 deletions
|
|
@ -997,46 +997,45 @@ class LibraryController {
|
|||
stats.numAudioTracks = bookStats.numAudioFiles
|
||||
|
||||
// Get top 10 rated items
|
||||
const topRatedReviews = await Database.reviewModel.findAll({
|
||||
attributes: [
|
||||
'libraryItemId',
|
||||
[Sequelize.fn('AVG', Sequelize.col('rating')), 'avgRating'],
|
||||
[Sequelize.fn('COUNT', Sequelize.col('id')), 'numReviews']
|
||||
],
|
||||
include: [
|
||||
{
|
||||
model: Database.libraryItemModel,
|
||||
attributes: ['id'],
|
||||
where: { libraryId: req.library.id },
|
||||
include: [
|
||||
{
|
||||
model: Database.bookModel,
|
||||
attributes: ['id'],
|
||||
include: [
|
||||
{
|
||||
model: Database.bookMetadataModel,
|
||||
attributes: ['title']
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
try {
|
||||
const topRatedReviews = await Database.reviewModel.findAll({
|
||||
attributes: [
|
||||
'libraryItemId',
|
||||
[Sequelize.fn('AVG', Sequelize.col('review.rating')), 'avgRating'],
|
||||
[Sequelize.fn('COUNT', Sequelize.col('review.id')), 'numReviews']
|
||||
],
|
||||
include: [
|
||||
{
|
||||
model: Database.libraryItemModel,
|
||||
attributes: ['id'],
|
||||
where: { libraryId: req.library.id },
|
||||
include: [
|
||||
{
|
||||
model: Database.bookModel,
|
||||
attributes: ['id', 'title']
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
group: ['libraryItemId', 'libraryItem.id', 'libraryItem.book.id'],
|
||||
order: [
|
||||
[Sequelize.literal('avgRating'), 'DESC'],
|
||||
[Sequelize.literal('numReviews'), 'DESC']
|
||||
],
|
||||
limit: 10
|
||||
})
|
||||
stats.topRatedItems = topRatedReviews.map((r) => {
|
||||
return {
|
||||
id: r.libraryItemId,
|
||||
title: r.libraryItem?.book?.title || 'Unknown',
|
||||
avgRating: parseFloat(r.getDataValue('avgRating')),
|
||||
numReviews: parseInt(r.getDataValue('numReviews'))
|
||||
}
|
||||
],
|
||||
group: ['libraryItemId', 'libraryItem.id', 'libraryItem.book.id', 'libraryItem.book.bookMetadata.id'],
|
||||
order: [
|
||||
[Sequelize.literal('avgRating'), 'DESC'],
|
||||
[Sequelize.literal('numReviews'), 'DESC']
|
||||
],
|
||||
limit: 10
|
||||
})
|
||||
stats.topRatedItems = topRatedReviews.map((r) => {
|
||||
return {
|
||||
id: r.libraryItemId,
|
||||
title: r.libraryItem?.book?.bookMetadata?.title || 'Unknown',
|
||||
avgRating: parseFloat(r.getDataValue('avgRating')),
|
||||
numReviews: parseInt(r.getDataValue('numReviews'))
|
||||
}
|
||||
})
|
||||
})
|
||||
} catch (error) {
|
||||
Logger.error('[LibraryController] Failed to get top rated items for stats', error)
|
||||
stats.topRatedItems = []
|
||||
}
|
||||
} else {
|
||||
const genres = await libraryItemsPodcastFilters.getGenresWithCount(req.library.id)
|
||||
const podcastStats = await libraryItemsPodcastFilters.getPodcastLibraryStats(req.library.id)
|
||||
|
|
|
|||
|
|
@ -116,6 +116,10 @@ class ReviewController {
|
|||
* @param {import('express').Response} res
|
||||
*/
|
||||
async findAllForUser(req, res) {
|
||||
if (!Database.serverSettings.enableReviews) {
|
||||
return res.status(403).send('Review feature is disabled')
|
||||
}
|
||||
|
||||
try {
|
||||
const reviews = await Database.reviewModel.findAll({
|
||||
where: { userId: req.user.id },
|
||||
|
|
@ -124,10 +128,23 @@ class ReviewController {
|
|||
model: Database.libraryItemModel,
|
||||
include: [
|
||||
{
|
||||
model: Database.bookModel
|
||||
model: Database.bookModel,
|
||||
include: [
|
||||
{
|
||||
model: Database.authorModel,
|
||||
through: { attributes: [] }
|
||||
},
|
||||
{
|
||||
model: Database.seriesModel,
|
||||
through: { attributes: ['id', 'sequence'] }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
model: Database.podcastModel
|
||||
model: Database.podcastModel,
|
||||
include: {
|
||||
model: Database.podcastEpisodeModel
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -138,7 +155,22 @@ class ReviewController {
|
|||
res.json(reviews.map((r) => {
|
||||
const json = r.toOldJSON()
|
||||
if (r.libraryItem) {
|
||||
json.libraryItem = r.libraryItem.toOldJSONMinified()
|
||||
// Manually set media if missing (Sequelize hooks don't run on nested includes)
|
||||
if (!r.libraryItem.media) {
|
||||
if (r.libraryItem.mediaType === 'book' && r.libraryItem.book) {
|
||||
r.libraryItem.media = r.libraryItem.book
|
||||
} else if (r.libraryItem.mediaType === 'podcast' && r.libraryItem.podcast) {
|
||||
r.libraryItem.media = r.libraryItem.podcast
|
||||
}
|
||||
}
|
||||
|
||||
if (r.libraryItem.media) {
|
||||
try {
|
||||
json.libraryItem = r.libraryItem.toOldJSONMinified()
|
||||
} catch (err) {
|
||||
Logger.error(`[ReviewController] Failed to minify library item ${r.libraryItem.id}`, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return json
|
||||
}))
|
||||
|
|
@ -156,6 +188,10 @@ class ReviewController {
|
|||
* @param {import('express').NextFunction} next
|
||||
*/
|
||||
async middleware(req, res, next) {
|
||||
if (!Database.serverSettings.enableReviews) {
|
||||
return res.status(403).send('Review feature is disabled')
|
||||
}
|
||||
|
||||
// Basic library item access check
|
||||
req.libraryItem = await Database.libraryItemModel.getExpandedById(req.params.id)
|
||||
if (!req.libraryItem?.media) return res.sendStatus(404)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue