mirror of
https://github.com/AzuraCast/AzuraCast.git
synced 2024-06-14 13:16:37 +00:00
Add "Source" tab to Podcast modal and wire up select API request.
This commit is contained in:
parent
b0ab0916ae
commit
e3dfe85653
|
@ -125,6 +125,9 @@ return static function (RouteCollectorProxy $group) {
|
||||||
$group->post('/podcasts/art', Controller\Api\Stations\Podcasts\Art\PostArtAction::class)
|
$group->post('/podcasts/art', Controller\Api\Stations\Podcasts\Art\PostArtAction::class)
|
||||||
->setName('api:stations:podcasts:new-art');
|
->setName('api:stations:podcasts:new-art');
|
||||||
|
|
||||||
|
$group->get('/podcasts/playlists', Controller\Api\Stations\Podcasts\PlaylistsAction::class)
|
||||||
|
->setName('api:stations:podcasts:playlists');
|
||||||
|
|
||||||
$group->group(
|
$group->group(
|
||||||
'/podcast/{podcast_id}',
|
'/podcast/{podcast_id}',
|
||||||
function (RouteCollectorProxy $group) {
|
function (RouteCollectorProxy $group) {
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
:language-options="languageOptions"
|
:language-options="languageOptions"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<podcast-form-source
|
||||||
|
:form="form"
|
||||||
|
/>
|
||||||
|
|
||||||
<podcast-common-artwork
|
<podcast-common-artwork
|
||||||
v-model="form.artwork_file"
|
v-model="form.artwork_file"
|
||||||
:artwork-src="record.links.art"
|
:artwork-src="record.links.art"
|
||||||
|
@ -26,6 +30,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import PodcastFormBasicInfo from './PodcastForm/BasicInfo.vue';
|
import PodcastFormBasicInfo from './PodcastForm/BasicInfo.vue';
|
||||||
|
import PodcastFormSource from './PodcastForm/Source.vue';
|
||||||
import PodcastCommonArtwork from './Common/Artwork.vue';
|
import PodcastCommonArtwork from './Common/Artwork.vue';
|
||||||
import mergeExisting from "~/functions/mergeExisting";
|
import mergeExisting from "~/functions/mergeExisting";
|
||||||
import {baseEditModalProps, ModalFormTemplateRef, useBaseEditModal} from "~/functions/useBaseEditModal";
|
import {baseEditModalProps, ModalFormTemplateRef, useBaseEditModal} from "~/functions/useBaseEditModal";
|
||||||
|
|
128
frontend/src/components/Stations/Podcasts/PodcastForm/Source.vue
Normal file
128
frontend/src/components/Stations/Podcasts/PodcastForm/Source.vue
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
<template>
|
||||||
|
<tab
|
||||||
|
:label="$gettext('Source')"
|
||||||
|
:item-header-class="tabClass"
|
||||||
|
>
|
||||||
|
<div class="row g-3">
|
||||||
|
<form-group-multi-check
|
||||||
|
id="edit_form_source"
|
||||||
|
class="col-md-12"
|
||||||
|
:field="v$.source"
|
||||||
|
:options="sourceOptions"
|
||||||
|
stacked
|
||||||
|
radio
|
||||||
|
:label="$gettext('Source')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section
|
||||||
|
v-show="form.source === 'playlist'"
|
||||||
|
class="card mb-3"
|
||||||
|
role="region"
|
||||||
|
>
|
||||||
|
<div class="card-header text-bg-primary">
|
||||||
|
<h2 class="card-title">
|
||||||
|
{{ $gettext('Playlist-Based Podcast') }}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p>
|
||||||
|
{{
|
||||||
|
$gettext('Playlist-based podcasts will automatically sync with the contents of a playlist, creating new podcast episodes for any media added to the playlist.')
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<loading :loading="playlistsLoading">
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<form-group-select
|
||||||
|
id="form_edit_playlist_id"
|
||||||
|
class="col-md-12"
|
||||||
|
:field="v$.playlist_id"
|
||||||
|
:options="playlistOptions"
|
||||||
|
:label="$gettext('Select Playlist')"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<form-group-checkbox
|
||||||
|
id="form_edit_playlist_auto_publish"
|
||||||
|
class="col-md-12"
|
||||||
|
:field="v$.playlist_auto_publish"
|
||||||
|
:label="$gettext('Automatically Publish New Episodes')"
|
||||||
|
:description="$gettext('Whether new episodes should be marked as published or held for review as unpublished.')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</loading>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</tab>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import FormGroupSelect from "~/components/Form/FormGroupSelect.vue";
|
||||||
|
import {useVModel} from "@vueuse/core";
|
||||||
|
import {useVuelidateOnFormTab} from "~/functions/useVuelidateOnFormTab";
|
||||||
|
import {required} from "@vuelidate/validators";
|
||||||
|
import Tab from "~/components/Common/Tab.vue";
|
||||||
|
import FormGroupMultiCheck from "~/components/Form/FormGroupMultiCheck.vue";
|
||||||
|
import FormGroupCheckbox from "~/components/Form/FormGroupCheckbox.vue";
|
||||||
|
import {useTranslate} from "~/vendor/gettext.ts";
|
||||||
|
import {onMounted, ref, shallowRef} from "vue";
|
||||||
|
import {useAxios} from "~/vendor/axios.ts";
|
||||||
|
import objectToFormOptions from "~/functions/objectToFormOptions.ts";
|
||||||
|
import {getStationApiUrl} from "~/router.ts";
|
||||||
|
import Loading from "~/components/Common/Loading.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
form: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:form']);
|
||||||
|
const form = useVModel(props, 'form', emit);
|
||||||
|
|
||||||
|
const {v$, tabClass} = useVuelidateOnFormTab(
|
||||||
|
{
|
||||||
|
source: {required},
|
||||||
|
playlist_id: {},
|
||||||
|
playlist_auto_publish: {}
|
||||||
|
},
|
||||||
|
form,
|
||||||
|
{
|
||||||
|
source: 'manual',
|
||||||
|
playlist_id: null,
|
||||||
|
playlist_auto_publish: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const {$gettext} = useTranslate();
|
||||||
|
|
||||||
|
const sourceOptions = [
|
||||||
|
{
|
||||||
|
value: 'manual',
|
||||||
|
text: $gettext('Manually Add Episodes'),
|
||||||
|
description: $gettext('Create podcast episodes independent of your station\'s media collection.')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'playlist',
|
||||||
|
text: $gettext('Synchronize with Playlist'),
|
||||||
|
description: $gettext('Automatically create new podcast episodes when media is added to a specified playlist.')
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const playlistsLoading = ref(true);
|
||||||
|
const playlistOptions = shallowRef([]);
|
||||||
|
|
||||||
|
const {axios} = useAxios();
|
||||||
|
const playlistsApiUrl = getStationApiUrl('/podcasts/playlists');
|
||||||
|
|
||||||
|
const loadPlaylists = () => {
|
||||||
|
axios.get(playlistsApiUrl.value).then((resp) => {
|
||||||
|
playlistOptions.value = objectToFormOptions(resp.data);
|
||||||
|
}).finally(() => {
|
||||||
|
playlistsLoading.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(loadPlaylists);
|
||||||
|
</script>
|
38
src/Controller/Api/Stations/Podcasts/PlaylistsAction.php
Normal file
38
src/Controller/Api/Stations/Podcasts/PlaylistsAction.php
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Controller\Api\Stations\Podcasts;
|
||||||
|
|
||||||
|
use App\Container\EntityManagerAwareTrait;
|
||||||
|
use App\Controller\SingleActionInterface;
|
||||||
|
use App\Entity\Enums\PlaylistSources;
|
||||||
|
use App\Http\Response;
|
||||||
|
use App\Http\ServerRequest;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
|
||||||
|
final class PlaylistsAction implements SingleActionInterface
|
||||||
|
{
|
||||||
|
use EntityManagerAwareTrait;
|
||||||
|
|
||||||
|
public function __invoke(
|
||||||
|
ServerRequest $request,
|
||||||
|
Response $response,
|
||||||
|
array $params
|
||||||
|
): ResponseInterface {
|
||||||
|
$playlistsRaw = $this->em->createQuery(
|
||||||
|
<<<'DQL'
|
||||||
|
SELECT sp.id, sp.name
|
||||||
|
FROM App\Entity\StationPlaylist sp
|
||||||
|
WHERE sp.station = :station
|
||||||
|
AND sp.source = :sourceSongs
|
||||||
|
DQL
|
||||||
|
)->setParameter('station', $request->getStation())
|
||||||
|
->setParameter('sourceSongs', PlaylistSources::Songs->value)
|
||||||
|
->getArrayResult();
|
||||||
|
|
||||||
|
return $response->withJson(
|
||||||
|
array_column($playlistsRaw, 'name', 'id')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -302,6 +302,12 @@ final class PodcastsController extends AbstractApiCrudController
|
||||||
unset($data['categories']);
|
unset($data['categories']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($data['playlist_id'])) {
|
||||||
|
$data['playlist'] = $data['playlist_id'];
|
||||||
|
unset($data['playlist_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$record = parent::fromArray($data, $record, $context);
|
$record = parent::fromArray($data, $record, $context);
|
||||||
|
|
||||||
if (null !== $newCategories) {
|
if (null !== $newCategories) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user