Skip to content

Commit

Permalink
Add:Random library sorting option for libraries and series #3166
Browse files Browse the repository at this point in the history
- Fixed author sort and match button not showing
  • Loading branch information
advplyr committed Jul 25, 2024
1 parent 82f136b commit 43d6c66
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 26 deletions.
18 changes: 11 additions & 7 deletions client/components/app/BookShelfToolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,6 @@

<ui-context-menu-dropdown v-if="contextMenuItems.length" :items="contextMenuItems" :menu-width="110" class="ml-2" @action="contextMenuAction" />
</template>
<!-- home page -->
<template v-else-if="isHome">
<div class="flex-grow" />
<ui-context-menu-dropdown v-if="contextMenuItems.length" :items="contextMenuItems" :menu-width="110" class="ml-2" @action="contextMenuAction" />
</template>
<!-- search page -->
<template v-else-if="page === 'search'">
<div class="flex-grow" />
Expand All @@ -99,10 +94,15 @@
<!-- authors page -->
<template v-else-if="page === 'authors'">
<div class="flex-grow" />
<ui-btn v-if="userCanUpdate && authors && authors.length && !isBatchSelecting" :loading="processingAuthors" color="primary" small @click="matchAllAuthors">{{ $strings.ButtonMatchAllAuthors }}</ui-btn>
<ui-btn v-if="userCanUpdate && authors?.length && !isBatchSelecting" :loading="processingAuthors" color="primary" small @click="matchAllAuthors">{{ $strings.ButtonMatchAllAuthors }}</ui-btn>

<!-- author sort select -->
<controls-sort-select v-if="authors && authors.length" v-model="settings.authorSortBy" :descending.sync="settings.authorSortDesc" :items="authorSortItems" class="w-36 sm:w-44 md:w-48 h-7.5 ml-1 sm:ml-4" @change="updateAuthorSort" />
<controls-sort-select v-if="authors?.length" v-model="settings.authorSortBy" :descending.sync="settings.authorSortDesc" :items="authorSortItems" class="w-36 sm:w-44 md:w-48 h-7.5 ml-1 sm:ml-4" @change="updateAuthorSort" />
</template>
<!-- home page -->
<template v-else-if="isHome">
<div class="flex-grow" />
<ui-context-menu-dropdown v-if="contextMenuItems.length" :items="contextMenuItems" :menu-width="110" class="ml-2" @action="contextMenuAction" />
</template>
</div>
</div>
Expand Down Expand Up @@ -187,6 +187,10 @@ export default {
{
text: this.$strings.LabelTotalDuration,
value: 'totalDuration'
},
{
text: this.$strings.LabelRandomly,
value: 'random'
}
]
},
Expand Down
10 changes: 9 additions & 1 deletion client/components/controls/LibrarySortSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ export default {
{
text: this.$strings.LabelFileModified,
value: 'mtimeMs'
},
{
text: this.$strings.LabelRandomly,
value: 'random'
}
]
},
Expand Down Expand Up @@ -128,6 +132,10 @@ export default {
{
text: this.$strings.LabelFileModified,
value: 'mtimeMs'
},
{
text: this.$strings.LabelRandomly,
value: 'random'
}
]
},
Expand Down Expand Up @@ -215,4 +223,4 @@ export default {
}
}
}
</script>
</script>
1 change: 1 addition & 0 deletions client/strings/en-us.json
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@
"LabelRSSFeedPreventIndexing": "Prevent Indexing",
"LabelRSSFeedSlug": "RSS Feed Slug",
"LabelRSSFeedURL": "RSS Feed URL",
"LabelRandomly": "Randomly",
"LabelReAddSeriesToContinueListening": "Re-add series to Continue Listening",
"LabelRead": "Read",
"LabelReadAgain": "Read Again",
Expand Down
3 changes: 2 additions & 1 deletion server/utils/queries/libraryItemsBookFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ const Sequelize = require('sequelize')
const Database = require('../../Database')
const Logger = require('../../Logger')
const authorFilters = require('./authorFilters')
const { asciiOnlyToLowerCase } = require('../index')

const ShareManager = require('../../managers/ShareManager')

