Update API interface and wire up Podcast Episodes for playlist-synced podcasts.

This commit is contained in:
Buster Neece 2024-03-03 13:32:08 -06:00
parent 8fa8ab7e26
commit 09d186d506
No known key found for this signature in database
5 changed files with 61 additions and 27 deletions

View File

@ -1,9 +1,6 @@
<template>
<section
class="card"
role="region"
>
<div class="card-header text-bg-primary">
<card-page>
<template #header>
<div class="row align-items-center">
<div class="col-md-7">
<div class="d-flex align-items-center">
@ -27,9 +24,18 @@
/>
</div>
</div>
</div>
<div class="card-body buttons">
</template>
<template
v-if="!podcastIsManual"
#info
>
<p class="card-text">
{{
$gettext('This podcast is automatically synchronized with a playlist. Episodes cannot be manually added or removed via this panel.')
}}
</p>
</template>
<template #actions>
<router-link
class="btn btn-secondary"
:to="{name: 'stations:podcasts:index'}"
@ -39,10 +45,11 @@
</router-link>
<add-button
v-if="podcastIsManual"
:text="$gettext('Add Episode')"
@click="doCreate"
/>
</div>
</template>
<data-table
id="station_podcast_episodes"
@ -74,12 +81,18 @@
</span>
</div>
</template>
<template #cell(podcast_media)="{item}">
<template #cell(media)="{item}">
<template v-if="item.media">
<span>{{ item.media.original_name }}</span>
<br>
<small>{{ item.media.length_text }}</small>
</template>
<template v-else-if="item.playlist_media">
<span>{{ item.playlist_media.text }}</span>
</template>
<template v-else>
&nbsp;
</template>
</template>
<template #cell(is_published)="{item}">
<span v-if="item.is_published">
@ -106,6 +119,7 @@
{{ $gettext('Edit') }}
</button>
<button
v-if="podcastIsManual"
type="button"
class="btn btn-danger"
@click="doDelete(item.links.self)"
@ -115,14 +129,12 @@
</div>
</template>
</data-table>
</section>
</card-page>
<edit-modal
ref="$editEpisodeModal"
:podcast="podcast"
:create-url="podcast.links.episodes"
:new-art-url="podcast.links.episode_new_art"
:new-media-url="podcast.links.episode_new_media"
:podcast-id="podcast.id"
@relist="relist"
/>
</template>
@ -134,7 +146,7 @@ import Icon from '~/components/Common/Icon.vue';
import AlbumArt from '~/components/Common/AlbumArt.vue';
import StationsCommonQuota from "~/components/Stations/Common/Quota.vue";
import {useTranslate} from "~/vendor/gettext";
import {ref} from "vue";
import {computed, ref} from "vue";
import AddButton from "~/components/Common/AddButton.vue";
import {IconChevronLeft} from "~/components/Common/icons";
import useHasDatatable, {DataTableTemplateRef} from "~/functions/useHasDatatable.ts";
@ -143,6 +155,7 @@ import useConfirmAndDelete from "~/functions/useConfirmAndDelete.ts";
import {ApiPodcast} from "~/entities/ApiInterfaces.ts";
import useHasEditModal from "~/functions/useHasEditModal.ts";
import useStationDateTimeFormatter from "~/functions/useStationDateTimeFormatter.ts";
import CardPage from "~/components/Common/CardPage.vue";
const props = defineProps<{
podcast: ApiPodcast
@ -168,7 +181,7 @@ const fields: DataTableField[] = [
sortable: false
},
{
key: 'podcast_media',
key: 'media',
label: $gettext('File Name'),
sortable: false
},
@ -200,6 +213,10 @@ const fields: DataTableField[] = [
}
];
const podcastIsManual = computed(() => {
return props.podcast.source == 'manual';
});
const $quota = ref<InstanceType<typeof StationsCommonQuota> | null>(null);
const $datatable = ref<DataTableTemplateRef>(null);

View File

@ -14,6 +14,7 @@
/>
<episode-form-media
v-if="podcastIsManual"
v-model="form.media_file"
:record-has-media="record.has_media"
:new-media-url="newMediaUrl"
@ -44,20 +45,18 @@ import Tabs from "~/components/Common/Tabs.vue";
const props = defineProps({
...baseEditModalProps,
podcastId: {
type: String,
required: true
},
newArtUrl: {
type: String,
required: true
},
newMediaUrl: {
type: String,
podcast: {
type: Object,
required: true
}
});
const newArtUrl = computed(() => props.podcast.links.episode_new_art);
const newMediaUrl = computed(() => props.podcast.links.episode_new_media);
const podcastIsManual = computed(() => {
return props.podcast.source == 'manual';
});
const emit = defineEmits(['relist']);
const $modal = ref<ModalFormTemplateRef>(null);

View File

@ -604,6 +604,9 @@ export interface ApiNowPlayingStationRemote {
export type ApiPodcast = HasLinks & {
id?: string;
storage_location_id?: number;
source?: string;
playlist_id?: number | null;
playlist_auto_publish?: boolean;
title?: string;
link?: string | null;
description?: string;
@ -637,7 +640,9 @@ export type ApiPodcastEpisode = HasLinks & {
is_published?: boolean;
publish_at?: number | null;
has_media?: boolean;
media?: ApiPodcastMedia;
playlist_media_id?: string | null;
playlist_media?: ApiSong | null;
media?: ApiPodcastMedia | null;
has_custom_art?: boolean;
art?: string | null;
art_updated_at?: number;

View File

@ -45,6 +45,9 @@ final class PodcastEpisode
#[OA\Property]
public ?string $playlist_media_id = null;
#[OA\Property]
public ?Song $playlist_media = null;
#[OA\Property]
public ?PodcastMedia $media = null;

View File

@ -15,6 +15,11 @@ use App\Utilities\Strings;
final class PodcastEpisodeApiGenerator
{
public function __construct(
private readonly SongApiGenerator $songApiGen
) {
}
public function __invoke(
PodcastEpisode $record,
ServerRequest $request
@ -43,14 +48,19 @@ final class PodcastEpisodeApiGenerator
$playlistMediaRow = $record->getPlaylistMedia();
if ($playlistMediaRow instanceof StationMedia) {
$return->has_media = true;
$return->playlist_media = $this->songApiGen->__invoke($playlistMediaRow);
$return->playlist_media_id = $playlistMediaRow->getUniqueId();
} else {
$return->has_media = false;
$return->playlist_media = null;
$return->playlist_media_id = null;
}
break;
case PodcastSources::Manual:
$return->playlist_media = null;
$return->playlist_media_id = null;
$mediaRow = $record->getMedia();