179 lines
5.5 KiB
Vue
179 lines
5.5 KiB
Vue
<template>
|
|
<div>
|
|
<div class="flex flex-wrap">
|
|
<div class="w-1/5 p-1">
|
|
<ui-text-input-with-label v-model="newEpisode.season" :label="$strings.LabelSeason" />
|
|
</div>
|
|
<div class="w-1/5 p-1">
|
|
<ui-text-input-with-label v-model="newEpisode.episode" :label="$strings.LabelEpisode" />
|
|
</div>
|
|
<div class="w-1/5 p-1">
|
|
<ui-dropdown v-model="newEpisode.episodeType" :label="$strings.LabelEpisodeType" :items="episodeTypes" small />
|
|
</div>
|
|
<div class="w-2/5 p-1">
|
|
<ui-text-input-with-label v-model="pubDateInput" @input="updatePubDate" type="datetime-local" :label="$strings.LabelPubDate" />
|
|
</div>
|
|
<div class="w-full p-1">
|
|
<ui-text-input-with-label v-model="newEpisode.title" :label="$strings.LabelTitle" />
|
|
</div>
|
|
<div class="w-full p-1">
|
|
<ui-textarea-with-label v-model="newEpisode.subtitle" :label="$strings.LabelSubtitle" :rows="3" />
|
|
</div>
|
|
<div class="w-full p-1">
|
|
<ui-rich-text-editor :label="$strings.LabelDescription" v-model="newEpisode.description" />
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center justify-end pt-4">
|
|
<!-- desktop -->
|
|
<ui-btn @click="submit" class="mx-2 hidden md:block">{{ $strings.ButtonSave }}</ui-btn>
|
|
<ui-btn @click="saveAndClose" class="mx-2 hidden md:block">{{ $strings.ButtonSaveAndClose }}</ui-btn>
|
|
|
|
<!-- mobile -->
|
|
<ui-btn @click="saveAndClose" class="mx-2 md:hidden">{{ $strings.ButtonSave }}</ui-btn>
|
|
</div>
|
|
<div v-if="enclosureUrl" class="pb-4 pt-6">
|
|
<ui-text-input-with-label :value="enclosureUrl" readonly class="text-xs">
|
|
<label class="px-1 text-xs text-gray-200 font-semibold">{{ $strings.LabelEpisodeUrlFromRssFeed }}</label>
|
|
</ui-text-input-with-label>
|
|
</div>
|
|
<div v-else class="py-4">
|
|
<p class="text-xs text-gray-300 font-semibold">{{ $strings.LabelEpisodeNotLinkedToRssFeed }}</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
props: {
|
|
processing: Boolean,
|
|
libraryItem: {
|
|
type: Object,
|
|
default: () => {}
|
|
},
|
|
episode: {
|
|
type: Object,
|
|
default: () => {}
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
newEpisode: {
|
|
season: null,
|
|
episode: null,
|
|
episodeType: null,
|
|
title: null,
|
|
subtitle: null,
|
|
description: null,
|
|
pubDate: null,
|
|
publishedAt: null
|
|
},
|
|
pubDateInput: null
|
|
}
|
|
},
|
|
watch: {
|
|
episode: {
|
|
immediate: true,
|
|
handler(newVal) {
|
|
if (newVal) this.init()
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
isProcessing: {
|
|
get() {
|
|
return this.processing
|
|
},
|
|
set(val) {
|
|
this.$emit('update:processing', val)
|
|
}
|
|
},
|
|
episodeId() {
|
|
return this.episode ? this.episode.id : null
|
|
},
|
|
enclosure() {
|
|
return this.episode ? this.episode.enclosure || {} : {}
|
|
},
|
|
enclosureUrl() {
|
|
return this.enclosure.url
|
|
},
|
|
episodeTypes() {
|
|
return this.$store.state.globals.episodeTypes.map((e) => {
|
|
return {
|
|
text: this.$strings[e.descriptionKey] || e.text,
|
|
value: e.value
|
|
}
|
|
})
|
|
}
|
|
},
|
|
methods: {
|
|
updatePubDate(val) {
|
|
if (val) {
|
|
this.newEpisode.pubDate = this.$formatJsDate(new Date(val), 'E, d MMM yyyy HH:mm:ssxx')
|
|
this.newEpisode.publishedAt = new Date(val).valueOf()
|
|
} else {
|
|
this.newEpisode.pubDate = null
|
|
this.newEpisode.publishedAt = null
|
|
}
|
|
},
|
|
init() {
|
|
this.newEpisode.season = this.episode.season || ''
|
|
this.newEpisode.episode = this.episode.episode || ''
|
|
this.newEpisode.episodeType = this.episode.episodeType || ''
|
|
this.newEpisode.title = this.episode.title || ''
|
|
this.newEpisode.subtitle = this.episode.subtitle || ''
|
|
this.newEpisode.description = this.episode.description || ''
|
|
this.newEpisode.pubDate = this.episode.pubDate || ''
|
|
this.newEpisode.publishedAt = this.episode.publishedAt
|
|
|
|
this.pubDateInput = this.episode.pubDate ? this.$formatJsDate(new Date(this.episode.pubDate), "yyyy-MM-dd'T'HH:mm") : null
|
|
},
|
|
getUpdatePayload() {
|
|
var updatePayload = {}
|
|
for (const key in this.newEpisode) {
|
|
if (this.newEpisode[key] != this.episode[key]) {
|
|
updatePayload[key] = this.newEpisode[key]
|
|
}
|
|
}
|
|
return updatePayload
|
|
},
|
|
async saveAndClose() {
|
|
const wasUpdated = await this.submit()
|
|
if (wasUpdated !== null) this.$emit('close')
|
|
},
|
|
async submit() {
|
|
if (this.isProcessing) {
|
|
return null
|
|
}
|
|
|
|
const updatedDetails = this.getUpdatePayload()
|
|
if (!Object.keys(updatedDetails).length) {
|
|
this.$toast.info(this.$strings.ToastNoUpdatesNecessary)
|
|
return false
|
|
}
|
|
return this.updateDetails(updatedDetails)
|
|
},
|
|
async updateDetails(updatedDetails) {
|
|
this.isProcessing = true
|
|
const updateResult = await this.$axios.$patch(`/api/podcasts/${this.libraryItem.id}/episode/${this.episodeId}`, updatedDetails).catch((error) => {
|
|
console.error('Failed update episode', error)
|
|
this.isProcessing = false
|
|
this.$toast.error(error?.response?.data || this.$strings.ToastFailedToUpdate)
|
|
return false
|
|
})
|
|
|
|
this.isProcessing = false
|
|
if (updateResult) {
|
|
if (updateResult) {
|
|
this.$toast.success(this.$strings.ToastItemUpdateSuccess)
|
|
return true
|
|
} else {
|
|
this.$toast.info(this.$strings.MessageNoUpdatesWereNecessary)
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
},
|
|
mounted() {}
|
|
}
|
|
</script>
|