Expand Down Expand Up @@ -274,6 +273,8 @@ module.exports = {
return [[Sequelize.literal(`CAST(\`series.bookSeries.sequence\` AS FLOAT) ${nullDir}`)]]
} else if (sortBy === 'progress') {
return [[Sequelize.literal('mediaProgresses.updatedAt'), dir]]
} else if (sortBy === 'random') {
return [Database.sequelize.random()]
}
return []
},
Expand Down
2 changes: 2 additions & 0 deletions server/utils/queries/libraryItemsPodcastFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ module.exports = {
}
} else if (sortBy === 'media.numTracks') {
return [['numEpisodes', dir]]
} else if (sortBy === 'random') {
return [Database.sequelize.random()]
}
return []
},
Expand Down
40 changes: 23 additions & 17 deletions server/utils/queries/seriesFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@ module.exports = {

/**
* Get series filtered and sorted
*
* @param {import('../../objects/Library')} library
* @param {import('../../objects/user/User')} user
* @param {string} filterBy
* @param {string} sortBy
* @param {boolean} sortDesc
* @param {string[]} include
* @param {number} limit
* @param {number} offset
*
* @param {import('../../objects/Library')} library
* @param {import('../../objects/user/User')} user
* @param {string} filterBy
* @param {string} sortBy
* @param {boolean} sortDesc
* @param {string[]} include
* @param {number} limit
* @param {number} offset
* @returns {Promise<{ series:object[], count:number }>}
*/
async getFilteredSeries(library, user, filterBy, sortBy, sortDesc, include, limit, offset) {
let filterValue = null
let filterGroup = null
if (filterBy) {
const searchGroups = ['genres', 'tags', 'authors', 'progress', 'narrators', 'publishers', 'languages']
const group = searchGroups.find(_group => filterBy.startsWith(_group + '.'))
const group = searchGroups.find((_group) => filterBy.startsWith(_group + '.'))
filterGroup = group || filterBy
filterValue = group ? this.decode(filterBy.replace(`${group}.`, '')) : null
}
Expand All @@ -49,9 +49,11 @@ module.exports = {
// Handle library setting to hide single book series
// TODO: Merge with existing query
if (library.settings.hideSingleBookSeries) {
seriesWhere.push(Sequelize.where(Sequelize.literal(`(SELECT count(*) FROM books b, bookSeries bs WHERE bs.seriesId = series.id AND bs.bookId = b.id)`), {
[Sequelize.Op.gt]: 1
}))
seriesWhere.push(
Sequelize.where(Sequelize.literal(`(SELECT count(*) FROM books b, bookSeries bs WHERE bs.seriesId = series.id AND bs.bookId = b.id)`), {
[Sequelize.Op.gt]: 1
})
)
}

// Handle filters
Expand Down Expand Up @@ -101,9 +103,11 @@ module.exports = {
}

if (attrQuery) {
seriesWhere.push(Sequelize.where(Sequelize.literal(`(${attrQuery})`), {
[Sequelize.Op.gt]: 0
}))
seriesWhere.push(
Sequelize.where(Sequelize.literal(`(${attrQuery})`), {
[Sequelize.Op.gt]: 0
})
)
}

const order = []
Expand Down Expand Up @@ -133,6 +137,8 @@ module.exports = {
} else if (sortBy === 'lastBookUpdated') {
seriesAttributes.include.push([Sequelize.literal('(SELECT MAX(b.updatedAt) FROM books b, bookSeries bs WHERE bs.seriesId = series.id AND b.id = bs.bookId)'), 'mostRecentBookUpdated'])
order.push(['mostRecentBookUpdated', dir])
} else if (sortBy === 'random') {
order.push(Database.sequelize.random())
}

const { rows: series, count } = await Database.seriesModel.findAndCountAll({
Expand Down Expand Up @@ -184,7 +190,7 @@ module.exports = {
sensitivity: 'base'
})
})
oldSeries.books = s.bookSeries.map(bs => {
oldSeries.books = s.bookSeries.map((bs) => {
const libraryItem = bs.book.libraryItem.toJSON()
delete bs.book.libraryItem
libraryItem.media = bs.book
Expand Down

0 comments on commit 43d6c66

Please sign in to comment.