mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-11-04 03:17:00 -05:00 
			
		
		
		
	Add:Random library sorting option for libraries and series #3166
- Fixed author sort and match button not showing
This commit is contained in:
		
							parent
							
								
									82f136ba79
								
							
						
					
					
						commit
						43d6c6678f
					
				@ -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" />
 | 
			
		||||
@ -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>
 | 
			
		||||
@ -187,6 +187,10 @@ export default {
 | 
			
		||||
        {
 | 
			
		||||
          text: this.$strings.LabelTotalDuration,
 | 
			
		||||
          value: 'totalDuration'
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          text: this.$strings.LabelRandomly,
 | 
			
		||||
          value: 'random'
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@ -88,6 +88,10 @@ export default {
 | 
			
		||||
        {
 | 
			
		||||
          text: this.$strings.LabelFileModified,
 | 
			
		||||
          value: 'mtimeMs'
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          text: this.$strings.LabelRandomly,
 | 
			
		||||
          value: 'random'
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
@ -128,6 +132,10 @@ export default {
 | 
			
		||||
        {
 | 
			
		||||
          text: this.$strings.LabelFileModified,
 | 
			
		||||
          value: 'mtimeMs'
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          text: this.$strings.LabelRandomly,
 | 
			
		||||
          value: 'random'
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@ -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",
 | 
			
		||||
 | 
			
		||||
@ -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')
 | 
			
		||||
 | 
			
		||||
@ -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 []
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
@ -89,6 +89,8 @@ module.exports = {
 | 
			
		||||
      }
 | 
			
		||||
    } else if (sortBy === 'media.numTracks') {
 | 
			
		||||
      return [['numEpisodes', dir]]
 | 
			
		||||
    } else if (sortBy === 'random') {
 | 
			
		||||
      return [Database.sequelize.random()]
 | 
			
		||||
    }
 | 
			
		||||
    return []
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@ module.exports = {
 | 
			
		||||
    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
 | 
			
		||||
    }
 | 
			
		||||
@ -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)`), {
 | 
			
		||||
      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
 | 
			
		||||
@ -101,9 +103,11 @@ module.exports = {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (attrQuery) {
 | 
			
		||||
      seriesWhere.push(Sequelize.where(Sequelize.literal(`(${attrQuery})`), {
 | 
			
		||||
      seriesWhere.push(
 | 
			
		||||
        Sequelize.where(Sequelize.literal(`(${attrQuery})`), {
 | 
			
		||||
          [Sequelize.Op.gt]: 0
 | 
			
		||||
      }))
 | 
			
		||||
        })
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const order = []
 | 
			
		||||
@ -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({
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user