mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-05-24 01:13:00 -04:00
Merge pull request #4293 from advplyr/search_episodes
Add support for searching podcast episode titles #3301
This commit is contained in:
commit
8d0434143c
@ -217,6 +217,16 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.results.episodes?.length) {
|
||||||
|
shelves.push({
|
||||||
|
id: 'episodes',
|
||||||
|
label: 'Episodes',
|
||||||
|
labelStringKey: 'LabelEpisodes',
|
||||||
|
type: 'episode',
|
||||||
|
entities: this.results.episodes.map((res) => res.libraryItem)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (this.results.series?.length) {
|
if (this.results.series?.length) {
|
||||||
shelves.push({
|
shelves.push({
|
||||||
id: 'series',
|
id: 'series',
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex items-center h-full px-1 overflow-hidden">
|
||||||
|
<covers-book-cover :library-item="libraryItem" :width="coverWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
||||||
|
<div class="grow px-2 episodeSearchCardContent">
|
||||||
|
<p class="truncate text-sm">{{ episodeTitle }}</p>
|
||||||
|
<p class="text-xs text-gray-200 truncate">{{ podcastTitle }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
libraryItem: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
episode: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
bookCoverAspectRatio() {
|
||||||
|
return this.$store.getters['libraries/getBookCoverAspectRatio']
|
||||||
|
},
|
||||||
|
coverWidth() {
|
||||||
|
if (this.bookCoverAspectRatio === 1) return 50 * 1.2
|
||||||
|
return 50
|
||||||
|
},
|
||||||
|
media() {
|
||||||
|
return this.libraryItem?.media || {}
|
||||||
|
},
|
||||||
|
mediaMetadata() {
|
||||||
|
return this.media.metadata || {}
|
||||||
|
},
|
||||||
|
episodeTitle() {
|
||||||
|
return this.episode.title || 'No Title'
|
||||||
|
},
|
||||||
|
podcastTitle() {
|
||||||
|
return this.mediaMetadata.title || 'No Title'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {},
|
||||||
|
mounted() {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.episodeSearchCardContent {
|
||||||
|
width: calc(100% - 80px);
|
||||||
|
height: 75px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
@ -39,6 +39,15 @@
|
|||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<p v-if="episodeResults.length" class="uppercase text-xs text-gray-400 my-1 px-1 font-semibold">{{ $strings.LabelEpisodes }}</p>
|
||||||
|
<template v-for="item in episodeResults">
|
||||||
|
<li :key="item.libraryItem.recentEpisode.id" class="text-gray-50 select-none relative cursor-pointer hover:bg-black-400 py-1" role="option" @click="clickOption">
|
||||||
|
<nuxt-link :to="`/item/${item.libraryItem.id}`">
|
||||||
|
<cards-episode-search-card :episode="item.libraryItem.recentEpisode" :library-item="item.libraryItem" />
|
||||||
|
</nuxt-link>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
|
||||||
<p v-if="authorResults.length" class="uppercase text-xs text-gray-400 mb-1 mt-3 px-1 font-semibold">{{ $strings.LabelAuthors }}</p>
|
<p v-if="authorResults.length" class="uppercase text-xs text-gray-400 mb-1 mt-3 px-1 font-semibold">{{ $strings.LabelAuthors }}</p>
|
||||||
<template v-for="item in authorResults">
|
<template v-for="item in authorResults">
|
||||||
<li :key="item.id" class="text-gray-50 select-none relative cursor-pointer hover:bg-black-400 py-1" role="option" @click="clickOption">
|
<li :key="item.id" class="text-gray-50 select-none relative cursor-pointer hover:bg-black-400 py-1" role="option" @click="clickOption">
|
||||||
@ -100,6 +109,7 @@ export default {
|
|||||||
isFetching: false,
|
isFetching: false,
|
||||||
search: null,
|
search: null,
|
||||||
podcastResults: [],
|
podcastResults: [],
|
||||||
|
episodeResults: [],
|
||||||
bookResults: [],
|
bookResults: [],
|
||||||
authorResults: [],
|
authorResults: [],
|
||||||
seriesResults: [],
|
seriesResults: [],
|
||||||
@ -115,7 +125,7 @@ export default {
|
|||||||
return this.$store.state.libraries.currentLibraryId
|
return this.$store.state.libraries.currentLibraryId
|
||||||
},
|
},
|
||||||
totalResults() {
|
totalResults() {
|
||||||
return this.bookResults.length + this.seriesResults.length + this.authorResults.length + this.tagResults.length + this.genreResults.length + this.podcastResults.length + this.narratorResults.length
|
return this.bookResults.length + this.seriesResults.length + this.authorResults.length + this.tagResults.length + this.genreResults.length + this.podcastResults.length + this.narratorResults.length + this.episodeResults.length
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -132,6 +142,7 @@ export default {
|
|||||||
this.search = null
|
this.search = null
|
||||||
this.lastSearch = null
|
this.lastSearch = null
|
||||||
this.podcastResults = []
|
this.podcastResults = []
|
||||||
|
this.episodeResults = []
|
||||||
this.bookResults = []
|
this.bookResults = []
|
||||||
this.authorResults = []
|
this.authorResults = []
|
||||||
this.seriesResults = []
|
this.seriesResults = []
|
||||||
@ -175,6 +186,7 @@ export default {
|
|||||||
if (!this.isFetching) return
|
if (!this.isFetching) return
|
||||||
|
|
||||||
this.podcastResults = searchResults.podcast || []
|
this.podcastResults = searchResults.podcast || []
|
||||||
|
this.episodeResults = searchResults.episodes || []
|
||||||
this.bookResults = searchResults.book || []
|
this.bookResults = searchResults.book || []
|
||||||
this.authorResults = searchResults.authors || []
|
this.authorResults = searchResults.authors || []
|
||||||
this.seriesResults = searchResults.series || []
|
this.seriesResults = searchResults.series || []
|
||||||
|
@ -22,6 +22,7 @@ export default {
|
|||||||
})
|
})
|
||||||
results = {
|
results = {
|
||||||
podcasts: results?.podcast || [],
|
podcasts: results?.podcast || [],
|
||||||
|
episodes: results?.episodes || [],
|
||||||
books: results?.book || [],
|
books: results?.book || [],
|
||||||
authors: results?.authors || [],
|
authors: results?.authors || [],
|
||||||
series: results?.series || [],
|
series: results?.series || [],
|
||||||
@ -61,6 +62,7 @@ export default {
|
|||||||
})
|
})
|
||||||
this.results = {
|
this.results = {
|
||||||
podcasts: results?.podcast || [],
|
podcasts: results?.podcast || [],
|
||||||
|
episodes: results?.episodes || [],
|
||||||
books: results?.book || [],
|
books: results?.book || [],
|
||||||
authors: results?.authors || [],
|
authors: results?.authors || [],
|
||||||
series: results?.series || [],
|
series: results?.series || [],
|
||||||
|
@ -411,6 +411,43 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search podcast episode title
|
||||||
|
const podcastEpisodes = await Database.podcastEpisodeModel.findAll({
|
||||||
|
where: [
|
||||||
|
Sequelize.literal(textSearchQuery.matchExpression('podcastEpisode.title')),
|
||||||
|
{
|
||||||
|
'$podcast.libraryItem.libraryId$': library.id
|
||||||
|
}
|
||||||
|
],
|
||||||
|
replacements: userPermissionPodcastWhere.replacements,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: Database.podcastModel,
|
||||||
|
where: [...userPermissionPodcastWhere.podcastWhere],
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: Database.libraryItemModel
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
distinct: true,
|
||||||
|
offset,
|
||||||
|
limit
|
||||||
|
})
|
||||||
|
const episodeMatches = []
|
||||||
|
for (const episode of podcastEpisodes) {
|
||||||
|
const libraryItem = episode.podcast.libraryItem
|
||||||
|
libraryItem.media = episode.podcast
|
||||||
|
libraryItem.media.podcastEpisodes = []
|
||||||
|
const oldPodcastEpisodeJson = episode.toOldJSONExpanded(libraryItem.id)
|
||||||
|
const libraryItemJson = libraryItem.toOldJSONExpanded()
|
||||||
|
libraryItemJson.recentEpisode = oldPodcastEpisodeJson
|
||||||
|
episodeMatches.push({
|
||||||
|
libraryItem: libraryItemJson
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const matchJsonValue = textSearchQuery.matchExpression('json_each.value')
|
const matchJsonValue = textSearchQuery.matchExpression('json_each.value')
|
||||||
|
|
||||||
// Search tags
|
// Search tags
|
||||||
@ -450,7 +487,8 @@ module.exports = {
|
|||||||
return {
|
return {
|
||||||
podcast: itemMatches,
|
podcast: itemMatches,
|
||||||
tags: tagMatches,
|
tags: tagMatches,
|
||||||
genres: genreMatches
|
genres: genreMatches,
|
||||||
|
episodes: episodeMatches
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user