import { format as formatDate } from "date-fns"; import Pages from "./Pages"; import Export from "./Export"; import AlbumsModel from "../models/albums"; import JobsModel from "../models/jobs"; import UsersModel from "../models/users"; import ErrorEvent from "../libs/error"; import { getAlbumDetails } from "../helpers"; /** * Classe permettant la gestion des albums d'un utilisateur */ class Albums extends Pages { /** * Méthode permettant d'ajouter un album dans une collection * @param {Object} req * @return {Object} */ static async postAddOne(req) { const { body, user } = req; const data = { ...body, discogsId: body.id, User: user._id, }; data.released = data.released ? new Date(data.released.replace("-00", "-01")) : null; delete data.id; const album = new AlbumsModel(data); await album.save(); const jobData = { model: "Albums", id: album._id, }; const job = new JobsModel(jobData); job.save(); return album; } /** * Méthode permettant de récupérer les éléments distincts d'une collection * @param {String} field * @param {ObjectId} user * @return {Array} */ static async getAllDistincts(field, user) { const distincts = await AlbumsModel.find( { User: user, }, [], { sort: { [field]: 1, }, } ).distinct(field); return distincts; } /** * Méthode permettant de récupérer la liste des albums d'une collection * @return {Object} */ async getAll() { const { page, limit, exportFormat = "json", sort = "artists_sort", order = "asc", artist, format, year, genre, style, userId: collectionUserId, } = this.req.query; let userId = this.req.user?._id; const where = {}; if (artist) { where["artists.name"] = artist; } if (format) { where["formats.name"] = format; } if (year) { where.year = year; } if (genre) { where.genres = genre; } if (style) { where.styles = style; } if (!this.req.user && !collectionUserId) { throw new ErrorEvent( 401, "Collection", "Cette collection n'est pas publique" ); } if (collectionUserId) { const userIsSharingCollection = await UsersModel.findById( collectionUserId ); if ( !userIsSharingCollection || !userIsSharingCollection.isPublicCollection ) { throw new ErrorEvent( 401, "Collection", "Cette collection n'est pas publique" ); } userId = userIsSharingCollection._id; } const count = await AlbumsModel.count({ User: userId, ...where, }); let params = { sort: { [sort]: order.toLowerCase() === "asc" ? 1 : -1, }, }; if (page && limit) { const skip = (page - 1) * limit; params = { ...params, skip, limit, }; } const rows = await AlbumsModel.find( { User: userId, ...where, }, [], params ); switch (exportFormat) { case "csv": return Export.convertToCsv(rows); case "xls": return Export.convertToXls(rows); case "xml": return Export.convertToXml(rows); case "musictopus": return Export.convertToMusicTopus(rows); case "json": default: return { rows, count, }; } } /** * Méthode permettant de mettre à jour un album * * @return {Object} */ async patchOne() { const { itemId: _id } = this.req.params; const { _id: User } = this.req.user; const query = { _id, User, }; const album = await AlbumsModel.findOne(query); if (!album) { throw new ErrorEvent( 404, "Mise à jour", "Impossible de trouver cet album" ); } const values = await getAlbumDetails(album.discogsId); return AlbumsModel.findOneAndUpdate(query, values, { new: true }); } /** * Méthode permettant de supprimer un élément d'une collection * @return {Boolean} */ async deleteOne() { const res = await AlbumsModel.findOneAndDelete({ user: this.req.user._id, _id: this.req.params.itemId, }); if (res) { return true; } throw new ErrorEvent( 404, "Suppression", "Impossible de trouver cet album" ); } /** * Méthode permettant de créer la page "ma-collection" */ async loadMyCollection() { const artists = await Albums.getAllDistincts( "artists.name", this.req.user._id ); const formats = await Albums.getAllDistincts( "formats.name", this.req.user._id ); const years = await Albums.getAllDistincts("year", this.req.user._id); const genres = await Albums.getAllDistincts( "genres", this.req.user._id ); const styles = await Albums.getAllDistincts( "styles", this.req.user._id ); this.setPageContent("artists", artists); this.setPageContent("formats", formats); this.setPageContent("years", years); this.setPageContent("genres", genres); this.setPageContent("styles", styles); this.setPageTitle("Ma collection"); } /** * Méthode permettant d'afficher le détails d'un album */ async loadItem() { const { itemId: _id } = this.req.params; const { _id: User } = this.req.user; const album = await AlbumsModel.findOne({ _id, User, }); const item = { ...album.toJSON(), released: album.released ? formatDate(album.released, "MM/dd/yyyy") : null, }; this.setPageContent("item", item); this.setPageTitle( `Détails de l'album ${item.title} de ${item.artists_sort}` ); } /** * Méthode permettant de créer la page "collection/:userId" */ async loadPublicCollection() { const { userId } = this.req.params; const user = await UsersModel.findById(userId); if (!user || !user.isPublicCollection) { throw new ErrorEvent( 401, "Collection non partagée", "Cet utilisateur ne souhaite pas partager sa collection" ); } const artists = await Albums.getAllDistincts("artists.name", userId); const formats = await Albums.getAllDistincts("formats.name", userId); const years = await Albums.getAllDistincts("year", userId); const genres = await Albums.getAllDistincts("genres", userId); const styles = await Albums.getAllDistincts("styles", userId); this.setPageContent("username", user.username); this.setPageTitle(`Collection publique de ${user.username}`); this.setPageContent("artists", artists); this.setPageContent("formats", formats); this.setPageContent("years", years); this.setPageContent("genres", genres); this.setPageContent("styles", styles); } } export default Albums;