Add ability to clear upcoming song queue with single click.
This commit is contained in:
parent
a35e8bf27d
commit
8d3cab6e76
|
@ -5,6 +5,8 @@ release channel, you can take advantage of these new features and fixes.
|
|||
|
||||
## New Features/Changes
|
||||
|
||||
- You can now clear the entire upcoming song queue with a single button click.
|
||||
|
||||
## Code Quality/Technical Changes
|
||||
|
||||
- A number of security fixes are being incorporated into the software as of this version. See below for details.
|
||||
|
|
|
@ -240,6 +240,9 @@ return static function (RouteCollectorProxy $app) {
|
|||
$group->get('', Controller\Api\Stations\QueueController::class . ':listAction')
|
||||
->setName('api:stations:queue');
|
||||
|
||||
$group->post('/clear', Controller\Api\Stations\QueueController::class . ':clearAction')
|
||||
->setName('api:stations:queue:clear');
|
||||
|
||||
$group->get('/{id}', Controller\Api\Stations\QueueController::class . ':getAction')
|
||||
->setName('api:stations:queue:record');
|
||||
|
||||
|
|
|
@ -4,44 +4,49 @@
|
|||
<b-card-header header-bg-variant="primary-dark">
|
||||
<h2 class="card-title" key="lang_queue" v-translate>Upcoming Song Queue</h2>
|
||||
</b-card-header>
|
||||
<div class="pt-3">
|
||||
<data-table ref="datatable" id="station_queue" :fields="fields" :api-url="listUrl" handle-client-side>
|
||||
<template #cell(actions)="row">
|
||||
<b-button-group>
|
||||
<b-button v-if="row.item.log" size="sm" variant="primary" @click.prevent="doShowLogs(row.item.log)">
|
||||
<translate key="lang_btn_logs">Logs</translate>
|
||||
</b-button>
|
||||
<b-button size="sm" variant="danger" @click.prevent="doDelete(row.item.links.self)">
|
||||
<translate key="lang_btn_delete">Delete</translate>
|
||||
</b-button>
|
||||
</b-button-group>
|
||||
</template>
|
||||
<template #cell(song_title)="row">
|
||||
<div v-if="row.item.autodj_custom_uri">
|
||||
{{ row.item.autodj_custom_uri }}
|
||||
</div>
|
||||
<div v-else-if="row.item.song.title">
|
||||
<b>{{ row.item.song.title }}</b><br>
|
||||
{{ row.item.song.artist }}
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ row.item.song.text }}
|
||||
</div>
|
||||
</template>
|
||||
<template #cell(cued_at)="row">
|
||||
{{ formatTime(row.item.cued_at) }}
|
||||
</template>
|
||||
<template #cell(source)="row">
|
||||
<div v-if="row.item.is_request">
|
||||
<translate key="lang_source_request">Listener Request</translate>
|
||||
</div>
|
||||
<div v-else-if="row.item.playlist">
|
||||
<translate key="lang_source_playlist">Playlist: </translate>
|
||||
{{ row.item.playlist }}
|
||||
</div>
|
||||
</template>
|
||||
</data-table>
|
||||
<div class="card-actions">
|
||||
<b-button variant="outline-danger" @click="doClear()">
|
||||
<icon icon="remove"></icon>
|
||||
<translate key="lang_btn_clear_requests">Clear Upcoming Song Queue</translate>
|
||||
</b-button>
|
||||
</div>
|
||||
<data-table ref="datatable" id="station_queue" :fields="fields" :api-url="listUrl" handle-client-side>
|
||||
<template #cell(actions)="row">
|
||||
<b-button-group>
|
||||
<b-button v-if="row.item.log" size="sm" variant="primary"
|
||||
@click.prevent="doShowLogs(row.item.log)">
|
||||
<translate key="lang_btn_logs">Logs</translate>
|
||||
</b-button>
|
||||
<b-button size="sm" variant="danger" @click.prevent="doDelete(row.item.links.self)">
|
||||
<translate key="lang_btn_delete">Delete</translate>
|
||||
</b-button>
|
||||
</b-button-group>
|
||||
</template>
|
||||
<template #cell(song_title)="row">
|
||||
<div v-if="row.item.autodj_custom_uri">
|
||||
{{ row.item.autodj_custom_uri }}
|
||||
</div>
|
||||
<div v-else-if="row.item.song.title">
|
||||
<b>{{ row.item.song.title }}</b><br>
|
||||
{{ row.item.song.artist }}
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ row.item.song.text }}
|
||||
</div>
|
||||
</template>
|
||||
<template #cell(cued_at)="row">
|
||||
{{ formatTime(row.item.cued_at) }}
|
||||
</template>
|
||||
<template #cell(source)="row">
|
||||
<div v-if="row.item.is_request">
|
||||
<translate key="lang_source_request">Listener Request</translate>
|
||||
</div>
|
||||
<div v-else-if="row.item.playlist">
|
||||
<translate key="lang_source_playlist">Playlist: </translate>
|
||||
{{ row.item.playlist }}
|
||||
</div>
|
||||
</template>
|
||||
</data-table>
|
||||
</b-card>
|
||||
|
||||
<queue-logs-modal ref="logs_modal"></queue-logs-modal>
|
||||
|
@ -52,22 +57,24 @@
|
|||
import DataTable from '../Common/DataTable';
|
||||
import QueueLogsModal from './Queue/LogsModal';
|
||||
import handleAxiosError from '../Function/handleAxiosError';
|
||||
import Icon from "../Common/Icon";
|
||||
|
||||
export default {
|
||||
name: 'StationPlaylists',
|
||||
components: { QueueLogsModal, DataTable },
|
||||
components: {QueueLogsModal, DataTable, Icon},
|
||||
props: {
|
||||
listUrl: String,
|
||||
clearUrl: String,
|
||||
locale: String,
|
||||
stationTimeZone: String
|
||||
},
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
fields: [
|
||||
{ key: 'actions', label: this.$gettext('Actions'), sortable: false },
|
||||
{ key: 'song_title', isRowHeader: true, label: this.$gettext('Song Title'), sortable: false },
|
||||
{ key: 'cued_at', label: this.$gettext('Cued On'), sortable: false },
|
||||
{ key: 'source', label: this.$gettext('Source'), sortable: false }
|
||||
{key: 'actions', label: this.$gettext('Actions'), sortable: false},
|
||||
{key: 'song_title', isRowHeader: true, label: this.$gettext('Song Title'), sortable: false},
|
||||
{key: 'cued_at', label: this.$gettext('Cued On'), sortable: false},
|
||||
{key: 'source', label: this.$gettext('Source'), sortable: false}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
@ -99,6 +106,28 @@ export default {
|
|||
this.axios.delete(url).then((resp) => {
|
||||
notify('<b>' + resp.data.message + '</b>', 'success');
|
||||
|
||||
this.$refs.datatable.refresh();
|
||||
}).catch((err) => {
|
||||
handleAxiosError(err);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
doClear() {
|
||||
let buttonText = this.$gettext('Clear');
|
||||
let buttonConfirmText = this.$gettext('Clear upcoming song queue?');
|
||||
|
||||
Swal.fire({
|
||||
title: buttonConfirmText,
|
||||
confirmButtonText: buttonText,
|
||||
confirmButtonColor: '#e64942',
|
||||
showCancelButton: true,
|
||||
focusCancel: true
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
this.axios.post(this.clearUrl).then((resp) => {
|
||||
notify('<b>' + resp.data.message + '</b>', 'success');
|
||||
|
||||
this.$refs.datatable.refresh();
|
||||
}).catch((err) => {
|
||||
handleAxiosError(err);
|
||||
|
|
|
@ -134,4 +134,12 @@ class QueueController extends AbstractStationApiCrudController
|
|||
|
||||
return $apiResponse;
|
||||
}
|
||||
|
||||
public function clearAction(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$station = $request->getStation();
|
||||
$this->queueRepo->clearUpcomingQueue($station);
|
||||
|
||||
return $response->withJson(Entity\Api\Status::deleted());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,6 +96,18 @@ class StationQueueRepository extends Repository
|
|||
return $this->getUpcomingQuery($station)->execute();
|
||||
}
|
||||
|
||||
public function clearUpcomingQueue(Entity\Station $station): void
|
||||
{
|
||||
$this->em->createQuery(
|
||||
<<<'DQL'
|
||||
DELETE FROM App\Entity\StationQueue sq
|
||||
WHERE sq.station = :station
|
||||
AND sq.sent_to_autodj = 0
|
||||
DQL
|
||||
)->setParameter('station', $station)
|
||||
->execute();
|
||||
}
|
||||
|
||||
public function getUpcomingQuery(Entity\Station $station): Query
|
||||
{
|
||||
return $this->getUpcomingBaseQuery($station)->getQuery();
|
||||
|
|
|
@ -5,6 +5,7 @@ $this->layout('main', ['title' => __('Upcoming Song Queue'), 'manual' => true]);
|
|||
/** @var App\Http\RouterInterface $router */
|
||||
$props = [
|
||||
'listUrl' => (string)$router->fromHere('api:stations:queue'),
|
||||
'clearUrl' => (string)$router->fromHere('api:stations:queue:clear'),
|
||||
'locale' => substr($customization->getLocale(), 0, 2),
|
||||
'stationTimeZone' => $stationTz,
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue