mirror of
https://github.com/AzuraCast/AzuraCast.git
synced 2024-06-17 22:47:04 +00:00
Update API interface and wire up Podcast Episodes for playlist-synced podcasts.
This commit is contained in:
parent
8fa8ab7e26
commit
09d186d506
|
@ -1,9 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<section
|
<card-page>
|
||||||
class="card"
|
<template #header>
|
||||||
role="region"
|
|
||||||
>
|
|
||||||
<div class="card-header text-bg-primary">
|
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
|
@ -27,9 +24,18 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
<template
|
||||||
<div class="card-body buttons">
|
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
|
<router-link
|
||||||
class="btn btn-secondary"
|
class="btn btn-secondary"
|
||||||
:to="{name: 'stations:podcasts:index'}"
|
:to="{name: 'stations:podcasts:index'}"
|
||||||
|
@ -39,10 +45,11 @@
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<add-button
|
<add-button
|
||||||
|
v-if="podcastIsManual"
|
||||||
:text="$gettext('Add Episode')"
|
:text="$gettext('Add Episode')"
|
||||||
@click="doCreate"
|
@click="doCreate"
|
||||||
/>
|
/>
|
||||||
</div>
|
</template>
|
||||||
|
|
||||||
<data-table
|
<data-table
|
||||||
id="station_podcast_episodes"
|
id="station_podcast_episodes"
|
||||||
|
@ -74,12 +81,18 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #cell(podcast_media)="{item}">
|
<template #cell(media)="{item}">
|
||||||
<template v-if="item.media">
|
<template v-if="item.media">
|
||||||
<span>{{ item.media.original_name }}</span>
|
<span>{{ item.media.original_name }}</span>
|
||||||
<br>
|
<br>
|
||||||
<small>{{ item.media.length_text }}</small>
|
<small>{{ item.media.length_text }}</small>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="item.playlist_media">
|
||||||
|
<span>{{ item.playlist_media.text }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template #cell(is_published)="{item}">
|
<template #cell(is_published)="{item}">
|
||||||
<span v-if="item.is_published">
|
<span v-if="item.is_published">
|
||||||
|
@ -106,6 +119,7 @@
|
||||||
{{ $gettext('Edit') }}
|
{{ $gettext('Edit') }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
v-if="podcastIsManual"
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-danger"
|
class="btn btn-danger"
|
||||||
@click="doDelete(item.links.self)"
|
@click="doDelete(item.links.self)"
|
||||||
|
@ -115,14 +129,12 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</data-table>
|
</data-table>
|
||||||
</section>
|
</card-page>
|
||||||
|
|
||||||
<edit-modal
|
<edit-modal
|
||||||
ref="$editEpisodeModal"
|
ref="$editEpisodeModal"
|
||||||
|
:podcast="podcast"
|
||||||
:create-url="podcast.links.episodes"
|
: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"
|
@relist="relist"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -134,7 +146,7 @@ import Icon from '~/components/Common/Icon.vue';
|
||||||
import AlbumArt from '~/components/Common/AlbumArt.vue';
|
import AlbumArt from '~/components/Common/AlbumArt.vue';
|
||||||
import StationsCommonQuota from "~/components/Stations/Common/Quota.vue";
|
import StationsCommonQuota from "~/components/Stations/Common/Quota.vue";
|
||||||
import {useTranslate} from "~/vendor/gettext";
|
import {useTranslate} from "~/vendor/gettext";
|
||||||
import {ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
import AddButton from "~/components/Common/AddButton.vue";
|
import AddButton from "~/components/Common/AddButton.vue";
|
||||||
import {IconChevronLeft} from "~/components/Common/icons";
|
import {IconChevronLeft} from "~/components/Common/icons";
|
||||||
import useHasDatatable, {DataTableTemplateRef} from "~/functions/useHasDatatable.ts";
|
import useHasDatatable, {DataTableTemplateRef} from "~/functions/useHasDatatable.ts";
|
||||||
|
@ -143,6 +155,7 @@ import useConfirmAndDelete from "~/functions/useConfirmAndDelete.ts";
|
||||||
import {ApiPodcast} from "~/entities/ApiInterfaces.ts";
|
import {ApiPodcast} from "~/entities/ApiInterfaces.ts";
|
||||||
import useHasEditModal from "~/functions/useHasEditModal.ts";
|
import useHasEditModal from "~/functions/useHasEditModal.ts";
|
||||||
import useStationDateTimeFormatter from "~/functions/useStationDateTimeFormatter.ts";
|
import useStationDateTimeFormatter from "~/functions/useStationDateTimeFormatter.ts";
|
||||||
|
import CardPage from "~/components/Common/CardPage.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
podcast: ApiPodcast
|
podcast: ApiPodcast
|
||||||
|
@ -168,7 +181,7 @@ const fields: DataTableField[] = [
|
||||||
sortable: false
|
sortable: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'podcast_media',
|
key: 'media',
|
||||||
label: $gettext('File Name'),
|
label: $gettext('File Name'),
|
||||||
sortable: false
|
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 $quota = ref<InstanceType<typeof StationsCommonQuota> | null>(null);
|
||||||
|
|
||||||
const $datatable = ref<DataTableTemplateRef>(null);
|
const $datatable = ref<DataTableTemplateRef>(null);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<episode-form-media
|
<episode-form-media
|
||||||
|
v-if="podcastIsManual"
|
||||||
v-model="form.media_file"
|
v-model="form.media_file"
|
||||||
:record-has-media="record.has_media"
|
:record-has-media="record.has_media"
|
||||||
:new-media-url="newMediaUrl"
|
:new-media-url="newMediaUrl"
|
||||||
|
@ -44,20 +45,18 @@ import Tabs from "~/components/Common/Tabs.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
...baseEditModalProps,
|
...baseEditModalProps,
|
||||||
podcastId: {
|
podcast: {
|
||||||
type: String,
|
type: Object,
|
||||||
required: true
|
|
||||||
},
|
|
||||||
newArtUrl: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
newMediaUrl: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
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 emit = defineEmits(['relist']);
|
||||||
|
|
||||||
const $modal = ref<ModalFormTemplateRef>(null);
|
const $modal = ref<ModalFormTemplateRef>(null);
|
||||||
|
|
|
@ -604,6 +604,9 @@ export interface ApiNowPlayingStationRemote {
|
||||||
export type ApiPodcast = HasLinks & {
|
export type ApiPodcast = HasLinks & {
|
||||||
id?: string;
|
id?: string;
|
||||||
storage_location_id?: number;
|
storage_location_id?: number;
|
||||||
|
source?: string;
|
||||||
|
playlist_id?: number | null;
|
||||||
|
playlist_auto_publish?: boolean;
|
||||||
title?: string;
|
title?: string;
|
||||||
link?: string | null;
|
link?: string | null;
|
||||||
description?: string;
|
description?: string;
|
||||||
|
@ -637,7 +640,9 @@ export type ApiPodcastEpisode = HasLinks & {
|
||||||
is_published?: boolean;
|
is_published?: boolean;
|
||||||
publish_at?: number | null;
|
publish_at?: number | null;
|
||||||
has_media?: boolean;
|
has_media?: boolean;
|
||||||
media?: ApiPodcastMedia;
|
playlist_media_id?: string | null;
|
||||||
|
playlist_media?: ApiSong | null;
|
||||||
|
media?: ApiPodcastMedia | null;
|
||||||
has_custom_art?: boolean;
|
has_custom_art?: boolean;
|
||||||
art?: string | null;
|
art?: string | null;
|
||||||
art_updated_at?: number;
|
art_updated_at?: number;
|
||||||
|
|
|
@ -45,6 +45,9 @@ final class PodcastEpisode
|
||||||
#[OA\Property]
|
#[OA\Property]
|
||||||
public ?string $playlist_media_id = null;
|
public ?string $playlist_media_id = null;
|
||||||
|
|
||||||
|
#[OA\Property]
|
||||||
|
public ?Song $playlist_media = null;
|
||||||
|
|
||||||
#[OA\Property]
|
#[OA\Property]
|
||||||
public ?PodcastMedia $media = null;
|
public ?PodcastMedia $media = null;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,11 @@ use App\Utilities\Strings;
|
||||||
|
|
||||||
final class PodcastEpisodeApiGenerator
|
final class PodcastEpisodeApiGenerator
|
||||||
{
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly SongApiGenerator $songApiGen
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
public function __invoke(
|
public function __invoke(
|
||||||
PodcastEpisode $record,
|
PodcastEpisode $record,
|
||||||
ServerRequest $request
|
ServerRequest $request
|
||||||
|
@ -43,14 +48,19 @@ final class PodcastEpisodeApiGenerator
|
||||||
$playlistMediaRow = $record->getPlaylistMedia();
|
$playlistMediaRow = $record->getPlaylistMedia();
|
||||||
if ($playlistMediaRow instanceof StationMedia) {
|
if ($playlistMediaRow instanceof StationMedia) {
|
||||||
$return->has_media = true;
|
$return->has_media = true;
|
||||||
|
|
||||||
|
$return->playlist_media = $this->songApiGen->__invoke($playlistMediaRow);
|
||||||
$return->playlist_media_id = $playlistMediaRow->getUniqueId();
|
$return->playlist_media_id = $playlistMediaRow->getUniqueId();
|
||||||
} else {
|
} else {
|
||||||
$return->has_media = false;
|
$return->has_media = false;
|
||||||
|
|
||||||
|
$return->playlist_media = null;
|
||||||
$return->playlist_media_id = null;
|
$return->playlist_media_id = null;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PodcastSources::Manual:
|
case PodcastSources::Manual:
|
||||||
|
$return->playlist_media = null;
|
||||||
$return->playlist_media_id = null;
|
$return->playlist_media_id = null;
|
||||||
|
|
||||||
$mediaRow = $record->getMedia();
|
$mediaRow = $record->getMedia();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user