mirror of
https://github.com/AzuraCast/AzuraCast.git
synced 2024-06-13 04:36:41 +00:00
Fixes #6647 -- Make disabled stations render correctly in new Vue SPA.
This commit is contained in:
parent
546e1ce4a8
commit
ad69a8a694
|
@ -42,6 +42,8 @@ release channel, you can take advantage of these new features and fixes.
|
|||
|
||||
- Fixed an issue preventing web updates from going through correctly.
|
||||
|
||||
- Fixed an issue where disabled stations wouldn't show their profile pages at all.
|
||||
|
||||
---
|
||||
|
||||
# AzuraCast 0.19.1 (Aug 21, 2023)
|
||||
|
|
|
@ -1,176 +1,34 @@
|
|||
<template>
|
||||
<profile-header
|
||||
v-bind="pickProps(props, headerPanelProps)"
|
||||
:station="profileInfo.station"
|
||||
/>
|
||||
|
||||
<div
|
||||
id="profile"
|
||||
class="row row-of-cards"
|
||||
<loading
|
||||
v-if="isEnabled"
|
||||
:loading="isLoading"
|
||||
lazy
|
||||
>
|
||||
<div class="col-lg-7">
|
||||
<template v-if="hasStarted">
|
||||
<profile-now-playing
|
||||
v-bind="pickProps(props, nowPlayingPanelProps)"
|
||||
@api-call="makeApiCall"
|
||||
/>
|
||||
|
||||
<profile-schedule
|
||||
:schedule-items="profileInfo.schedule"
|
||||
/>
|
||||
|
||||
<profile-streams
|
||||
:station="profileInfo.station"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<now-playing-not-started-panel />
|
||||
</template>
|
||||
|
||||
<profile-public-pages
|
||||
v-bind="pickProps(props, {...publicPagesPanelProps,...embedModalProps})"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-5">
|
||||
<profile-requests
|
||||
v-if="stationSupportsRequests"
|
||||
v-bind="pickProps(props, requestsPanelProps)"
|
||||
/>
|
||||
|
||||
<profile-streamers
|
||||
v-if="stationSupportsStreamers"
|
||||
v-bind="pickProps(props, streamersPanelProps)"
|
||||
/>
|
||||
|
||||
<template v-if="hasActiveFrontend">
|
||||
<profile-frontend
|
||||
v-bind="pickProps(props, frontendPanelProps)"
|
||||
:frontend-running="profileInfo.services.frontend_running"
|
||||
@api-call="makeApiCall"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-if="hasActiveBackend">
|
||||
<profile-backend
|
||||
v-bind="pickProps(props, backendPanelProps)"
|
||||
:backend-running="profileInfo.services.backend_running"
|
||||
@api-call="makeApiCall"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<profile-backend-none />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<enabled-profile v-bind="state" />
|
||||
</loading>
|
||||
<station-disabled-panel v-else />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ProfileStreams from './Profile/StreamsPanel.vue';
|
||||
import ProfileHeader from './Profile/HeaderPanel.vue';
|
||||
import ProfileNowPlaying from './Profile/NowPlayingPanel.vue';
|
||||
import ProfileSchedule from './Profile/SchedulePanel.vue';
|
||||
import ProfileRequests from './Profile/RequestsPanel.vue';
|
||||
import ProfileStreamers from './Profile/StreamersPanel.vue';
|
||||
import ProfilePublicPages from './Profile/PublicPagesPanel.vue';
|
||||
import ProfileFrontend from './Profile/FrontendPanel.vue';
|
||||
import ProfileBackendNone from './Profile/BackendNonePanel.vue';
|
||||
import ProfileBackend from './Profile/BackendPanel.vue';
|
||||
import NowPlayingNotStartedPanel from "./Profile/NowPlayingNotStartedPanel.vue";
|
||||
import {BackendAdapter, FrontendAdapter} from '~/entities/RadioAdapters';
|
||||
import NowPlaying from '~/entities/NowPlaying';
|
||||
import {computed} from "vue";
|
||||
import {useAxios} from "~/vendor/axios";
|
||||
import backendPanelProps from "./Profile/backendPanelProps";
|
||||
import embedModalProps from "./Profile/embedModalProps";
|
||||
import frontendPanelProps from "./Profile/frontendPanelProps";
|
||||
import headerPanelProps from "./Profile/headerPanelProps";
|
||||
import nowPlayingPanelProps from "./Profile/nowPlayingPanelProps";
|
||||
import publicPagesPanelProps from "./Profile/publicPagesPanelProps";
|
||||
import requestsPanelProps from "./Profile/requestsPanelProps";
|
||||
import streamersPanelProps from "./Profile/streamersPanelProps";
|
||||
import {pickProps} from "~/functions/pickProps";
|
||||
import useRefreshableAsyncState from "~/functions/useRefreshableAsyncState";
|
||||
import {useIntervalFn} from "@vueuse/core";
|
||||
import {useSweetAlert} from "~/vendor/sweetalert";
|
||||
import {useNotify} from "~/functions/useNotify";
|
||||
import {useTranslate} from "~/vendor/gettext";
|
||||
import {useAzuraCastStation} from "~/vendor/azuracast.ts";
|
||||
import {useAxios} from "~/vendor/axios.ts";
|
||||
import {useAsyncState} from "@vueuse/core";
|
||||
import {getStationApiUrl} from "~/router.ts";
|
||||
import StationDisabledPanel from "~/components/Stations/Profile/StationDisabledPanel.vue";
|
||||
import Loading from "~/components/Common/Loading.vue";
|
||||
import EnabledProfile from "~/components/Stations/Profile/EnabledProfile.vue";
|
||||
|
||||
const props = defineProps({
|
||||
...backendPanelProps,
|
||||
...embedModalProps,
|
||||
...frontendPanelProps,
|
||||
...headerPanelProps,
|
||||
...nowPlayingPanelProps,
|
||||
...publicPagesPanelProps,
|
||||
...requestsPanelProps,
|
||||
...streamersPanelProps,
|
||||
profileApiUri: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
stationSupportsRequests: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
stationSupportsStreamers: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const hasActiveFrontend = computed(() => {
|
||||
return props.frontendType !== FrontendAdapter.Remote;
|
||||
});
|
||||
|
||||
const hasActiveBackend = computed(() => {
|
||||
return props.backendType !== BackendAdapter.None;
|
||||
});
|
||||
const {isEnabled} = useAzuraCastStation();
|
||||
|
||||
const {axios} = useAxios();
|
||||
|
||||
const {state: profileInfo, execute: reloadProfile} = useRefreshableAsyncState(
|
||||
() => axios.get(props.profileApiUri).then((r) => r.data),
|
||||
{
|
||||
station: {
|
||||
...NowPlaying.station
|
||||
},
|
||||
services: {
|
||||
backend_running: false,
|
||||
frontend_running: false,
|
||||
has_started: false,
|
||||
needs_restart: false
|
||||
},
|
||||
schedule: []
|
||||
}
|
||||
);
|
||||
|
||||
const profileReloadTimeout = computed(() => {
|
||||
return (!document.hidden) ? 15000 : 30000
|
||||
});
|
||||
|
||||
useIntervalFn(
|
||||
reloadProfile,
|
||||
profileReloadTimeout
|
||||
);
|
||||
|
||||
const {showAlert} = useSweetAlert();
|
||||
const {notify} = useNotify();
|
||||
const {$gettext} = useTranslate();
|
||||
|
||||
const makeApiCall = (uri) => {
|
||||
showAlert({
|
||||
title: $gettext('Are you sure?')
|
||||
}).then((result) => {
|
||||
if (!result.value) {
|
||||
return;
|
||||
const {isLoading, state} = useAsyncState(
|
||||
async () => {
|
||||
if (isEnabled) {
|
||||
const r = await axios.get(getStationApiUrl('/vue/profile').value);
|
||||
return await r.data;
|
||||
}
|
||||
|
||||
axios.post(uri).then((resp) => {
|
||||
notify(resp.data.formatted_message, {
|
||||
variant: (resp.data.success) ? 'success' : 'warning'
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
return {};
|
||||
},
|
||||
{}
|
||||
);
|
||||
</script>
|
||||
|
|
176
frontend/src/components/Stations/Profile/EnabledProfile.vue
Normal file
176
frontend/src/components/Stations/Profile/EnabledProfile.vue
Normal file
|
@ -0,0 +1,176 @@
|
|||
<template>
|
||||
<profile-header
|
||||
v-bind="pickProps(props, headerPanelProps)"
|
||||
:station="profileInfo.station"
|
||||
/>
|
||||
|
||||
<div
|
||||
id="profile"
|
||||
class="row row-of-cards"
|
||||
>
|
||||
<div class="col-lg-7">
|
||||
<template v-if="hasStarted">
|
||||
<profile-now-playing
|
||||
v-bind="pickProps(props, nowPlayingPanelProps)"
|
||||
@api-call="makeApiCall"
|
||||
/>
|
||||
|
||||
<profile-schedule
|
||||
:schedule-items="profileInfo.schedule"
|
||||
/>
|
||||
|
||||
<profile-streams
|
||||
:station="profileInfo.station"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<now-playing-not-started-panel />
|
||||
</template>
|
||||
|
||||
<profile-public-pages
|
||||
v-bind="pickProps(props, {...publicPagesPanelProps,...embedModalProps})"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-5">
|
||||
<profile-requests
|
||||
v-if="stationSupportsRequests"
|
||||
v-bind="pickProps(props, requestsPanelProps)"
|
||||
/>
|
||||
|
||||
<profile-streamers
|
||||
v-if="stationSupportsStreamers"
|
||||
v-bind="pickProps(props, streamersPanelProps)"
|
||||
/>
|
||||
|
||||
<template v-if="hasActiveFrontend">
|
||||
<profile-frontend
|
||||
v-bind="pickProps(props, frontendPanelProps)"
|
||||
:frontend-running="profileInfo.services.frontend_running"
|
||||
@api-call="makeApiCall"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-if="hasActiveBackend">
|
||||
<profile-backend
|
||||
v-bind="pickProps(props, backendPanelProps)"
|
||||
:backend-running="profileInfo.services.backend_running"
|
||||
@api-call="makeApiCall"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<profile-backend-none />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ProfileStreams from './StreamsPanel.vue';
|
||||
import ProfileHeader from './HeaderPanel.vue';
|
||||
import ProfileNowPlaying from './NowPlayingPanel.vue';
|
||||
import ProfileSchedule from './SchedulePanel.vue';
|
||||
import ProfileRequests from './RequestsPanel.vue';
|
||||
import ProfileStreamers from './StreamersPanel.vue';
|
||||
import ProfilePublicPages from './PublicPagesPanel.vue';
|
||||
import ProfileFrontend from './FrontendPanel.vue';
|
||||
import ProfileBackendNone from './BackendNonePanel.vue';
|
||||
import ProfileBackend from './BackendPanel.vue';
|
||||
import NowPlayingNotStartedPanel from "./NowPlayingNotStartedPanel.vue";
|
||||
import {BackendAdapter, FrontendAdapter} from '~/entities/RadioAdapters';
|
||||
import NowPlaying from '~/entities/NowPlaying';
|
||||
import {computed} from "vue";
|
||||
import {useAxios} from "~/vendor/axios";
|
||||
import backendPanelProps from "./backendPanelProps";
|
||||
import embedModalProps from "./embedModalProps";
|
||||
import frontendPanelProps from "./frontendPanelProps";
|
||||
import headerPanelProps from "./headerPanelProps";
|
||||
import nowPlayingPanelProps from "./nowPlayingPanelProps";
|
||||
import publicPagesPanelProps from "./publicPagesPanelProps";
|
||||
import requestsPanelProps from "./requestsPanelProps";
|
||||
import streamersPanelProps from "./streamersPanelProps";
|
||||
import {pickProps} from "~/functions/pickProps";
|
||||
import useRefreshableAsyncState from "~/functions/useRefreshableAsyncState";
|
||||
import {useIntervalFn} from "@vueuse/core";
|
||||
import {useSweetAlert} from "~/vendor/sweetalert";
|
||||
import {useNotify} from "~/functions/useNotify";
|
||||
import {useTranslate} from "~/vendor/gettext";
|
||||
|
||||
const props = defineProps({
|
||||
...backendPanelProps,
|
||||
...embedModalProps,
|
||||
...frontendPanelProps,
|
||||
...headerPanelProps,
|
||||
...nowPlayingPanelProps,
|
||||
...publicPagesPanelProps,
|
||||
...requestsPanelProps,
|
||||
...streamersPanelProps,
|
||||
profileApiUri: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
stationSupportsRequests: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
stationSupportsStreamers: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const hasActiveFrontend = computed(() => {
|
||||
return props.frontendType !== FrontendAdapter.Remote;
|
||||
});
|
||||
|
||||
const hasActiveBackend = computed(() => {
|
||||
return props.backendType !== BackendAdapter.None;
|
||||
});
|
||||
|
||||
const {axios} = useAxios();
|
||||
|
||||
const {state: profileInfo, execute: reloadProfile} = useRefreshableAsyncState(
|
||||
() => axios.get(props.profileApiUri).then((r) => r.data),
|
||||
{
|
||||
station: {
|
||||
...NowPlaying.station
|
||||
},
|
||||
services: {
|
||||
backend_running: false,
|
||||
frontend_running: false,
|
||||
has_started: false,
|
||||
needs_restart: false
|
||||
},
|
||||
schedule: []
|
||||
}
|
||||
);
|
||||
|
||||
const profileReloadTimeout = computed(() => {
|
||||
return (!document.hidden) ? 15000 : 30000
|
||||
});
|
||||
|
||||
useIntervalFn(
|
||||
reloadProfile,
|
||||
profileReloadTimeout
|
||||
);
|
||||
|
||||
const {showAlert} = useSweetAlert();
|
||||
const {notify} = useNotify();
|
||||
const {$gettext} = useTranslate();
|
||||
|
||||
const makeApiCall = (uri) => {
|
||||
showAlert({
|
||||
title: $gettext('Are you sure?')
|
||||
}).then((result) => {
|
||||
if (!result.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
axios.post(uri).then((resp) => {
|
||||
notify(resp.data.formatted_message, {
|
||||
variant: (resp.data.success) ? 'success' : 'warning'
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,44 @@
|
|||
<template>
|
||||
<div class="outside-card-header d-flex align-items-center">
|
||||
<div class="flex-fill">
|
||||
<h2 class="display-6 m-0">
|
||||
{{ name }}
|
||||
</h2>
|
||||
</div>
|
||||
<div
|
||||
v-if="userAllowedForStation(StationPermission.Profile)"
|
||||
class="flex-shrink-0 ms-3"
|
||||
>
|
||||
<router-link
|
||||
class="btn btn-primary"
|
||||
role="button"
|
||||
:to="{name: 'stations:profile:edit'}"
|
||||
>
|
||||
<icon :icon="IconEdit" />
|
||||
<span>
|
||||
{{ $gettext('Edit Profile') }}
|
||||
</span>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<card-page
|
||||
id="station-disabled"
|
||||
:title="$gettext('Station Disabled')"
|
||||
>
|
||||
<div class="card-body">
|
||||
<p class="card-text">
|
||||
{{ $gettext('Your station is currently not enabled for broadcasting. You can still manage media, playlists, and other station settings. To re-enable broadcasting, edit your station profile.') }}
|
||||
</p>
|
||||
</div>
|
||||
</card-page>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {StationPermission, userAllowedForStation} from "~/acl.ts";
|
||||
import {IconEdit} from "~/components/Common/icons.ts";
|
||||
import Icon from "~/components/Common/Icon.vue";
|
||||
import CardPage from "~/components/Common/CardPage.vue";
|
||||
import {useAzuraCastStation} from "~/vendor/azuracast.ts";
|
||||
|
||||
const {name} = useAzuraCastStation();
|
||||
</script>
|
|
@ -6,8 +6,7 @@ export default function useStationsRoutes() {
|
|||
{
|
||||
path: '/',
|
||||
component: () => import('~/components/Stations/Profile.vue'),
|
||||
name: 'stations:index',
|
||||
...populateComponentRemotely(getStationApiUrl('/vue/profile'))
|
||||
name: 'stations:index'
|
||||
},
|
||||
{
|
||||
path: '/branding',
|
||||
|
|
2
frontend/src/vendor/azuracast.ts
vendored
2
frontend/src/vendor/azuracast.ts
vendored
|
@ -11,6 +11,7 @@ export function setGlobalProps(newGlobalProps: AzuraCastConstants): void {
|
|||
export interface AzuraCastStationConstants {
|
||||
id: number | null,
|
||||
name: string | null,
|
||||
isEnabled: boolean | null,
|
||||
shortName: string | null,
|
||||
timezone: string | null,
|
||||
offlineText: string | null,
|
||||
|
@ -60,6 +61,7 @@ export function useAzuraCastStation(): AzuraCastStationConstants {
|
|||
return (station !== null) ? station : {
|
||||
id: null,
|
||||
name: null,
|
||||
isEnabled: null,
|
||||
shortName: null,
|
||||
timezone: null,
|
||||
offlineText: null
|
||||
|
|
|
@ -24,11 +24,6 @@ final class IndexAction implements SingleActionInterface
|
|||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
$view = $request->getView();
|
||||
|
||||
if (!$station->getIsEnabled()) {
|
||||
return $view->renderToResponse($response, 'stations/profile_disabled');
|
||||
}
|
||||
|
||||
$router = $request->getRouter();
|
||||
|
||||
$globalProps = $view->getGlobalProps();
|
||||
|
|
|
@ -227,6 +227,7 @@ final class View extends Engine
|
|||
$this->globalProps->set('station', [
|
||||
'id' => $station->getIdRequired(),
|
||||
'name' => $station->getName(),
|
||||
'isEnabled' => $station->getIsEnabled(),
|
||||
'shortName' => $station->getShortName(),
|
||||
'timezone' => $station->getTimezone(),
|
||||
'offlineText' => $station->getBrandingConfig()->getOfflineText(),
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @var App\Entity\Station $station
|
||||
* @var App\Http\RouterInterface $router
|
||||
*/
|
||||
|
||||
$this->layout('main', [
|
||||
'title' =>
|
||||
__('Station Broadcasting Disabled'),
|
||||
]);
|
||||
?>
|
||||
|
||||
<p>
|
||||
<?= sprintf(
|
||||
__(
|
||||
'Your station is currently not enabled for broadcasting. You can still manage media, playlists, and other station settings. To re-enable broadcasting, <a href="%s">edit your station profile</a>.'
|
||||
),
|
||||
$router->fromHere('stations:profile:edit')
|
||||
) ?></p>
|
|
@ -1,10 +0,0 @@
|
|||
<?php $this->layout('main', ['title' => __('Report Not Available'), 'manual' => true]) ?>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title"><?=__('Report Not Available') ?></h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><?=__('This report is not available for this station, because the system administrator has chosen not to collect detailed IP-based listener information.') ?></p>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user