mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-01-03 20:49:04 +01:00
Update:Remove manual sorting of podcast episodes and default to sort by published at
This commit is contained in:
parent
3c465994fe
commit
3e98b6f749
@ -33,8 +33,8 @@ export default {
|
|||||||
showMenu: false,
|
showMenu: false,
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
text: 'Current',
|
text: 'Pub Date',
|
||||||
value: 'index'
|
value: 'publishedAt'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Title',
|
text: 'Title',
|
||||||
@ -47,10 +47,6 @@ export default {
|
|||||||
{
|
{
|
||||||
text: 'Episode',
|
text: 'Episode',
|
||||||
value: 'episode'
|
value: 'episode'
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Pub Date',
|
|
||||||
value: 'publishedAt'
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="p-4 w-full text-sm py-6 rounded-lg bg-bg shadow-lg border border-black-300 relative overflow-hidden" style="min-height: 400px; max-height: 80vh">
|
<div class="p-4 w-full text-sm py-6 rounded-lg bg-bg shadow-lg border border-black-300 relative overflow-hidden" style="min-height: 400px; max-height: 80vh">
|
||||||
<form @submit.prevent="submitForm">
|
<form v-if="author" @submit.prevent="submitForm">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="w-40 p-2">
|
<div class="w-40 p-2">
|
||||||
<div class="w-full h-45 relative">
|
<div class="w-full h-45 relative">
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full px-2 py-3 overflow-hidden relative border-b border-white border-opacity-10" @mouseover="mouseover" @mouseleave="mouseleave">
|
<div class="w-full px-2 py-3 overflow-hidden relative border-b border-white border-opacity-10" @mouseover="mouseover" @mouseleave="mouseleave">
|
||||||
<div v-if="episode" class="flex items-center h-24">
|
<div v-if="episode" class="flex items-center h-24">
|
||||||
<div v-show="userCanUpdate" class="w-12 min-w-12 max-w-16 h-full">
|
|
||||||
<div class="flex h-full items-center justify-center">
|
|
||||||
<span class="material-icons drag-handle text-lg text-white text-opacity-50 hover:text-opacity-100">menu</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex-grow px-2">
|
<div class="flex-grow px-2">
|
||||||
<p class="text-sm font-semibold">
|
<p class="text-sm font-semibold">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
@ -49,8 +44,8 @@ export default {
|
|||||||
episode: {
|
episode: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {}
|
default: () => {}
|
||||||
},
|
}
|
||||||
isDragging: Boolean
|
// isDragging: Boolean
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -59,15 +54,15 @@ export default {
|
|||||||
isHovering: false
|
isHovering: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
// watch: {
|
||||||
isDragging: {
|
// isDragging: {
|
||||||
handler(newVal) {
|
// handler(newVal) {
|
||||||
if (newVal) {
|
// if (newVal) {
|
||||||
this.isHovering = false
|
// this.isHovering = false
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
computed: {
|
computed: {
|
||||||
userCanUpdate() {
|
userCanUpdate() {
|
||||||
return this.$store.getters['user/getUserCanUpdate']
|
return this.$store.getters['user/getUserCanUpdate']
|
||||||
@ -117,7 +112,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
mouseover() {
|
mouseover() {
|
||||||
if (this.isDragging) return
|
// if (this.isDragging) return
|
||||||
this.isHovering = true
|
this.isHovering = true
|
||||||
},
|
},
|
||||||
mouseleave() {
|
mouseleave() {
|
||||||
|
@ -9,23 +9,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="!episodes.length" class="py-4 text-center text-lg">No Episodes</p>
|
<p v-if="!episodes.length" class="py-4 text-center text-lg">No Episodes</p>
|
||||||
<draggable v-model="episodesCopy" v-bind="dragOptions" class="list-group" handle=".drag-handle" draggable=".item" tag="div" @start="drag = true" @end="drag = false" @update="draggableUpdate">
|
<template v-for="episode in episodes">
|
||||||
<transition-group type="transition" :name="!drag ? 'episode' : null">
|
<tables-podcast-episode-table-row :key="episode.id" :episode="episode" :library-item-id="libraryItem.id" class="item" @edit="editEpisode" />
|
||||||
<template v-for="episode in episodesCopy">
|
</template>
|
||||||
<tables-podcast-episode-table-row :key="episode.id" :is-dragging="drag" :episode="episode" :library-item-id="libraryItem.id" class="item" :class="drag ? '' : 'episode'" @edit="editEpisode" />
|
|
||||||
</template>
|
|
||||||
</transition-group>
|
|
||||||
</draggable>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import draggable from 'vuedraggable'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
|
||||||
draggable
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
libraryItem: {
|
libraryItem: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -34,30 +25,11 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
sortKey: 'index',
|
sortKey: 'publishedAt',
|
||||||
sortDesc: true,
|
sortDesc: true
|
||||||
drag: false,
|
|
||||||
episodesCopy: [],
|
|
||||||
orderChanged: false,
|
|
||||||
savingOrder: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
libraryItem: {
|
|
||||||
handler(newVal) {
|
|
||||||
this.init()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
dragOptions() {
|
|
||||||
return {
|
|
||||||
animation: 200,
|
|
||||||
group: 'description',
|
|
||||||
ghostClass: 'ghost',
|
|
||||||
disabled: !this.userCanUpdate
|
|
||||||
}
|
|
||||||
},
|
|
||||||
userCanUpdate() {
|
userCanUpdate() {
|
||||||
return this.$store.getters['user/getUserCanUpdate']
|
return this.$store.getters['user/getUserCanUpdate']
|
||||||
},
|
},
|
||||||
@ -72,66 +44,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
changeSort() {
|
|
||||||
this.episodesCopy.sort((a, b) => {
|
|
||||||
if (this.sortDesc) {
|
|
||||||
return String(b[this.sortKey]).localeCompare(String(a[this.sortKey]), undefined, { numeric: true, sensitivity: 'base' })
|
|
||||||
}
|
|
||||||
return String(a[this.sortKey]).localeCompare(String(b[this.sortKey]), undefined, { numeric: true, sensitivity: 'base' })
|
|
||||||
})
|
|
||||||
|
|
||||||
this.orderChanged = this.checkHasOrderChanged()
|
|
||||||
},
|
|
||||||
checkHasOrderChanged() {
|
|
||||||
for (let i = 0; i < this.episodesCopy.length; i++) {
|
|
||||||
var epc = this.episodesCopy[i]
|
|
||||||
var ep = this.episodes[i]
|
|
||||||
if (epc.index != ep.index) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
editEpisode(episode) {
|
editEpisode(episode) {
|
||||||
this.$store.commit('setSelectedLibraryItem', this.libraryItem)
|
this.$store.commit('setSelectedLibraryItem', this.libraryItem)
|
||||||
this.$store.commit('globals/setSelectedEpisode', episode)
|
this.$store.commit('globals/setSelectedEpisode', episode)
|
||||||
this.$store.commit('globals/setShowEditPodcastEpisodeModal', true)
|
this.$store.commit('globals/setShowEditPodcastEpisodeModal', true)
|
||||||
},
|
|
||||||
draggableUpdate() {
|
|
||||||
this.orderChanged = this.checkHasOrderChanged()
|
|
||||||
},
|
|
||||||
async saveOrder() {
|
|
||||||
if (!this.userCanUpdate) return
|
|
||||||
|
|
||||||
this.savingOrder = true
|
|
||||||
|
|
||||||
var episodesUpdate = {
|
|
||||||
episodes: this.episodesCopy.map((b) => b.id)
|
|
||||||
}
|
|
||||||
await this.$axios
|
|
||||||
.$patch(`/api/items/${this.libraryItem.id}/episodes`, episodesUpdate)
|
|
||||||
.then((podcast) => {
|
|
||||||
console.log('Podcast updated', podcast)
|
|
||||||
this.$toast.success('Saved episode order')
|
|
||||||
this.orderChanged = false
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error('Failed to update podcast', error)
|
|
||||||
this.$toast.error('Failed to save podcast episode order')
|
|
||||||
})
|
|
||||||
this.savingOrder = false
|
|
||||||
},
|
|
||||||
init() {
|
|
||||||
this.episodesCopy = this.episodes.map((ep) => {
|
|
||||||
return {
|
|
||||||
...ep
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {}
|
||||||
this.init()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -224,20 +224,6 @@ class LibraryItemController {
|
|||||||
res.json(libraryItem.toJSON())
|
res.json(libraryItem.toJSON())
|
||||||
}
|
}
|
||||||
|
|
||||||
// PATCH: api/items/:id/episodes
|
|
||||||
async updateEpisodes(req, res) { // For updating podcast episode order
|
|
||||||
var libraryItem = req.libraryItem
|
|
||||||
var orderedFileData = req.body.episodes
|
|
||||||
if (!libraryItem.media.setEpisodeOrder) {
|
|
||||||
Logger.error(`[LibraryItemController] updateEpisodes invalid media type ${libraryItem.id}`)
|
|
||||||
return res.sendStatus(500)
|
|
||||||
}
|
|
||||||
libraryItem.media.setEpisodeOrder(orderedFileData)
|
|
||||||
await this.db.updateLibraryItem(libraryItem)
|
|
||||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
|
||||||
res.json(libraryItem.toJSON())
|
|
||||||
}
|
|
||||||
|
|
||||||
// DELETE: api/items/:id/episode/:episodeId
|
// DELETE: api/items/:id/episode/:episodeId
|
||||||
async removeEpisode(req, res) {
|
async removeEpisode(req, res) {
|
||||||
var episodeId = req.params.episodeId
|
var episodeId = req.params.episodeId
|
||||||
|
@ -224,18 +224,10 @@ class Podcast {
|
|||||||
this.episodes.push(pe)
|
this.episodes.push(pe)
|
||||||
}
|
}
|
||||||
|
|
||||||
setEpisodeOrder(episodeIds) {
|
|
||||||
episodeIds.reverse() // episode Ids will already be in descending order
|
|
||||||
this.episodes = this.episodes.map(ep => {
|
|
||||||
var indexOf = episodeIds.findIndex(id => id === ep.id)
|
|
||||||
ep.index = indexOf + 1
|
|
||||||
return ep
|
|
||||||
})
|
|
||||||
this.episodes.sort((a, b) => b.index - a.index)
|
|
||||||
}
|
|
||||||
|
|
||||||
reorderEpisodes() {
|
reorderEpisodes() {
|
||||||
var hasUpdates = false
|
var hasUpdates = false
|
||||||
|
|
||||||
|
// TODO: Sort by published date
|
||||||
this.episodes = naturalSort(this.episodes).asc((ep) => ep.bestFilename)
|
this.episodes = naturalSort(this.episodes).asc((ep) => ep.bestFilename)
|
||||||
for (let i = 0; i < this.episodes.length; i++) {
|
for (let i = 0; i < this.episodes.length; i++) {
|
||||||
if (this.episodes[i].index !== (i + 1)) {
|
if (this.episodes[i].index !== (i + 1)) {
|
||||||
|
@ -90,7 +90,6 @@ class ApiRouter {
|
|||||||
this.router.post('/items/:id/play', LibraryItemController.middleware.bind(this), LibraryItemController.startPlaybackSession.bind(this))
|
this.router.post('/items/:id/play', LibraryItemController.middleware.bind(this), LibraryItemController.startPlaybackSession.bind(this))
|
||||||
this.router.post('/items/:id/play/:episodeId', LibraryItemController.middleware.bind(this), LibraryItemController.startEpisodePlaybackSession.bind(this))
|
this.router.post('/items/:id/play/:episodeId', LibraryItemController.middleware.bind(this), LibraryItemController.startEpisodePlaybackSession.bind(this))
|
||||||
this.router.patch('/items/:id/tracks', LibraryItemController.middleware.bind(this), LibraryItemController.updateTracks.bind(this))
|
this.router.patch('/items/:id/tracks', LibraryItemController.middleware.bind(this), LibraryItemController.updateTracks.bind(this))
|
||||||
this.router.patch('/items/:id/episodes', LibraryItemController.middleware.bind(this), LibraryItemController.updateEpisodes.bind(this))
|
|
||||||
this.router.delete('/items/:id/episode/:episodeId', LibraryItemController.middleware.bind(this), LibraryItemController.removeEpisode.bind(this))
|
this.router.delete('/items/:id/episode/:episodeId', LibraryItemController.middleware.bind(this), LibraryItemController.removeEpisode.bind(this))
|
||||||
this.router.get('/items/:id/scan', LibraryItemController.middleware.bind(this), LibraryItemController.scan.bind(this))
|
this.router.get('/items/:id/scan', LibraryItemController.middleware.bind(this), LibraryItemController.scan.bind(this))
|
||||||
this.router.get('/items/:id/audio-metadata', LibraryItemController.middleware.bind(this), LibraryItemController.updateAudioFileMetadata.bind(this))
|
this.router.get('/items/:id/audio-metadata', LibraryItemController.middleware.bind(this), LibraryItemController.updateAudioFileMetadata.bind(this))
|
||||||
|
Loading…
Reference in New Issue
Block a user