Add schedule embed widget for embedding the stations playlist schedule view into websites (#4323)
This commit is contained in:
parent
fc44a4ea91
commit
328caf3987
|
@ -496,6 +496,12 @@ return [
|
|||
// Auto-managed by Assets
|
||||
],
|
||||
|
||||
'Vue_PublicSchedule' => [
|
||||
'order' => 10,
|
||||
'require' => ['vue-component-common', 'bootstrap-vue', 'moment_base', 'moment_timezone'],
|
||||
// Auto-managed by Assets
|
||||
],
|
||||
|
||||
'Vue_PublicWebDJ' => [
|
||||
'order' => 10,
|
||||
'require' => ['vue-component-common'],
|
||||
|
|
|
@ -33,6 +33,9 @@ return function (App $app) {
|
|||
$group->get('/ondemand[/{embed:embed}]', Controller\Frontend\PublicPages\OnDemandAction::class)
|
||||
->setName('public:ondemand');
|
||||
|
||||
$group->get('/schedule[/{embed:embed}]', Controller\Frontend\PublicPages\ScheduleAction::class)
|
||||
->setName('public:schedule');
|
||||
|
||||
$group->get('/podcasts', Controller\Frontend\PublicPages\PodcastsController::class)
|
||||
->setName('public:podcasts');
|
||||
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<div class="card" style="height: 100%;">
|
||||
<div class="card-header bg-primary-dark">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="flex-shrink">
|
||||
<h2 class="card-title py-2">
|
||||
<template v-if="stationName">
|
||||
{{ stationName }}
|
||||
</template>
|
||||
<template v-else>
|
||||
<translate key="lang_title">Schedule</translate>
|
||||
</template>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="station-schedule-calendar">
|
||||
<schedule ref="schedule" :schedule-url="scheduleUrl" :station-time-zone="stationTimeZone"
|
||||
:locale="locale"></schedule>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.schedule.embed {
|
||||
.container {
|
||||
max-width: 100%;
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
#station-schedule-calendar {
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import Schedule from '../Common/ScheduleView';
|
||||
|
||||
export default {
|
||||
components: { Schedule },
|
||||
props: {
|
||||
scheduleUrl: String,
|
||||
stationName: String,
|
||||
locale: String,
|
||||
stationTimeZone: String
|
||||
},
|
||||
mounted () {
|
||||
moment.relativeTimeThreshold('ss', 1);
|
||||
moment.relativeTimeRounding(function (value) {
|
||||
return Math.round(value * 10) / 10;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
formatTime (time) {
|
||||
return moment(time).tz(this.stationTimeZone).format('LT');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -72,7 +72,8 @@ export const profileEmbedModalProps = {
|
|||
publicPageEmbedUri: String,
|
||||
publicOnDemandEmbedUri: String,
|
||||
publicRequestEmbedUri: String,
|
||||
publicHistoryEmbedUri: String
|
||||
publicHistoryEmbedUri: String,
|
||||
publicScheduleEmbedUri: String
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -88,6 +89,10 @@ export default {
|
|||
{
|
||||
value: 'history',
|
||||
text: this.$gettext('History')
|
||||
},
|
||||
{
|
||||
value: 'schedule',
|
||||
text: this.$gettext('Schedule')
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -142,6 +147,9 @@ export default {
|
|||
case 'requests':
|
||||
return this.publicRequestEmbedUri;
|
||||
|
||||
case 'schedule':
|
||||
return this.publicScheduleEmbedUri;
|
||||
|
||||
case 'player':
|
||||
default:
|
||||
return this.publicPageEmbedUri;
|
||||
|
@ -170,6 +178,9 @@ export default {
|
|||
case 'history':
|
||||
return '300px';
|
||||
|
||||
case 'schedule':
|
||||
return '800px'
|
||||
|
||||
case 'player':
|
||||
default:
|
||||
return '150px';
|
||||
|
|
|
@ -37,6 +37,12 @@
|
|||
<a :href="publicPodcastsUri">{{ publicPodcastsUri }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td key="lang_profile_schedule" v-translate>Schedule</td>
|
||||
<td>
|
||||
<a :href="publicScheduleUri">{{ publicScheduleUri }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="card-actions" v-if="userCanManageProfile">
|
||||
|
@ -85,6 +91,7 @@ export const profilePublicProps = {
|
|||
publicWebDjUri: String,
|
||||
publicOnDemandUri: String,
|
||||
publicPodcastsUri: String,
|
||||
publicScheduleUri: String,
|
||||
togglePublicPageUri: String
|
||||
}
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@ module.exports = {
|
|||
PublicOnDemand: './vue/Public/OnDemand.vue',
|
||||
PublicPlayer: './vue/Public/Player.vue',
|
||||
PublicRequests: './vue/Public/Requests.vue',
|
||||
PublicSchedule: './vue/Public/Schedule.vue',
|
||||
PublicWebDJ: './vue/Public/WebDJ.vue',
|
||||
StationsMedia: './vue/Stations/Media.vue',
|
||||
StationsMounts: './vue/Stations/Mounts.vue',
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\Frontend\PublicPages;
|
||||
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class ScheduleAction
|
||||
{
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
bool $embed = false
|
||||
): ResponseInterface {
|
||||
// Override system-wide iframe refusal
|
||||
$response = $response->withHeader('X-Frame-Options', '*');
|
||||
|
||||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
}
|
||||
|
||||
return $request->getView()->renderToResponse(
|
||||
$response,
|
||||
'frontend/public/schedule',
|
||||
[
|
||||
'embed' => $embed,
|
||||
'station' => $station,
|
||||
'station_tz' => $station->getTimezone(),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
/** @var App\Entity\Station $station */
|
||||
|
||||
$pageClass = 'schedule station-' . $station->getShortName();
|
||||
if ($embed) {
|
||||
$pageClass .= ' embed';
|
||||
}
|
||||
|
||||
$this->layout(
|
||||
'minimal',
|
||||
[
|
||||
'page_class' => $pageClass,
|
||||
'title' => __('Schedule') . ' - ' . $this->e($station->getName()),
|
||||
'hide_footer' => true,
|
||||
]
|
||||
);
|
||||
|
||||
$props = [
|
||||
'scheduleUrl' => (string)$router->named('api:stations:schedule', ['station_id' => $station->getId()]),
|
||||
'stationName' => $station->getName(),
|
||||
'locale' => substr($customization->getLocale()->getLocale(), 0, 2),
|
||||
'stationTimeZone' => $station_tz,
|
||||
];
|
||||
|
||||
/** @var \App\Assets $assets */
|
||||
$assets->addVueRender('Vue_PublicSchedule', '#station-schedule', $props);
|
||||
?>
|
||||
|
||||
<section id="content" role="main" class="d-flex align-items-stretch" style="height: 100vh;">
|
||||
<div class="container pt-5 pb-5 h-100" style="flex: 1;">
|
||||
<div id="station-schedule"></div>
|
||||
</div>
|
||||
</section>
|
|
@ -72,6 +72,12 @@ $props = [
|
|||
[],
|
||||
true
|
||||
),
|
||||
'publicScheduleUri' => (string)$router->named(
|
||||
'public:schedule',
|
||||
['station_id' => $station->getShortName()],
|
||||
[],
|
||||
true
|
||||
),
|
||||
'publicOnDemandEmbedUri' => (string)$router->named(
|
||||
'public:ondemand',
|
||||
['station_id' => $station->getShortName(), 'embed' => 'embed'],
|
||||
|
@ -90,6 +96,12 @@ $props = [
|
|||
[],
|
||||
true
|
||||
),
|
||||
'publicScheduleEmbedUri' => (string)$router->named(
|
||||
'public:schedule',
|
||||
['station_id' => $station->getShortName(), 'embed' => 'embed'],
|
||||
[],
|
||||
true
|
||||
),
|
||||
|
||||
'togglePublicPageUri' => $router->fromHere(
|
||||
'stations:profile:toggle',
|
||||
|
|
Loading…
Reference in New Issue