diff --git a/app/views/search/resultDetails.js b/app/views/search/resultDetails.js index 099344d..fd0f339 100644 --- a/app/views/search/resultDetails.js +++ b/app/views/search/resultDetails.js @@ -6,7 +6,8 @@ import { modal } from '../partials/modal'; export const resultDetails = (searchController, result, emit = () => {}) => { const { __ } = searchController.i18n; - const modalId = `result_${result.uri}`; + const source = result.sources[0]; + const modalId = `result_${source.uri}`; const hasReviews = typeof result.averageRating !== 'undefined' && typeof result.numberOfReviews !== 'undefined'; @@ -27,37 +28,41 @@ export const resultDetails = (searchController, result, emit = () => {}) => { const tabNames = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty']; + const coversHTMLArray = result.covers.map((cover, index, allCovers) => { + return html`
+ ${cover.sourceId.replace(':', ' ').toUpperCase()}, Published: ${cover.publishDate} + ${typeof allCovers[index - 1] === 'undefined' + ? null + : html`` + } + ${typeof allCovers[index + 1] === 'undefined' + ? null + : html`` + } +
`; + }); + const modalContent = html`

${__('search.covers')}

${typeof result.covers === 'undefined' ? html`` - : html`
+ : html`
${result.covers.map((cover, index) => { return [ - html``, - // html``, + html``, + // html``, ]; })} -
- ${result.covers.map((cover, index, allCovers) => { - return html`
- ${cover.uri.replace(':', ' ').toUpperCase()}, Published: ${cover.publishDate} - ${typeof allCovers[index - 1] === 'undefined' - ? null - : html`` - } - ${typeof allCovers[index + 1] === 'undefined' - ? null - : html`` - } -
`; - })} -
+
${ + searchController.openModal === modalId + ? coversHTMLArray + : '' /* Leave the covers column empty until opened to prevent loading too many images */ + }
` }
@@ -72,7 +77,7 @@ export const resultDetails = (searchController, result, emit = () => {}) => {

Top Reviews

- + ${result.numberOfReviews} ${__('search.see_interaction_details')} @@ -92,27 +97,29 @@ export const resultDetails = (searchController, result, emit = () => {}) => {

${!searchController.showShelves ? null : html`
    ${searchController.shelves.map(shelf => { return html`
  • -
  • `; })}
`}

- + ${__('search.see_book_details')}

`; + const onShow = () => { + const coversColumn = document.getElementById(`covers_${modalId}`); + coversColumn.innerHTML = ''; + coversHTMLArray.forEach(element => coversColumn.appendChild(element)); + }; + return modal(modalId, searchController, modalContent, { styles: "width:90%;", buttonHTML, // This should be replaced with buttonHTML containing the ratings and number of reviews etc. headerText: result.name, - onShow: () => { - if (typeof result.covers === 'undefined') { - searchController.getCovers(result.uri).then(() => emit('render')); - } - }, + onShow, }); } \ No newline at end of file diff --git a/server/controllers/bookData/Inventaire.js b/server/controllers/bookData/Inventaire.js index 3bb4ff2..e3855e0 100644 --- a/server/controllers/bookData/Inventaire.js +++ b/server/controllers/bookData/Inventaire.js @@ -15,6 +15,7 @@ class Inventaire { static handleQuickEntity(entityObject) { return { + id: null, name: ( typeof entityObject.label !== 'undefined' ? entityObject.label @@ -25,22 +26,26 @@ class Inventaire { ? entityObject.description : null ), - source: 'inventaire', - link: ( - typeof entityObject.uri !== 'undefined' - ? `${Inventaire.url}/entity/${entityObject.uri}` - : null - ), - uri: ( - typeof entityObject.uri !== 'undefined' - ? entityObject.uri - : null - ), + sources: [ + { + source: 'inventaire', + uri: ( + typeof entityObject.uri !== 'undefined' + ? entityObject.uri + : null + ), + link: ( + typeof entityObject.uri !== 'undefined' + ? `${Inventaire.url}/entity/${entityObject.uri}` + : null + ), + }, + ], covers: ( typeof entityObject.image !== 'undefined' ? entityObject.image.map(imageId => { return { - uri: imageId.toString(), + sourceId: imageId.toString(), url: `${Inventaire.url}/img/entities/${imageId}`, } }) @@ -72,17 +77,21 @@ class Inventaire { : null ) ), - source: 'inventaire', - link: ( - typeof entityObject.uri !== 'undefined' - ? `${Inventaire.url}/entity/${entityObject.uri}` - : null - ), - uri: ( - typeof entityObject.uri !== 'undefined' - ? entityObject.uri - : null - ), + sources: [ + { + source: 'inventaire', + uri: ( + typeof entityObject.uri !== 'undefined' + ? entityObject.uri + : null + ), + link: ( + typeof entityObject.uri !== 'undefined' + ? `${Inventaire.url}/entity/${entityObject.uri}` + : null + ), + }, + ], }; } @@ -109,7 +118,7 @@ class Inventaire { if (typeof bookData.entities !== 'undefined' && typeof bookData.entities[uri] !== 'undefined') { bookData = Inventaire.handleEntity(bookData.entities[uri], this.lang); - bookData['covers'] = await this.getCovers(bookData.uri); + bookData['covers'] = await this.getCovers(bookData.sources[0].uri); return bookData; } @@ -126,7 +135,7 @@ class Inventaire { } // Note: property `wdt:P629` is a given entity (uri)'s list of editions (ISBNs). - const editionsRequest = fetch(`${Inventaire.url}/api/entities?action=reverse-claims&uri=${encodeURIComponent(uri)}&property=wdt:P629`) + const editionsRequest = fetch(`${Inventaire.url}/api/entities?action=reverse-claims&value=${encodeURIComponent(uri)}&property=wdt:P629`) editionsRequest.catch(exception => { console.error(exception); return { @@ -180,7 +189,7 @@ class Inventaire { }).map(key => { const entity = responseJSON.entities[key]; return { - uri: entity.uri, + sourceId: entity.uri, url: typeof entity.claims['invp:P2'] !== 'undefined' ? `${Inventaire.url}/img/entities/${entity.claims['invp:P2'][0]}` : null, publishDate: typeof entity.claims['wdt:P577'] !== 'undefined' ? entity.claims['wdt:P577'][0] : null, } @@ -193,7 +202,10 @@ class Inventaire { return a.publishDate < b.publishDate ? -1 : 1; }); - return covers; + return covers.map(cover => { + delete cover.publishDate; + return cover; + }); }); } } diff --git a/server/controllers/bookReference.js b/server/controllers/bookReference.js index 352918b..75991d1 100644 --- a/server/controllers/bookReference.js +++ b/server/controllers/bookReference.js @@ -28,7 +28,7 @@ class BookReferenceController { } // Get formatted book data from source - const bookData = dataClass.getBookData(sourceId); + const bookData = await dataClass.getBookData(sourceId); if (typeof bookData.uri !== 'undefined') { // Check for references by exact name and author from source diff --git a/server/controllers/search/Inventaire.js b/server/controllers/search/Inventaire.js index e39afce..d1d9fa5 100644 --- a/server/controllers/search/Inventaire.js +++ b/server/controllers/search/Inventaire.js @@ -43,7 +43,14 @@ function searchInventaire(searchTerm, language) { message: 'An error occurred when trying read the response from Inventaire as JSON.', } }); - return json.then(responseJSON => responseJSON.results.map(work => Inventaire.handleEntity(work, language))); + return json.then(responseJSON => { + return responseJSON.results.map(async work => { + const inventaire = new Inventaire(langauge); + const bookData = Inventaire.handleEntity(work, language); + bookData['covers'] = await inventaire.getCovers(bookData.sources[0].uri); + return bookData; + }); + }); } } diff --git a/server/controllers/search/index.js b/server/controllers/search/index.js index 1b4a82a..0e2958e 100644 --- a/server/controllers/search/index.js +++ b/server/controllers/search/index.js @@ -3,6 +3,7 @@ const { Op, fn, col } = require('sequelize'); const BooksController = require('../bookData'); const { quickSearchInventaire } = require('./Inventaire'); +const Inventaire = require('../bookData/Inventaire'); const defaultSearchOptions = { searchBy: 'name', // A column name in the BookReference model, mainly 'name' or 'description' @@ -57,6 +58,30 @@ 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) { const searchBy = options.searchBy.replace('title', 'name').replace('author', 'description'); const { source, language } = options; @@ -77,22 +102,23 @@ class SearchController { // Add any search results that match refs with the same URI and delete from results array const urisToCheck = searchResults.filter( - result => !bookReferences.some(ref => result.uri === ref.sources[source]) - ).map(result => result.uri); + result => !bookReferences.some(ref => result.sources[0].uri === ref.sources[source]) + ).map(result => result.sources[0].uri); let extraReferences = []; if (urisToCheck.length > 0) { // Need to figure this out extraReferences = await this.searchReferencesBySourceCodes(source, urisToCheck); } + searchResults = searchResults.filter( // Only show the rest of the search results + result => !extraReferences.some( + ref => result.sources[0].uri === ref.sources[source] + ) + ); return [ - ...bookReferences, - ...extraReferences, - ...searchResults.filter( // Only show the rest of the search results - result => !extraReferences.some( - ref => result.uri === ref.sources[source] - ) - ), + ...bookReferences.map(match => SearchController.formatReferenceSources(match)), + ...extraReferences.map(match => SearchController.formatReferenceSources(match)), + ...searchResults, ]; }