mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-04-25 01:16:40 +02:00
Fixed sorting to be more consistent for multiple series (and generally)
This commit is contained in:
parent
d64932dad7
commit
b322d0207b
@ -160,17 +160,30 @@ class LibraryController {
|
|||||||
minified: req.query.minified === '1',
|
minified: req.query.minified === '1',
|
||||||
collapseseries: req.query.collapseseries === '1'
|
collapseseries: req.query.collapseseries === '1'
|
||||||
}
|
}
|
||||||
|
var mediaIsBook = payload.mediaType === 'book'
|
||||||
|
|
||||||
var filterSeries = null
|
var filterSeries = null
|
||||||
if (payload.filterBy) {
|
if (payload.filterBy) {
|
||||||
// If filtering by series, will include seriesName and seriesSequence on media metadata
|
// If filtering by series, will include seriesName and seriesSequence on media metadata
|
||||||
filterSeries = (payload.mediaType == 'book' && payload.filterBy.startsWith('series.')) ? libraryHelpers.decode(payload.filterBy.replace('series.', '')) : null
|
filterSeries = (mediaIsBook && payload.filterBy.startsWith('series.')) ? libraryHelpers.decode(payload.filterBy.replace('series.', '')) : null
|
||||||
if (filterSeries === 'No Series') filterSeries = null
|
if (filterSeries === 'No Series') filterSeries = null
|
||||||
|
|
||||||
libraryItems = libraryHelpers.getFilteredLibraryItems(libraryItems, payload.filterBy, req.user, this.rssFeedManager.feedsArray)
|
libraryItems = libraryHelpers.getFilteredLibraryItems(libraryItems, payload.filterBy, req.user, this.rssFeedManager.feedsArray)
|
||||||
payload.total = libraryItems.length
|
payload.total = libraryItems.length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (payload.collapseseries) {
|
||||||
|
libraryItems = libraryHelpers.collapseBookSeries(libraryItems, this.db.series, filterSeries)
|
||||||
|
payload.total = libraryItems.length
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var sortArray = []
|
||||||
|
if (filterSeries) {
|
||||||
|
// Book media when filtering series will sort by the series sequence
|
||||||
|
sortArray.push({ asc: (li) => li.media.metadata.getSeries(filterSeries).sequence })
|
||||||
|
}
|
||||||
|
|
||||||
if (payload.sortBy) {
|
if (payload.sortBy) {
|
||||||
var sortKey = payload.sortBy
|
var sortKey = payload.sortBy
|
||||||
|
|
||||||
@ -186,29 +199,37 @@ class LibraryController {
|
|||||||
sortKey += 'IgnorePrefix'
|
sortKey += 'IgnorePrefix'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start sort
|
// If series are collapsed and not sorting by title, sort all collapsed series to the end in alphabetical order
|
||||||
var direction = payload.sortDesc ? 'desc' : 'asc'
|
if (payload.collapseseries && !sortByTitle) {
|
||||||
var sortArray = [
|
sortArray.push({
|
||||||
{
|
asc: (li) => {
|
||||||
[direction]: (li) => {
|
if (li.collapsedSeries) {
|
||||||
// When collapsing by series and sorting by title use the series name instead of the book title
|
return this.db.serverSettings.sortingIgnorePrefix ?
|
||||||
if (payload.mediaType === 'book' && payload.collapseseries && li.media.metadata.seriesName) {
|
li.collapsedSeries.nameIgnorePrefix :
|
||||||
if (sortByTitle) {
|
li.collapsedSeries.name
|
||||||
return this.db.serverSettings.sortingIgnorePrefix ? li.media.metadata.seriesNameIgnorePrefix : li.media.metadata.seriesName
|
} else {
|
||||||
} else {
|
return ''
|
||||||
// When not sorting by title always show the collapsed series at the end
|
|
||||||
return direction === 'desc' ? -1 : 'zzzz'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var direction = payload.sortDesc ? 'desc' : 'asc'
|
||||||
|
sortArray.push({
|
||||||
|
[direction]: (li) => {
|
||||||
|
if (mediaIsBook && sortByTitle && li.collapsedSeries) {
|
||||||
|
return this.db.serverSettings.sortingIgnorePrefix ?
|
||||||
|
li.collapsedSeries.nameIgnorePrefix :
|
||||||
|
li.collapsedSeries.name
|
||||||
|
} else {
|
||||||
// Supports dot notation strings i.e. "media.metadata.title"
|
// Supports dot notation strings i.e. "media.metadata.title"
|
||||||
return sortKey.split('.').reduce((a, b) => a[b], li)
|
return sortKey.split('.').reduce((a, b) => a[b], li)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
})
|
||||||
|
|
||||||
// Secondary sort when sorting by book author use series sort title
|
// Secondary sort when sorting by book author use series sort title
|
||||||
if (payload.mediaType === 'book' && payload.sortBy.includes('author')) {
|
if (mediaIsBook && payload.sortBy.includes('author')) {
|
||||||
sortArray.push({
|
sortArray.push({
|
||||||
asc: (li) => {
|
asc: (li) => {
|
||||||
if (li.media.metadata.series && li.media.metadata.series.length) {
|
if (li.media.metadata.series && li.media.metadata.series.length) {
|
||||||
@ -218,30 +239,31 @@ class LibraryController {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the items
|
||||||
|
if (sortArray.length) {
|
||||||
libraryItems = naturalSort(libraryItems).by(sortArray)
|
libraryItems = naturalSort(libraryItems).by(sortArray)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload.collapseseries) {
|
payload.results = libraryItems.map(li => {
|
||||||
libraryItems = libraryHelpers.collapseBookSeries(libraryItems, this.db.series)
|
let json = payload.minified ? li.toJSONMinified() : li.toJSON()
|
||||||
payload.total = libraryItems.length
|
|
||||||
} else if (filterSeries) {
|
if (li.collapsedSeries) {
|
||||||
// Book media when filtering series will include series object on media metadata
|
json.collapsedSeries = {
|
||||||
libraryItems = libraryItems.map(li => {
|
id: li.collapsedSeries.id,
|
||||||
var series = li.media.metadata.getSeries(filterSeries)
|
name: li.collapsedSeries.name,
|
||||||
var liJson = payload.minified ? li.toJSONMinified() : li.toJSON()
|
nameIgnorePrefix: li.collapsedSeries.nameIgnorePrefix,
|
||||||
liJson.media.metadata.series = series
|
libraryItemIds: li.collapsedSeries.books.map(b => b.id),
|
||||||
return liJson
|
numBooks: li.collapsedSeries.books.length
|
||||||
})
|
}
|
||||||
libraryItems = naturalSort(libraryItems).asc(li => li.media.metadata.series.sequence)
|
} else if (filterSeries) {
|
||||||
} else {
|
json.media.metadata.series = li.media.metadata.getSeries(filterSeries)
|
||||||
libraryItems = libraryItems.map(li => payload.minified ? li.toJSONMinified() : li.toJSON())
|
}
|
||||||
}
|
|
||||||
|
return json
|
||||||
|
})
|
||||||
|
|
||||||
if (payload.limit) {
|
|
||||||
var startIndex = payload.page * payload.limit
|
|
||||||
libraryItems = libraryItems.slice(startIndex, startIndex + payload.limit)
|
|
||||||
}
|
|
||||||
payload.results = libraryItems
|
|
||||||
res.json(payload)
|
res.json(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,34 +280,34 @@ module.exports = {
|
|||||||
return totalSize
|
return totalSize
|
||||||
},
|
},
|
||||||
|
|
||||||
collapseBookSeries(libraryItems, series) {
|
|
||||||
var seriesObjects = this.getSeriesFromBooks(libraryItems, series, null, null, true)
|
collapseBookSeries(libraryItems, series, filterSeries) {
|
||||||
var seriesToUse = {}
|
// Get series from the library items. If this list is being collapsed after filtering for a series,
|
||||||
var collapsedLibraryItems = []
|
// don't collapse that series, only books that are in other series.
|
||||||
|
var seriesObjects = this
|
||||||
|
.getSeriesFromBooks(libraryItems, series, null, null, true)
|
||||||
|
.filter(s => s.id != filterSeries)
|
||||||
|
|
||||||
|
var filteredLibraryItems = []
|
||||||
|
|
||||||
libraryItems.forEach((li) => {
|
libraryItems.forEach((li) => {
|
||||||
if (li.mediaType != 'book') return
|
if (li.mediaType != 'book') return
|
||||||
|
|
||||||
// Handle when this is the first book in a series
|
// Handle when this is the first book in a series
|
||||||
seriesObjects.filter(s => s.books[0].id == li.id).forEach(series => {
|
seriesObjects.filter(s => s.books[0].id == li.id).forEach(series => {
|
||||||
let libraryItemJson = li.toJSONMinified()
|
// Clone the library item as we need to attach data to it, but don't
|
||||||
libraryItemJson.collapsedSeries = {
|
// want to change the global copy of the library item
|
||||||
id: series.id,
|
filteredLibraryItems.push(Object.assign(
|
||||||
name: series.name,
|
Object.create(Object.getPrototypeOf(li)),
|
||||||
nameIgnorePrefix: series.nameIgnorePrefix,
|
li, { collapsedSeries: series }))
|
||||||
libraryItemIds: series.books.map(b => b.id),
|
|
||||||
numBooks: series.books.length
|
|
||||||
}
|
|
||||||
collapsedLibraryItems.push(libraryItemJson);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ignore books contained in series
|
// Only included books not contained in series
|
||||||
if (li.media.metadata.series.length) return
|
if (!seriesObjects.some(s => s.books.some(b => b.id == li.id)))
|
||||||
|
filteredLibraryItems.push(li)
|
||||||
collapsedLibraryItems.push(li.toJSONMinified())
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return collapsedLibraryItems
|
return filteredLibraryItems
|
||||||
},
|
},
|
||||||
|
|
||||||
buildPersonalizedShelves(user, libraryItems, mediaType, allSeries, allAuthors, maxEntitiesPerShelf = 10) {
|
buildPersonalizedShelves(user, libraryItems, mediaType, allSeries, allAuthors, maxEntitiesPerShelf = 10) {
|
||||||
|
Loading…
Reference in New Issue
Block a user