mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-03-03 22:49:42 +00:00
Add review and rating features with sorting and filtering options
- Implemented a new ReviewController to handle review creation, updates, and retrieval for library items. - Added pagination, sorting, and filtering capabilities for reviews in the API. - Updated frontend components to support review display, including a new ReviewsTable and enhanced ratings UI. - Introduced new strings for user interface elements related to reviews and ratings. - Added tests for the ReviewController and Review model to ensure functionality and validation. - Enabled the option to toggle the review feature in server settings.
This commit is contained in:
parent
e4e2770fbd
commit
41e8906312
12 changed files with 603 additions and 43 deletions
|
|
@ -180,6 +180,110 @@ class ReviewController {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /api/libraries/:id/reviews
|
||||
* Get all reviews for items in a library.
|
||||
* Supports sorting by newest, oldest, highest, lowest.
|
||||
* Supports filtering by user or rating.
|
||||
* Supports pagination with limit and page.
|
||||
*
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async findAllForLibrary(req, res) {
|
||||
if (!Database.serverSettings.enableReviews) {
|
||||
return res.status(403).send('Review feature is disabled')
|
||||
}
|
||||
|
||||
const libraryId = req.params.id
|
||||
const { sort, filter, limit, page } = req.query
|
||||
|
||||
try {
|
||||
const where = {}
|
||||
const include = [
|
||||
{
|
||||
model: Database.userModel,
|
||||
attributes: ['id', 'username']
|
||||
},
|
||||
{
|
||||
model: Database.libraryItemModel,
|
||||
where: { libraryId },
|
||||
required: true,
|
||||
include: [
|
||||
{
|
||||
model: Database.bookModel,
|
||||
include: [
|
||||
{ model: Database.authorModel, through: { attributes: [] } },
|
||||
{ model: Database.seriesModel, through: { attributes: ['id', 'sequence'] } }
|
||||
]
|
||||
},
|
||||
{
|
||||
model: Database.podcastModel,
|
||||
include: { model: Database.podcastEpisodeModel }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
if (filter) {
|
||||
const [filterType, filterValue] = filter.split('.')
|
||||
if (filterType === 'user' && filterValue) {
|
||||
where.userId = filterValue
|
||||
} else if (filterType === 'rating' && filterValue) {
|
||||
where.rating = filterValue
|
||||
}
|
||||
}
|
||||
|
||||
let order = [['createdAt', 'DESC']]
|
||||
if (sort === 'oldest') order = [['createdAt', 'ASC']]
|
||||
else if (sort === 'highest') order = [['rating', 'DESC'], ['createdAt', 'DESC']]
|
||||
else if (sort === 'lowest') order = [['rating', 'ASC'], ['createdAt', 'DESC']]
|
||||
|
||||
const limitNum = limit ? parseInt(limit) : 50
|
||||
const pageNum = page ? parseInt(page) : 0
|
||||
const offset = pageNum * limitNum
|
||||
|
||||
const { count, rows: reviews } = await Database.reviewModel.findAndCountAll({
|
||||
where,
|
||||
include,
|
||||
order,
|
||||
limit: limitNum,
|
||||
offset
|
||||
})
|
||||
|
||||
const results = reviews.map((r) => {
|
||||
const json = r.toOldJSON()
|
||||
if (r.libraryItem) {
|
||||
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
|
||||
})
|
||||
|
||||
res.json({
|
||||
reviews: results,
|
||||
total: count,
|
||||
page: pageNum,
|
||||
limit: limitNum
|
||||
})
|
||||
} catch (error) {
|
||||
Logger.error(`[ReviewController] Failed to fetch reviews for library ${libraryId}`, error)
|
||||
res.status(500).send('Failed to fetch reviews')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Middleware for review routes.
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue