Compare commits

...

2 Commits

4 changed files with 119 additions and 65 deletions

View File

@ -7,6 +7,30 @@ class BookReferenceController {
this.lang = language; this.lang = language;
} }
static formatReferenceSources(reference) {
const referenceSources = Object.keys(reference.sources);
const reformattedSources = referenceSources.map(source => {
const uri = reference.sources[source];
let link;
switch (source) {
default:
case 'inventaire': {
link = `${Inventaire.url}/entity/${uri}`
break;
}
}
return {
source,
uri,
link,
}
});
reference.sources = reformattedSources;
return reference;
}
async createOrUpdateReference(source, sourceId, skipSearchBySourceCodes = false) { async createOrUpdateReference(source, sourceId, skipSearchBySourceCodes = false) {
const searchController = new SearchController(this.models); const searchController = new SearchController(this.models);
if (!skipSearchBySourceCodes) { if (!skipSearchBySourceCodes) {

View File

@ -2,8 +2,8 @@ const fetch = require('node-fetch');
const { Op, fn, col } = require('sequelize'); const { Op, fn, col } = require('sequelize');
const BooksController = require('../bookData'); const BooksController = require('../bookData');
const BookReferenceController = require('../bookReference');
const { quickSearchInventaire } = require('./Inventaire'); const { quickSearchInventaire } = require('./Inventaire');
const Inventaire = require('../bookData/Inventaire');
const defaultSearchOptions = { const defaultSearchOptions = {
searchBy: 'name', // A column name in the BookReference model, mainly 'name' or 'description' searchBy: 'name', // A column name in the BookReference model, mainly 'name' or 'description'
@ -58,30 +58,6 @@ class SearchController {
}; };
} }
static formatReferenceSources(reference) {
const referenceSources = Object.keys(reference.sources);
const reformattedSources = referenceSources.map(source => {
const uri = reference.sources[source];
let link;
switch (source) {
default:
case 'inventaire': {
link = `${Inventaire.url}/entity/${uri}`
break;
}
}
return {
source,
uri,
link,
}
});
reference.sources = reformattedSources;
return reference;
}
async search(searchTerm, options = defaultSearchOptions) { async search(searchTerm, options = defaultSearchOptions) {
const searchBy = options.searchBy.replace('title', 'name').replace('author', 'description'); const searchBy = options.searchBy.replace('title', 'name').replace('author', 'description');
const { source, language } = options; const { source, language } = options;
@ -116,8 +92,8 @@ class SearchController {
) )
); );
return [ return [
...bookReferences.map(match => SearchController.formatReferenceSources(match)), ...bookReferences.map(match => BookReferenceController.formatReferenceSources(match)),
...extraReferences.map(match => SearchController.formatReferenceSources(match)), ...extraReferences.map(match => BookReferenceController.formatReferenceSources(match)),
...searchResults, ...searchResults,
]; ];
} }

View File

@ -1,4 +1,6 @@
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const { Op, fn, col } = require('sequelize');
const BookReferenceController = require('./bookReference'); const BookReferenceController = require('./bookReference');
class ShelfController { class ShelfController {
@ -126,9 +128,79 @@ class ShelfController {
}; };
} }
return this.getFakeShelf(); // REMINDER: Factor in privacy levels
const shelf = await this.shelfModel.findByPk(shelfId); const shelf = await this.models.Shelf.findByPk(shelfId, {
include: [
{
as: 'User',
model: this.models.User,
attributes: ['id', 'username', 'displayName'],
required: true,
},
{
as: 'ShelfItems',
model: this.models.ShelfItem,
attributes: [
'id',
'bookEdition',
'order'
],
required: false,
include: [
{
as: 'Statuses',
model: this.models.Status,
attributes: ['text', 'progress', 'createdAt', 'updatedAt'],
required: false,
},
{
as: 'BookReference',
model: this.models.BookReference,
attributes: ['name', 'description', 'sources', 'covers'],
required: true,
// include: [
// {
// as: 'Interactions',
// model: this.models.Review,
// attributes: ['id'],
// required: false,
// },
// {
// as: 'Reviews',
// model: this.models.Review,
// attributes: ['id'],
// required: false,
// },
// {
// as: 'Ratings',
// model: this.models.Review,
// attributes: ['rating'],
// required: false,
// },
// ],
// group: [
// col('BookReference.id'),
// col('Interactions.id'),
// col('Reviews.id'),
// col('Ratings.id'),
// ],
},
],
orderBy: [[col('ShelfItems.order'), 'ASC']],
},
],
attributes: [
[col('Shelf.id'), 'id'],
'name',
'userId',
'permissionLevel',
'isDeletable',
'createdAt',
'updatedAt',
[fn('COUNT', col('ShelfItems.id')), 'numShelfItems'],
],
});
if (shelf === null) { if (shelf === null) {
return { return {
error: `Shelf with ID ${shelfId} not found.`, error: `Shelf with ID ${shelfId} not found.`,
@ -136,6 +208,8 @@ class ShelfController {
} }
shelf.updatedAt = this.getLastUpdatedTimestamp(shelf); shelf.updatedAt = this.getLastUpdatedTimestamp(shelf);
shelf.isPublic = shelf.permissionLevel === 0;
return shelf; return shelf;
} }
@ -198,7 +272,7 @@ class ShelfController {
async scrubShelfData (shelf, currentUser) { async scrubShelfData (shelf, currentUser) {
const userOwnsShelf = currentUser.id === shelf.userId; const userOwnsShelf = currentUser.id === shelf.userId;
const shelfUser = userOwnsShelf ? null : await shelf.getUser({ attributes: ['username, displayName'] }); const shelfUser = userOwnsShelf ? null : shelf.User;
let user = {}; let user = {};
if (shelfUser !== null) { if (shelfUser !== null) {
user.name = shelfUser.displayName; user.name = shelfUser.displayName;
@ -206,40 +280,25 @@ class ShelfController {
} else { } else {
user = null; user = null;
} }
const rawShelfItems = await shelf.getShelfItems({
attributes: ['bookId', 'createdAt', 'updatedAt'], // Untested
order: [['order', 'ASC']], const shelfItems = await Promise.all(shelf.ShelfItems.map(async (shelfItem) => {
}) const bookReference = BookReferenceController.formatReferenceSources(shelfItem.BookReference);
const bookReferenceMap = await Promise.all(shelfItems.map(shelfItem => { const reviews = await bookReference.getInteractions({
return shelfItem.getBookReference({
attributes: ['name', 'description', 'sources', 'covers'],
});
}));
const bookReferenceStatuses = await Promise.all(bookReferenceMap.map(bookReference => {
return bookReference.getStatuses({
where: { where: {
userId: shelf.userId, userId: shelf.userId,
}, }, // Return all reviews for any bookEdition so they can be filtered on frontend.
order: [['updatedAt', 'DESC']], attributes: ['text', 'rating', 'bookEdition'],
}); });
return {
title: bookReference.name,
author: bookReference.description,
sources: bookReference.sources,
covers: bookReference.covers,
updates: shelfItem.Statuses,
reviews,
};
})); }));
const bookReferences = bookReferenceMap.map(bookReference => {
bookReference.updates = bookReferenceStatuses.findAll(status => status.type === 1);
bookReference.rating = bookReferenceStatuses.find(status => status.type === 3);
bookReference.review = bookReferenceStatuses.find(status => status.type === 4);
return bookReference;
});
const shelfItems = rawShelfItems.map(shelfItem => {
const bookReference = bookReferences.find(bookData => bookData.id === shelfItem.bookId);
shelfItem.title = bookReference.name;
shelfItem.author = bookReference.description;
shelfItem.sources = bookReference.sources;
shelfItem.covers = bookReference.covers;
shelfItem.updates = bookReference.updates;
shelfItem.rating = bookReference.rating.data;
shelfItem.review = bookReference.review.data;
return shelfItem;
})
const shelfData = { const shelfData = {
name: shelf.name, name: shelf.name,

View File

@ -16,11 +16,6 @@ module.exports = models => {
onDelete: 'SET NULL', onDelete: 'SET NULL',
}); });
Shelf.belongsTo(User, {
foreignKey: 'permissionLevel',
onDelete: 'CASCADE',
});
Shelf.hasMany(ShelfItem, { Shelf.hasMany(ShelfItem, {
foreignKey: 'shelfId', foreignKey: 'shelfId',
}); });