mirror of
https://github.com/AzuraCast/AzuraCast.git
synced 2024-06-14 13:16:37 +00:00
Move badges to common, move profile to Vue3 Comp API.
This commit is contained in:
parent
27e5be80ee
commit
b663eb5736
|
@ -136,7 +136,7 @@ import AccountTwoFactorModal from "./Account/TwoFactorModal";
|
|||
import AccountEditModal from "./Account/EditModal";
|
||||
import Avatar from "~/components/Common/Avatar";
|
||||
import InfoCard from "~/components/Common/InfoCard";
|
||||
import EnabledBadge from "~/components/Stations/Profile/Common/EnabledBadge.vue";
|
||||
import EnabledBadge from "~/components/Common/Badges/EnabledBadge.vue";
|
||||
|
||||
export default {
|
||||
name: 'Account',
|
||||
|
|
|
@ -115,13 +115,17 @@ import {DateTime} from 'luxon';
|
|||
import formatFileSize from "~/functions/formatFileSize";
|
||||
import AdminBackupsConfigureModal from "~/components/Admin/Backups/ConfigureModal";
|
||||
import AdminBackupsRunBackupModal from "~/components/Admin/Backups/RunBackupModal";
|
||||
import EnabledBadge from "~/components/Stations/Profile/Common/EnabledBadge.vue";
|
||||
import EnabledBadge from "~/components/Common/Badges/EnabledBadge.vue";
|
||||
|
||||
export default {
|
||||
name: 'AdminBackups',
|
||||
components: {
|
||||
EnabledBadge,
|
||||
AdminBackupsRunBackupModal, AdminBackupsConfigureModal, AdminBackupsLastOutputModal, DataTable, Icon
|
||||
AdminBackupsRunBackupModal,
|
||||
AdminBackupsConfigureModal,
|
||||
AdminBackupsLastOutputModal,
|
||||
DataTable,
|
||||
Icon
|
||||
},
|
||||
props: {
|
||||
listUrl: String,
|
||||
|
|
|
@ -32,6 +32,12 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
inheritAttrs: false
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import ProfileStreams from './Profile/StreamsPanel';
|
||||
import ProfileHeader, {profileHeaderProps} from './Profile/HeaderPanel';
|
||||
import ProfileNowPlaying, {profileNowPlayingProps} from './Profile/NowPlayingPanel';
|
||||
|
@ -45,40 +51,25 @@ import ProfileBackend, {profileBackendProps} from './Profile/BackendPanel';
|
|||
import {profileEmbedModalProps} from './Profile/EmbedModal';
|
||||
import {BACKEND_NONE, FRONTEND_REMOTE} from '~/components/Entity/RadioAdapters.js';
|
||||
import NowPlaying from '~/components/Entity/NowPlaying';
|
||||
import {computed, onMounted, shallowRef} from "vue";
|
||||
import {useAxios} from "~/vendor/axios";
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
components: {
|
||||
ProfileBackend,
|
||||
ProfileBackendNone,
|
||||
ProfileFrontend,
|
||||
ProfilePublicPages,
|
||||
ProfileStreamers,
|
||||
ProfileRequests,
|
||||
ProfileSchedule,
|
||||
ProfileNowPlaying,
|
||||
ProfileHeader,
|
||||
ProfileStreams
|
||||
},
|
||||
mixins: [
|
||||
profileHeaderProps,
|
||||
profileNowPlayingProps,
|
||||
profileRequestsProps,
|
||||
profileStreamersProps,
|
||||
profilePublicProps,
|
||||
profileFrontendProps,
|
||||
profileBackendProps,
|
||||
profileEmbedModalProps
|
||||
],
|
||||
props: {
|
||||
const props = defineProps({
|
||||
...profileHeaderProps,
|
||||
...profileNowPlayingProps,
|
||||
...profileRequestsProps,
|
||||
...profileStreamersProps,
|
||||
...profilePublicProps,
|
||||
...profileFrontendProps,
|
||||
...profileBackendProps,
|
||||
...profileEmbedModalProps,
|
||||
profileApiUri: String,
|
||||
stationTimeZone: String,
|
||||
stationSupportsRequests: Boolean,
|
||||
stationSupportsStreamers: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
np: {
|
||||
});
|
||||
|
||||
const np = shallowRef({
|
||||
...NowPlaying,
|
||||
loading: true,
|
||||
services: {
|
||||
|
@ -86,34 +77,32 @@ export default {
|
|||
frontend_running: false
|
||||
},
|
||||
schedule: []
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.checkNowPlaying();
|
||||
},
|
||||
computed: {
|
||||
hasActiveFrontend() {
|
||||
return this.frontendType !== FRONTEND_REMOTE;
|
||||
},
|
||||
hasActiveBackend() {
|
||||
return this.backendType !== BACKEND_NONE;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
checkNowPlaying() {
|
||||
this.axios.get(this.profileApiUri).then((response) => {
|
||||
let np = response.data;
|
||||
np.loading = false;
|
||||
this.np = np;
|
||||
});
|
||||
|
||||
setTimeout(this.checkNowPlaying, (!document.hidden) ? 15000 : 30000);
|
||||
const hasActiveFrontend = computed(() => {
|
||||
return props.frontendType !== FRONTEND_REMOTE;
|
||||
});
|
||||
|
||||
const hasActiveBackend = computed(() => {
|
||||
return props.backendType !== BACKEND_NONE;
|
||||
});
|
||||
|
||||
const {axios} = useAxios();
|
||||
|
||||
const checkNowPlaying = () => {
|
||||
axios.get(props.profileApiUri).then((response) => {
|
||||
let np_new = response.data;
|
||||
np_new.loading = false;
|
||||
|
||||
np.value = np_new;
|
||||
|
||||
setTimeout(checkNowPlaying, (!document.hidden) ? 15000 : 30000);
|
||||
}).catch((error) => {
|
||||
if (!error.response || error.response.data.code !== 403) {
|
||||
setTimeout(this.checkNowPlaying, (!document.hidden) ? 30000 : 120000);
|
||||
setTimeout(checkNowPlaying, (!document.hidden) ? 30000 : 120000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(checkNowPlaying);
|
||||
</script>
|
||||
|
|
|
@ -38,12 +38,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {BACKEND_LIQUIDSOAP} from '~/components/Entity/RadioAdapters.js';
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import RunningBadge from "./Common/RunningBadge.vue";
|
||||
|
||||
export const profileBackendProps = {
|
||||
props: {
|
||||
numSongs: Number,
|
||||
numPlaylists: Number,
|
||||
backendType: String,
|
||||
|
@ -55,36 +50,56 @@ export const profileBackendProps = {
|
|||
backendRestartUri: String,
|
||||
backendStartUri: String,
|
||||
backendStopUri: String
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
components: {RunningBadge, Icon},
|
||||
mixins: [profileBackendProps],
|
||||
props: {
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import {BACKEND_LIQUIDSOAP} from '~/components/Entity/RadioAdapters.js';
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import RunningBadge from "~/components/Common/Badges/RunningBadge.vue";
|
||||
import gettext from "~/vendor/gettext";
|
||||
import {computed} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
...profileBackendProps,
|
||||
np: Object
|
||||
},
|
||||
computed: {
|
||||
langTotalTracks() {
|
||||
let numSongsRaw = this.$ngettext('%{numSongs} uploaded song', '%{numSongs} uploaded songs', this.numSongs);
|
||||
let numSongs = this.$gettextInterpolate(numSongsRaw, {numSongs: this.numSongs});
|
||||
});
|
||||
|
||||
let numPlaylistsRaw = this.$ngettext('%{numPlaylists} playlist', '%{numPlaylists} playlists', this.numPlaylists);
|
||||
let numPlaylists = this.$gettextInterpolate(numPlaylistsRaw, { numPlaylists: this.numPlaylists });
|
||||
const {$gettext, $ngettext} = gettext;
|
||||
|
||||
let translated = this.$gettext('LiquidSoap is currently shuffling from %{songs} and %{playlists}.');
|
||||
return this.$gettextInterpolate(translated, {
|
||||
const langTotalTracks = computed(() => {
|
||||
let numSongs = $ngettext(
|
||||
'%{numSongs} uploaded song',
|
||||
'%{numSongs} uploaded songs',
|
||||
props.numSongs,
|
||||
{numSongs: props.numSongs}
|
||||
);
|
||||
|
||||
let numPlaylists = $ngettext(
|
||||
'%{numPlaylists} playlist',
|
||||
'%{numPlaylists} playlists',
|
||||
props.numPlaylists,
|
||||
{numPlaylists: props.numPlaylists}
|
||||
);
|
||||
|
||||
return $gettext(
|
||||
'LiquidSoap is currently shuffling from %{songs} and %{playlists}.',
|
||||
{
|
||||
songs: numSongs,
|
||||
playlists: numPlaylists
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
backendName () {
|
||||
if (this.backendType === BACKEND_LIQUIDSOAP) {
|
||||
|
||||
const backendName = computed(() => {
|
||||
if (props.backendType === BACKEND_LIQUIDSOAP) {
|
||||
return 'Liquidsoap';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<b-modal size="lg" id="embed_modal" ref="modal" :title="langTitle" hide-footer no-enforce-focus>
|
||||
<b-modal size="lg" id="embed_modal" ref="modal" :title="$gettext('Embed Widgets')" hide-footer no-enforce-focus>
|
||||
<b-row>
|
||||
<b-col md="7">
|
||||
<b-card class="mb-3" no-body>
|
||||
|
@ -9,7 +9,7 @@
|
|||
<b-card-body>
|
||||
<b-row>
|
||||
<b-col md="6">
|
||||
<b-form-group :label="langEmbedType">
|
||||
<b-form-group :label="$gettext('Widget Type')">
|
||||
<b-form-radio-group
|
||||
id="embed_type"
|
||||
v-model="selectedType"
|
||||
|
@ -20,7 +20,7 @@
|
|||
</b-form-group>
|
||||
</b-col>
|
||||
<b-col md="6">
|
||||
<b-form-group :label="langTheme">
|
||||
<b-form-group :label="$gettext('Theme')">
|
||||
<b-form-radio-group
|
||||
id="embed_theme"
|
||||
v-model="selectedTheme"
|
||||
|
@ -61,10 +61,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import CopyToClipboardButton from '~/components/Common/CopyToClipboardButton';
|
||||
|
||||
export const profileEmbedModalProps = {
|
||||
props: {
|
||||
stationSupportsStreamers: Boolean,
|
||||
stationSupportsRequests: Boolean,
|
||||
enablePublicPage: Boolean,
|
||||
|
@ -76,93 +73,99 @@ export const profileEmbedModalProps = {
|
|||
publicRequestEmbedUri: String,
|
||||
publicHistoryEmbedUri: String,
|
||||
publicScheduleEmbedUri: String
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
components: {CopyToClipboardButton},
|
||||
mixins: [profileEmbedModalProps],
|
||||
data() {
|
||||
inheritAttrs: false
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import CopyToClipboardButton from '~/components/Common/CopyToClipboardButton';
|
||||
import {computed, ref} from "vue";
|
||||
import gettext from "~/vendor/gettext";
|
||||
|
||||
const props = defineProps({
|
||||
...profileEmbedModalProps
|
||||
});
|
||||
|
||||
const selectedType = ref('player');
|
||||
const selectedTheme = ref('light');
|
||||
|
||||
const {$gettext} = gettext;
|
||||
|
||||
const types = computed(() => {
|
||||
let types = [
|
||||
{
|
||||
value: 'player',
|
||||
text: this.$gettext('Radio Player')
|
||||
text: $gettext('Radio Player')
|
||||
},
|
||||
{
|
||||
value: 'history',
|
||||
text: this.$gettext('History')
|
||||
text: $gettext('History')
|
||||
},
|
||||
{
|
||||
value: 'schedule',
|
||||
text: this.$gettext('Schedule')
|
||||
text: $gettext('Schedule')
|
||||
}
|
||||
];
|
||||
|
||||
if (this.stationSupportsRequests && this.enableRequests) {
|
||||
if (props.stationSupportsRequests && props.enableRequests) {
|
||||
types.push({
|
||||
value: 'requests',
|
||||
text: this.$gettext('Requests')
|
||||
text: $gettext('Requests')
|
||||
});
|
||||
}
|
||||
|
||||
if (this.enableOnDemand) {
|
||||
if (props.enableOnDemand) {
|
||||
types.push({
|
||||
value: 'ondemand',
|
||||
text: this.$gettext('On-Demand Media')
|
||||
text: $gettext('On-Demand Media')
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
selectedType: 'player',
|
||||
types: types,
|
||||
selectedTheme: 'light',
|
||||
themes: [
|
||||
return types;
|
||||
});
|
||||
|
||||
const themes = computed(() => {
|
||||
return [
|
||||
{
|
||||
value: 'light',
|
||||
text: this.$gettext('Light')
|
||||
text: $gettext('Light')
|
||||
},
|
||||
{
|
||||
value: 'dark',
|
||||
text: this.$gettext('Dark')
|
||||
text: $gettext('Dark')
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
langTitle() {
|
||||
return this.$gettext('Embed Widgets');
|
||||
},
|
||||
langEmbedType() {
|
||||
return this.$gettext('Widget Type');
|
||||
},
|
||||
langTheme() {
|
||||
return this.$gettext('Theme');
|
||||
},
|
||||
baseEmbedUrl() {
|
||||
switch (this.selectedType) {
|
||||
];
|
||||
});
|
||||
|
||||
const baseEmbedUrl = computed(() => {
|
||||
switch (selectedType.value) {
|
||||
case 'history':
|
||||
return this.publicHistoryEmbedUri;
|
||||
return props.publicHistoryEmbedUri;
|
||||
|
||||
case 'ondemand':
|
||||
return this.publicOnDemandEmbedUri;
|
||||
return props.publicOnDemandEmbedUri;
|
||||
|
||||
case 'requests':
|
||||
return this.publicRequestEmbedUri;
|
||||
return props.publicRequestEmbedUri;
|
||||
|
||||
case 'schedule':
|
||||
return this.publicScheduleEmbedUri;
|
||||
return props.publicScheduleEmbedUri;
|
||||
|
||||
case 'player':
|
||||
default:
|
||||
return this.publicPageEmbedUri;
|
||||
return props.publicPageEmbedUri;
|
||||
}
|
||||
},
|
||||
embedUrl() {
|
||||
return this.baseEmbedUrl + '?theme=' + this.selectedTheme;
|
||||
},
|
||||
embedHeight() {
|
||||
switch (this.selectedType) {
|
||||
});
|
||||
|
||||
const embedUrl = computed(() => {
|
||||
return baseEmbedUrl.value + '?theme=' + selectedTheme.value;
|
||||
});
|
||||
|
||||
const embedHeight = computed(() => {
|
||||
switch (selectedType.value) {
|
||||
case 'ondemand':
|
||||
return '400px';
|
||||
|
||||
|
@ -179,15 +182,19 @@ export default {
|
|||
default:
|
||||
return '150px';
|
||||
}
|
||||
},
|
||||
embedCode() {
|
||||
return '<iframe src="' + this.embedUrl + '" frameborder="0" allowtransparency="true" style="width: 100%; min-height: ' + this.embedHeight + '; border: 0;"></iframe>';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.modal.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const embedCode = computed(() => {
|
||||
return '<iframe src="' + embedUrl.value + '" frameborder="0" allowtransparency="true" style="width: 100%; min-height: ' + embedHeight.value + '; border: 0;"></iframe>';
|
||||
});
|
||||
|
||||
const modal = ref(); // Template Ref
|
||||
|
||||
const open = () => {
|
||||
modal.value.show();
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
open
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -93,13 +93,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {FRONTEND_ICECAST, FRONTEND_SHOUTCAST} from '~/components/Entity/RadioAdapters.js';
|
||||
import CopyToClipboardButton from '~/components/Common/CopyToClipboardButton';
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import RunningBadge from "./Common/RunningBadge.vue";
|
||||
|
||||
export const profileFrontendProps = {
|
||||
props: {
|
||||
frontendType: String,
|
||||
frontendAdminUri: String,
|
||||
frontendAdminPassword: String,
|
||||
|
@ -110,28 +104,31 @@ export const profileFrontendProps = {
|
|||
frontendStopUri: String,
|
||||
hasStarted: Boolean,
|
||||
userCanManageBroadcasting: Boolean
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
components: {RunningBadge, Icon, CopyToClipboardButton},
|
||||
mixins: [profileFrontendProps],
|
||||
props: {
|
||||
inheritAttrs: false
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import {FRONTEND_ICECAST, FRONTEND_SHOUTCAST} from '~/components/Entity/RadioAdapters.js';
|
||||
import CopyToClipboardButton from '~/components/Common/CopyToClipboardButton';
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import RunningBadge from "~/components/Common/Badges/RunningBadge.vue";
|
||||
import {computed} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
...profileFrontendProps,
|
||||
np: Object
|
||||
},
|
||||
computed: {
|
||||
frontendName() {
|
||||
if (this.frontendType === FRONTEND_ICECAST) {
|
||||
});
|
||||
|
||||
const frontendName = computed(() => {
|
||||
if (props.frontendType === FRONTEND_ICECAST) {
|
||||
return 'Icecast';
|
||||
} else if (this.frontendType === FRONTEND_SHOUTCAST) {
|
||||
} else if (props.frontendType === FRONTEND_SHOUTCAST) {
|
||||
return 'Shoutcast';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
isIcecast () {
|
||||
return this.frontendType === FRONTEND_ICECAST;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -17,24 +17,24 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import PlayButton from "../../Common/PlayButton";
|
||||
|
||||
export const profileHeaderProps = {
|
||||
props: {
|
||||
stationName: String,
|
||||
stationDescription: String,
|
||||
userCanManageProfile: Boolean,
|
||||
manageProfileUri: String
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
np: Object
|
||||
},
|
||||
components: {PlayButton, Icon},
|
||||
mixins: [profileHeaderProps]
|
||||
inheritAttrs: false
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import PlayButton from "~/components/Common/PlayButton.vue";
|
||||
|
||||
const props = defineProps({
|
||||
...profileHeaderProps,
|
||||
np: Object
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -124,45 +124,68 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {BACKEND_LIQUIDSOAP} from '~/components/Entity/RadioAdapters.js';
|
||||
import Icon from '~/components/Common/Icon';
|
||||
|
||||
export const profileNowPlayingProps = {
|
||||
props: {
|
||||
backendType: String,
|
||||
userCanManageBroadcasting: Boolean,
|
||||
backendSkipSongUri: String,
|
||||
backendDisconnectStreamerUri: String
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
components: {Icon},
|
||||
mixins: [profileNowPlayingProps],
|
||||
props: {
|
||||
np: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
npElapsed: 0,
|
||||
clockInterval: null
|
||||
inheritAttrs: false
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import {BACKEND_LIQUIDSOAP} from '~/components/Entity/RadioAdapters.js';
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import {computed, onMounted, ref} from "vue";
|
||||
import {useIntervalFn} from "@vueuse/core";
|
||||
import gettext from "~/vendor/gettext";
|
||||
import formatTime from "~/functions/formatTime";
|
||||
|
||||
const props = defineProps({
|
||||
...profileNowPlayingProps,
|
||||
np: Object
|
||||
});
|
||||
|
||||
const npElapsed = ref(0);
|
||||
|
||||
onMounted(() => {
|
||||
useIntervalFn(
|
||||
() => {
|
||||
let current_time = Math.floor(Date.now() / 1000);
|
||||
let np_elapsed = current_time - props.np.now_playing.played_at;
|
||||
if (np_elapsed < 0) {
|
||||
np_elapsed = 0;
|
||||
} else if (np_elapsed >= props.np.now_playing.duration) {
|
||||
np_elapsed = props.np.now_playing.duration;
|
||||
}
|
||||
|
||||
npElapsed.value = np_elapsed;
|
||||
},
|
||||
mounted() {
|
||||
this.clockInterval = setInterval(this.iterateTimer, 1000);
|
||||
},
|
||||
computed: {
|
||||
langListeners() {
|
||||
let translated = this.$ngettext('%{listeners} Listener', '%{listeners} Listeners', this.np.listeners.total);
|
||||
return this.$gettextInterpolate(translated, {listeners: this.np.listeners.total});
|
||||
},
|
||||
isLiquidsoap() {
|
||||
return this.backendType === BACKEND_LIQUIDSOAP;
|
||||
},
|
||||
timeDisplay() {
|
||||
let time_played = this.npElapsed;
|
||||
let time_total = this.np.now_playing.duration;
|
||||
1000
|
||||
);
|
||||
});
|
||||
|
||||
const {$ngettext} = gettext;
|
||||
|
||||
const langListeners = computed(() => {
|
||||
return $ngettext(
|
||||
'%{listeners} Listener',
|
||||
'%{listeners} Listeners',
|
||||
props.np.listeners.total,
|
||||
{listeners: props.np.listeners.total}
|
||||
);
|
||||
});
|
||||
|
||||
const isLiquidsoap = computed(() => {
|
||||
return props.backendType === BACKEND_LIQUIDSOAP;
|
||||
});
|
||||
|
||||
const timeDisplay = computed(() => {
|
||||
let time_played = npElapsed.value;
|
||||
let time_total = props.np.now_playing.duration;
|
||||
|
||||
if (!time_total) {
|
||||
return null;
|
||||
|
@ -172,39 +195,6 @@ export default {
|
|||
time_played = time_total;
|
||||
}
|
||||
|
||||
return this.formatTime(time_played) + ' / ' + this.formatTime(time_total);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
iterateTimer() {
|
||||
let current_time = Math.floor(Date.now() / 1000);
|
||||
let np_elapsed = current_time - this.np.now_playing.played_at;
|
||||
if (np_elapsed < 0) {
|
||||
np_elapsed = 0;
|
||||
} else if (np_elapsed >= this.np.now_playing.duration) {
|
||||
np_elapsed = this.np.now_playing.duration;
|
||||
}
|
||||
|
||||
this.npElapsed = np_elapsed;
|
||||
},
|
||||
formatTime(time) {
|
||||
let sec_num = parseInt(time, 10);
|
||||
|
||||
let hours = Math.floor(sec_num / 3600);
|
||||
let minutes = Math.floor((sec_num - (hours * 3600)) / 60);
|
||||
let seconds = sec_num - (hours * 3600) - (minutes * 60);
|
||||
|
||||
if (hours < 10) {
|
||||
hours = '0' + hours;
|
||||
}
|
||||
if (minutes < 10) {
|
||||
minutes = '0' + minutes;
|
||||
}
|
||||
if (seconds < 10) {
|
||||
seconds = '0' + seconds;
|
||||
}
|
||||
return (hours !== '00' ? hours + ':' : '') + minutes + ':' + seconds;
|
||||
}
|
||||
}
|
||||
};
|
||||
return formatTime(time_played) + ' / ' + formatTime(time_total);
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -50,7 +50,8 @@
|
|||
<icon icon="code"></icon>
|
||||
{{ $gettext('Embed Widgets') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-danger" :data-confirm-title="langDisablePublicPages" :href="togglePublicPageUri">
|
||||
<a class="btn btn-outline-danger" :data-confirm-title="$gettext('Disable public pages?')"
|
||||
:href="togglePublicPageUri">
|
||||
<icon icon="close"></icon>
|
||||
{{ $gettext('Disable') }}
|
||||
</a>
|
||||
|
@ -65,7 +66,8 @@
|
|||
</h3>
|
||||
</div>
|
||||
<div class="card-actions" v-if="userCanManageProfile">
|
||||
<a class="btn btn-outline-success" :data-confirm-title="langEnablePublicPages" :href="togglePublicPageUri">
|
||||
<a class="btn btn-outline-success" :data-confirm-title="$gettext('Enable public pages?')"
|
||||
:href="togglePublicPageUri">
|
||||
<icon icon="check"></icon>
|
||||
{{ $gettext('Enable') }}
|
||||
</a>
|
||||
|
@ -75,12 +77,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import EmbedModal, {profileEmbedModalProps} from './EmbedModal';
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import EnabledBadge from "./Common/EnabledBadge.vue";
|
||||
import {profileEmbedModalProps} from './EmbedModal';
|
||||
|
||||
export const profilePublicProps = {
|
||||
props: {
|
||||
stationSupportsStreamers: Boolean,
|
||||
stationSupportsRequests: Boolean,
|
||||
enablePublicPage: Boolean,
|
||||
|
@ -94,25 +93,27 @@ export const profilePublicProps = {
|
|||
publicPodcastsUri: String,
|
||||
publicScheduleUri: String,
|
||||
togglePublicPageUri: String
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
components: {EnabledBadge, Icon, EmbedModal},
|
||||
mixins: [profilePublicProps, profileEmbedModalProps],
|
||||
computed: {
|
||||
langDisablePublicPages() {
|
||||
return this.$gettext('Disable public pages?');
|
||||
},
|
||||
langEnablePublicPages() {
|
||||
return this.$gettext('Enable public pages?');
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
doOpenEmbed () {
|
||||
this.$refs.embed_modal.open();
|
||||
}
|
||||
}
|
||||
inheritAttrs: false
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import EnabledBadge from "~/components/Common/Badges/EnabledBadge.vue";
|
||||
import {ref} from "vue";
|
||||
import EmbedModal from "~/components/Stations/Profile/EmbedModal.vue";
|
||||
|
||||
const props = defineProps({
|
||||
...profilePublicProps,
|
||||
...profileEmbedModalProps
|
||||
});
|
||||
|
||||
const embed_modal = ref(); // Template Ref
|
||||
|
||||
const doOpenEmbed = () => {
|
||||
embed_modal.value.open();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
<icon icon="assignment"></icon>
|
||||
{{ $gettext('View') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-danger" v-if="userCanManageProfile" :data-confirm-title="langDisableRequests" :href="requestsToggleUri">
|
||||
<a class="btn btn-outline-danger" v-if="userCanManageProfile"
|
||||
:data-confirm-title="$gettext('Disable song requests?')" :href="requestsToggleUri">
|
||||
<icon icon="close"></icon>
|
||||
{{ $gettext('Disable') }}
|
||||
</a>
|
||||
|
@ -26,7 +27,8 @@
|
|||
</h3>
|
||||
</div>
|
||||
<div class="card-actions" v-if="userCanManageProfile">
|
||||
<a class="btn btn-outline-success" :data-confirm-title="langEnableRequests" :href="requestsToggleUri">
|
||||
<a class="btn btn-outline-success" :data-confirm-title="$gettext('Enable song requests?')"
|
||||
:href="requestsToggleUri">
|
||||
<icon icon="check"></icon>
|
||||
{{ $gettext('Enable') }}
|
||||
</a>
|
||||
|
@ -36,30 +38,23 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import EnabledBadge from "./Common/EnabledBadge.vue";
|
||||
|
||||
export const profileRequestsProps = {
|
||||
props: {
|
||||
enableRequests: Boolean,
|
||||
userCanManageReports: Boolean,
|
||||
userCanManageProfile: Boolean,
|
||||
requestsViewUri: String,
|
||||
requestsToggleUri: String
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
components: {EnabledBadge, Icon},
|
||||
mixins: [profileRequestsProps],
|
||||
computed: {
|
||||
langDisableRequests() {
|
||||
return this.$gettext('Disable song requests?');
|
||||
},
|
||||
langEnableRequests() {
|
||||
return this.$gettext('Enable song requests?');
|
||||
}
|
||||
}
|
||||
inheritAttrs: false
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import Icon from '~/components/Common/Icon';
|
||||
|
||||
const props = defineProps({
|
||||
...profileRequestsProps
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -40,22 +40,27 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
inheritAttrs: false
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import {DateTime} from "luxon";
|
||||
import _ from "lodash";
|
||||
import {computed} from "vue";
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
const props = defineProps({
|
||||
scheduleItems: Array,
|
||||
stationTimeZone: String
|
||||
},
|
||||
computed: {
|
||||
processedScheduleItems() {
|
||||
const now = DateTime.now().setZone(this.stationTimeZone);
|
||||
});
|
||||
|
||||
return _.map(this.scheduleItems, (row) => {
|
||||
const start_moment = DateTime.fromSeconds(row.start_timestamp).setZone(this.stationTimeZone);
|
||||
const end_moment = DateTime.fromSeconds(row.end_timestamp).setZone(this.stationTimeZone);
|
||||
const processedScheduleItems = computed(() => {
|
||||
const now = DateTime.now().setZone(props.stationTimeZone);
|
||||
|
||||
return _.map(props.scheduleItems, (row) => {
|
||||
const start_moment = DateTime.fromSeconds(row.start_timestamp).setZone(props.stationTimeZone);
|
||||
const end_moment = DateTime.fromSeconds(row.end_timestamp).setZone(props.stationTimeZone);
|
||||
|
||||
row.time_until = start_moment.toRelative();
|
||||
|
||||
|
@ -81,7 +86,5 @@ export default {
|
|||
|
||||
return row;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
<icon icon="settings"></icon>
|
||||
{{ $gettext('Manage') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-danger" v-if="userCanManageProfile" :data-confirm-title="langDisableStreamers" :href="streamersToggleUri">
|
||||
<a class="btn btn-outline-danger" v-if="userCanManageProfile"
|
||||
:data-confirm-title="$gettext('Disable streamers?')" :href="streamersToggleUri">
|
||||
<icon icon="close"></icon>
|
||||
{{ $gettext('Disable') }}
|
||||
</a>
|
||||
|
@ -26,7 +27,8 @@
|
|||
</h3>
|
||||
</div>
|
||||
<div class="card-actions" v-if="userCanManageProfile">
|
||||
<a class="btn btn-outline-success" :data-confirm-title="langEnableStreamers" :href="streamersToggleUri">
|
||||
<a class="btn btn-outline-success" :data-confirm-title="$gettext('Enable streamers?')"
|
||||
:href="streamersToggleUri">
|
||||
<icon icon="check"></icon>
|
||||
{{ $gettext('Enable') }}
|
||||
</a>
|
||||
|
@ -36,30 +38,24 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import EnabledBadge from "./Common/EnabledBadge.vue";
|
||||
|
||||
export const profileStreamersProps = {
|
||||
props: {
|
||||
enableStreamers: Boolean,
|
||||
userCanManageProfile: Boolean,
|
||||
userCanManageStreamers: Boolean,
|
||||
streamersViewUri: String,
|
||||
streamersToggleUri: String
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
components: {EnabledBadge, Icon},
|
||||
mixins: [profileStreamersProps],
|
||||
computed: {
|
||||
langDisableStreamers() {
|
||||
return this.$gettext('Disable streamers?');
|
||||
},
|
||||
langEnableStreamers() {
|
||||
return this.$gettext('Enable streamers?');
|
||||
}
|
||||
}
|
||||
inheritAttrs: false
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import Icon from "~/components/Common/Icon.vue";
|
||||
import EnabledBadge from "~/components/Common/Badges/EnabledBadge.vue";
|
||||
|
||||
const props = defineProps({
|
||||
...profileStreamersProps
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -102,14 +102,16 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
inheritAttrs: false
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import Icon from '~/components/Common/Icon';
|
||||
import PlayButton from "~/components/Common/PlayButton";
|
||||
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
components: {PlayButton, Icon},
|
||||
props: {
|
||||
const props = defineProps({
|
||||
np: Object
|
||||
}
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue
Block a user