Skip to content
Snippets Groups Projects
PlaylistSelector.vue 10.9 KiB
Newer Older
  • Learn to ignore specific revisions
  •     <div>
            <b-modal
    
                ref="modalPlaylistSelector"
                :title="$t('playlistSelector.title')"
                :cancel-title="$t('cancel')"
                size="lg"
    
            >
                <p v-if="loaded">
    
                    {{ $t('playlistSelector.currentPlaylistLabel') }}:
    
    
                    <span v-if="timeslot === null || timeslot.playlist_id === null">
    
                        <i><small>{{ $t('noneSetFeminine') }}</small></i>
    
                    <span v-else>
    
                        {{ timeslot.playlist_id }}<br>
                        <span v-if="currentPlaylistDescription"> {{ $t('showMeta.description') }}: <b>{{ currentPlaylistDescription }}</b></span>
    
                </p>
    
                <div v-if="loaded">
    
                    <div v-if="playlists.length">
                        <b-table
    
                            ref="playlistsTable"
                            striped
                            :fields="playlistsTableFields"
                            :items="playlists"
    
                        >
                            <!-- Column: Entries
                            This column displays the number of entries of the playlist.
                            -->
    
                            <template #cell(entries)="data">
    
                                    v-b-tooltip.html="playlistToolTip(data.value)"
                                    class="tw-underline hover:tw-no-underline tw-cursor-help"
    
                                    {{ $t('playlistTable.items', { smart_count: data.value.length }) }}
    
                                </span>
                            </template>
    
    
                            <!-- Column: Duration
                            This column displays the number of entries of the playlist.
                            -->
    
                            <template #cell(duration)="data">
                                <span
    
                                    :class="{'is-mismatched': isMismatchedLength(data) }"
    
                                >
                                    {{ playlistDuration(data.item) }}
                                    <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 #cell(actions)="data">
    
                                <b-button-group size="sm">
                                    <b-button
    
                                        v-if="data.item.id !== timeslot.playlist_id"
                                        variant="info"
                                        @click="choose(data)"
    
                                        {{ $t('playlistTable.assign') }}
    
                                        v-else
                                        variant="danger"
                                        @click="choose(null)"
    
                                        {{ $t('playlistTable.unset') }}
    
                                    </b-button>
                                </b-button-group>
                            </template>
                        </b-table>
                    </div>
    
                    <!-- If no playlists are available -->
                    <div
    
                        v-else
                        class="tw-mb-4"
    
                    >
                        {{ $t('playlistSelector.noPlaylistsAvailable') }}
                    </div>
    
                </div>
    
                <div v-else>
                    <img
    
                        src="/assets/radio.gif"
                        :alt="$t('loading')"
    
                <div>
                    <div class="tw-space-x-2">
                        <b-button :to="'files'">
                            {{ $t('playlistSelector.goToFiles') }}
                        </b-button>
    
                        <b-button
    
                            v-if="!audioUpload"
                            v-model="audioFile"
                            @click="toggleAudioUpload"
    
                        >
                            {{ $t('playlistSelector.uploadAudio') }}
                        </b-button>
                    </div>
    
                    <div
    
                        v-if="audioUpload"
                        class="tw-mt-4 tw-space-x-2 tw-flex"
    
                            v-model="audioFile"
                            accept="audio/*"
    
                            :disabled="!audioFile"
                            @click="upload"
    
                        >
                            {{ $t('playlistSelector.upload') }}
                        </b-button>
                    </div>
    
                </div>
            </b-modal>
        </div>
    
        import {mapGetters} from 'vuex'
    
    
        import prettyDate from '@/mixins/prettyDate'
        import playlist from '@/mixins/playlist'
    
    
        export default {
    
            mixins: [prettyDate, playlist],
    
    
            data() {
                return {
                    scheduleId: null,
                    timeslot: null,
    
    
                    audioFile: null,
                    audioUpload: false,
                    audioUploadError: '',
    
                }
            },
    
            computed: {
                loaded() {
                    return this.$store.state.playlists.loaded.playlists
                },
    
    
                playlistsTableFields() {
                    return [
                        {key: 'id', label: this.$t('playlistTable.index') },
                        {key: 'description', label: this.$t('playlistTable.description') },
                        {key: 'entries', label: this.$t('playlistTable.entries') },
                        {key: 'duration', label: this.$t('playlistTable.duration') },
                        {key: 'actions', label: this.$t('playlistTable.actions'), class: 'text-right'},
                    ]
                },
    
    
                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).minutes,
    
                        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: {
    
                    event.preventDefault()
                    event.stopPropagation()
    
                        this.audioUploadError = this.$t('playlistSelector.missingFile')
    
                        return
    
                    this.audioUpload = false
    
                    this.$store.dispatch('files/addFile', {
                        show: this.selectedShow.slug,
                        uploadSourceFile: this.audioFile,
                        callback: this.handleUploadedFile,
                    })
                },
    
                handleUploadedFile() {
                    this.$store.dispatch('files/fetchFiles', {
                        slug: this.selectedShow.slug,
                        callback: this.createPlaylistForUploadedFile
                    })
                },
    
                createPlaylistForUploadedFile(files) {
                    const file = files.slice(-1)[0]
    
                    const {slug} = this.selectedShow
    
                    const playlist = {
                        description: 'Automatisch erstellt durch Dateiupload',
    
                        entries: [{file}]
    
                    }
    
                    this.$store.dispatch('playlists/add', {
                        slug,
                        playlist,
                    })
                },
    
                toggleAudioUpload() {
                    this.audioUpload = !this.audioUpload
                },
    
    
                open(scheduleId, timeslotId) {
    
                    this.audioFile = null
                    this.audioUpload = false
    
                    this.scheduleId = scheduleId
                    this.timeslot = this.getTimeslotById(timeslotId)
                    this.$refs.modalPlaylistSelector.show()
                },
    
                choose(data) {
                    const {item} = data || {}
                    const {id} = item || {}
                    let confirmed = true
    
                    if (data && this.isMismatchedLength(data)) {
    
                        confirmed = confirm(this.$t('playlistSelector.mismatchedLengthConfirmation'))
    
                    }
    
                    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 this.$t('playlistSelector.mismatchedLength')
    
                    }
    
                    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
                },
    
                isMismatchedLength(playlist) {
    
                    const totalDuration = this.playlistDuration(playlist.item)
                    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