audiobookshelf/server/models/Review.js
fannta1990 41e8906312 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.
2026-02-09 21:08:18 +08:00

107 lines
No EOL
2.3 KiB
JavaScript

const { DataTypes, Model } = require('sequelize')
/**
* @typedef ReviewJSON
* @property {string} id
* @property {number} rating
* @property {string} reviewText
* @property {string} userId
* @property {string} libraryItemId
* @property {number} updatedAt
* @property {number} createdAt
* @property {Object} [user]
* @property {string} user.id
* @property {string} user.username
*/
class Review extends Model {
constructor(values, options) {
super(values, options)
/** @type {string} */
this.id
/** @type {number} */
this.rating
/** @type {string} */
this.reviewText
/** @type {string} */
this.userId
/** @type {string} */
this.libraryItemId
/** @type {Date} */
this.updatedAt
/** @type {Date} */
this.createdAt
}
/**
* Initialize the Review model and associations.
* A user can have only one review per library item.
*
* @param {import('sequelize').Sequelize} sequelize
*/
static init(sequelize) {
super.init(
{
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
rating: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
min: 1,
max: 5
}
},
reviewText: {
type: DataTypes.TEXT,
allowNull: true
}
},
{
sequelize,
modelName: 'review',
indexes: [
{
unique: true,
fields: ['userId', 'libraryItemId']
}
]
}
)
const { user, libraryItem } = sequelize.models
user.hasMany(Review, { onDelete: 'CASCADE' })
Review.belongsTo(user)
libraryItem.hasMany(Review, { onDelete: 'CASCADE' })
Review.belongsTo(libraryItem)
}
/**
* Convert to the old JSON format for the browser.
*
* @returns {ReviewJSON}
*/
toOldJSON() {
return {
id: this.id,
rating: this.rating,
reviewText: this.reviewText,
userId: this.userId,
libraryItemId: this.libraryItemId,
updatedAt: this.updatedAt.valueOf(),
createdAt: this.createdAt.valueOf(),
user: this.user ? {
id: this.user.id,
username: this.user.username
} : undefined
}
}
}
module.exports = Review