Newer
Older
<template>
<div>
<b-modal
ref="modalPlaylistSelector"
title="Edit playlist for this timeslot"
size="lg"
>

jackie / Andrea Ida Malkah Klaura
committed
<p v-if="loaded">
Currently chosen playlist ID:
<span v-if="timeslot === null || timeslot.playlist_id === null">
<i><small>(none set)</small></i>
</span>
<span v-else>
{{ timeslot.playlist_id }}
<span v-if="currentPlaylistDescription">
, Description: <b>{{ currentPlaylistDescription }}</b>
</span>
</span>
</p>
<p>Available playlists:</p>
<div v-if="loaded">
<b-table
ref="playlistsTable"
striped
:fields="playlistsTableFields"
:items="playlists"
>
<!-- Column: Entries
This column displays the number of entries of the playlist.
-->
<template v-slot:cell(entries)="data">
v-b-tooltip.html="playlistToolTip(data.value)"
class="tw-underline hover:tw-no-underline tw-cursor-help"
{{ data.value.length }} items
</span>
</template>
<!-- Column: Duration
This column displays the number of entries of the playlist.
-->
<template v-slot:cell(duration)="data">
<span
:class="{'is-mismatched': isMismatchedLength(data) }"
>
{{ playlistDuration(data) }}
<abbr
v-if="isMismatchedLength(data)"
:title="title(data)"
>
(?)
</abbr>
</span>
</template>
<!-- Column: Actions
This column displays the available buttons for actions the user can
take on this playlist (e.g. editing and deleting).
-->
<template v-slot:cell(actions)="data">
<b-button-group size="sm">
<b-button
v-if="data.item.id !== timeslot.playlist_id"
variant="info"
@click="choose(data)"
>
Take it!
</b-button>
<b-button
v-else
variant="danger"
@click="choose(null)"
>
Unset
</b-button>
</b-button-group>
</template>
</b-table>
</div>
<div v-else>
<img

Richard Blechinger
committed
src="/assets/radio.gif"
alt="loading playlists"
>
</div>

jackie / Andrea Ida Malkah Klaura
committed
<div align="center">
<b-button :to="'files'">
Go to FileManager
</b-button>
</div>
</b-modal>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import prettyDate from '../../mixins/prettyDate'
export default {
mixins: [ prettyDate ],
data () {
return {
scheduleId: null,
timeslot: null,
playlistsTableFields: [
{ key: 'id', label: 'Index' },
{ key: 'description', label: 'Description' },
{ key: 'entries', label: 'Entries' },
{ key: 'duration', label: 'Duration' },
{ key: 'actions', label: 'Actions', class: 'text-right' },
],
}
},
computed: {
loaded () { return this.$store.state.playlists.loaded.playlists },
timeslotDurationInNs() {
const mm = this.timeslotDuration % 60;
const hh = (this.timeslotDuration - mm) / 60;
return this.hmsToNanoseconds(
`${this.leadingZero(hh)}:${this.leadingZero(mm)}:00`
);
},
timeslotDuration() {
const { start, end } = this.timeslot
return parseInt(
this.prettyDuration(start, end),
10
)
},
currentPlaylistDescription () {
let description = false
if (this.timeslot && this.timeslot.playlist_id !== null) {
let choosenList = this.playlists.find(list => list.id === this.timeslot.playlist_id)
if (choosenList && choosenList.description.length > 0) {
description = choosenList.description
}
}
return description
},
...mapGetters({
selectedShow: 'shows/selectedShow',
timeslots: 'shows/timeslots',
notes: 'shows/notes',
playlists: 'playlists/playlists',
getTimeslotById: 'shows/getTimeslotById',
})
},
methods: {
open (scheduleId, timeslotId) {
this.scheduleId = scheduleId
this.timeslot = this.getTimeslotById(timeslotId)
this.$refs.modalPlaylistSelector.show()
},
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
choose (data) {
const { item } = data || {}
const { id } = item || {}
let confirmed = true
if (data && this.isMismatchedLength(data)) {
confirmed = confirm("The playlist you have selected has a different length than the timeslot. Proceed?")
}
if (confirmed) {
let ts = {...this.timeslot}
ts.playlist_id = id
this.$store.dispatch('shows/updateTimeslot', {
show: this.selectedShow.id,
schedule: this.scheduleId,
timeslot: ts,
callback: () => { this.timeslot = this.getTimeslotById(ts.id) }
})
}
},
title(data) {
if (this.isMismatchedLength(data)) {
return "Playlist is not the same length as the timeslot"
}
return ""
},
playlistToolTip (entries) {
let text = '<div style="white-space: nowrap;" align="left">'
for (let i in entries) {
text += i + ': ' + entries[i].uri + '<br>'
}
text += '</div>'
return text
},
playlistDuration({ item }) {
if (!item.entries) {
return 0;
}
let delta = 0;
const totalDuration = item.entries.reduce((acc, entry) => {
const newDuration = acc + this.durationInSeconds(entry.duration);
if (Number.isNaN(newDuration)) {
return acc;
}
const unknowns = item.entries.filter(entry => !entry.duration);
if (unknowns.length === 1) {
delta = this.durationInSeconds(this.timeslotDurationInNs) - totalDuration;
const totalDurationInNanoseconds = (totalDuration + delta) * 1000 * 1000 * 1000
return this.prettyNanoseconds(totalDurationInNanoseconds)
},
isMismatchedLength(playlist) {
const totalDuration = this.playlistDuration(playlist);
let delta = 0;
const unknowns = playlist.item.entries.filter(entry => !entry.duration);
if (unknowns.length === 1) {
delta = this.timeslotDurationInNs - totalDuration;
}
return this.timeslotDurationInNs !== totalDuration + delta;
},
}
}
</script>
<style scoped>
.is-mismatched {
color: var(--orange);
}