Skip to content
Snippets Groups Projects
ModalEdit.vue 18.1 KiB
Newer Older
    <div>
        <b-modal
            ref="modalEmissionManagerEdit"
            :title="$t('scheduleEditor.titleEdit', { show: selectedShow.name })"
            size="lg"
            <server-errors :errors="serverErrors" />

            <div v-if="timeslot && loaded.schedule">
                <p
                    class="tw-mb-0"
                    v-html="$t('scheduleEditor.timeslotRuns', {
                        firstDate: prettyDate(timeslot.start),
                        startTime: prettyTime(timeslot.start),
                        endTime: prettyTime(timeslot.end),

                <div v-if="schedule.rrule === 1">
                    <p>
                        {{ $t('scheduleEditor.singleEmission') }}
                        <span v-if="!loaded.scheduleTimeslots">
                                src="/assets/radio.gif"
                                :alt="$t('loading')"
                        <span v-else>
                            <span
                                v-if="scheduleTimeslots.length > 1"
                                v-html="'<br>' + $t('scheduleEditor.coexistingTimeslot', {
                                    firstDate: timeslot.start === scheduleTimeslots[0].start ? prettyDate(scheduleTimeslots[1].start) : prettyDate(scheduleTimeslots[0].start),
                                    startTime: timeslot.start === scheduleTimeslots[0].start ? prettyTime(scheduleTimeslots[1].start) : prettyTime(scheduleTimeslots[0].start),
                                    endTime: timeslot.start === scheduleTimeslots[0].start ? prettyTime(scheduleTimeslots[1].end) : prettyTime(scheduleTimeslots[0].end),
                    </p>
                </div>
                <div v-else>
                    <p
                        v-html="$t('scheduleEditor.recurringSchedule', {
                            rrule: rruleRender(schedule.rrule),
                            lastDate: prettyDate(schedule.last_date),

                    <b-table
                        id="emission-table"
                        striped
                        :per-page="perPage"
                        :current-page="currentPage"
                        :fields="[
                            { key: 'start', label: $t('scheduleEditor.start') },
                            { key: 'end', label: $t('scheduleEditor.end') }
                        ]"
                        :items="scheduleTimeslots"
                        :busy="!loaded.scheduleTimeslots"
                        :tbody-tr-class="trClass"
                        <template #cell(start)="data">
                            {{ prettyDateTime(data.item.start) }}
                        </template>

                        <template #cell(end)="data">
                            {{ prettyDateTime(data.item.end) }}
                        </template>
                    </b-table>

                    <div class="tw-w-full tw-flex tw-justify-end">
                        <b-pagination
                            v-model="currentPage"
                            :total-rows="scheduleTimeslots.length"
                            :per-page="perPage"
                            aria-controls="emission-table"
                        />
                    </div>
                </div>
            </div>
            <div v-else>
                <img
                    src="/assets/radio.gif"
                    :alt="$t('loading')"
            <h4>{{ $t('scheduleEditor.addRepetition') }}</h4>
            <b-row>
                <b-col cols="6">
                    <label class="tw-leading-loose">
                        {{ $t('scheduleEditor.whenToRepeat') }}

                        <b-form-select
                            v-model="repetitionRule"
                            :options="repetitionOptions"
                        v-if="repetitionRule !== 4"
                        v-model="useSameTime"
                        {{ $t('scheduleEditor.useSameTime') }}
                    </b-checkbox>
                </b-col>
                <b-col
                    v-if="!useSameTime"
                    cols="6"
                >
                    <label class="tw-leading-loose">
                        {{ $t('scheduleEditor.repeatAt') }}
                        <b-form-input
                            v-model="repetitionTime"
                            type="time"
                        />
                    </label>
                </b-col>
            </b-row>

            <b-row
                v-if="repetitionRule === 3"
                class="tw-mt-4"
                <b-col cols="6">
                    <label class="tw-leading-loose">
                        {{ $t('scheduleEditor.addNoOfDays') }}

                        <b-form-input
                            v-model="addNoOfDays"
                            type="number"
                        />
                    </label>

                    <b-checkbox v-model="onlyBusinessDays">
                        {{ $t('scheduleEditor.onlyBusinessDays') }}
                    </b-checkbox>
                </b-col>
            </b-row>

            <b-row class="my-4">
                <b-col>
                    <b-button
                        variant="primary"
                        size="sm"
                        @click="createRepetitionSchedule"
                        {{ $t('scheduleEditor.addRepetition') }}
                    </b-button>
                </b-col>
            </b-row>

            <hr>
            <h4>Fallback für Ausstrahlungs-Schema hinzufügen</h4>
            <b-row class="tw-px-4">
                    <strong>Momentan hinterlegte Playlist:</strong> (keine)
                <div class="tw-w-full tw-block">
                    <b-button variant="primary">
                        {{ $t('scheduleEditor.assignPlaylist') }}
                    </b-button>
                </div>
            <template #modal-footer>
                <div
                    v-if="loaded.scheduleTimeslots"
                    class="tw-w-full tw-flex tw-justify-between tw-items-center"
                >
                    <div class="tw-space-x-2">
                                variant="danger"
                                size="sm"
                                @click="deleteFullSchedule(schedule.id)"
                            >
                                <span v-if="scheduleTimeslots.length === 1">{{ $t('scheduleEditor.delete.delete') }}</span>
                                <span v-else-if="schedule.rrule === 1">{{ $t('scheduleEditor.delete.both') }}</span>
                                <span v-else>{{ $t('scheduleEditor.delete.scheduleTimeslots') }}</span>
                            </b-button>
                                v-if="schedule.rrule > 1 && scheduleTimeslots.length > 1"
                                variant="danger"
                                size="sm"
                                @click="deleteSingleTimeslot(schedule.id, timeslot.id)"
                            >
                                {{ $t('scheduleEditor.delete.timeslot') }}
                            </b-button>
                        </template>

                        <b-button
                            v-if="schedule.rrule > 1 && scheduleTimeslots.length > 1"
                            variant="danger"
                            size="sm"
                            @click="deleteAllFutureTimeslots(schedule.id, timeslot.id)"
                            {{ $t('scheduleEditor.delete.allTimeslots') }}
                        </b-button>
                    </div>
                </div>
                <div v-else>
                    <img
                        src="/assets/radio.gif"
                        :alt="$t('loading')"
                    >
                </div>
            </template>
        </b-modal>

        <b-modal
            ref="modalEmissionManagerDeleteTimeslots"
            :title="$t('scheduleEditor.delete.timeslotsTitle')"
            size="lg"
            centered
            hide-footer
            no-close-on-esc
            no-close-on-backdrop
            <div>
                <img
                    src="/assets/radio.gif"
                    :alt="$t('loading')"
                >
                <b-progress
                    :value="deletion.count"
                    :max="deletion.amount"
                    variant="primary"
                    animated
                />
            </div>
        </b-modal>
    </div>
    import {mapGetters} from 'vuex'
    import prettyDate from '../../mixins/prettyDate'
    import rrules from '../../mixins/rrules'
    import ServerErrors from '@/components/ServerErrors.vue'

    export default {
        components: {ServerErrors},
        mixins: [prettyDate, rrules],

        data() {
            return {
                currentPage: 1,
                perPage: 5,
                timeslot: null,
                deletion: {
                    amount: 0,
                    count: 0,
                },
                useSameTime: true,
                onlyBusinessDays: false,
                addNoOfDays: 1,
                repetitionRule: 1,
                repetitionTime: '',
        },

        computed: {
            loaded() {
                return {
                    shows: this.$store.state.shows.loaded.shows,
                    schedule: this.$store.state.shows.loaded.schedule,
                    scheduleTimeslots: this.$store.state.shows.loaded.scheduleTimeslots,
                }
            },

                    {value: 1, text: this.$t("scheduleEditor.repetition.followingDay")},
                    {value: 2, text: this.$t("scheduleEditor.repetition.followingBusinessDay")},
                    {value: 3, text: this.$t("scheduleEditor.repetition.numberOfDaysLater")},
            ...mapGetters({
                selectedShow: 'shows/selectedShow',
                schedule: 'shows/schedule',
                scheduleTimeslots: 'shows/scheduleTimeslots',
            })
        },

        methods: {
            trClass(item, type) {
                if (!item || type !== 'row') {
                    return ''
                return item.id === this.timeslot.id
                    ? 'table-info'
                    : ''
            },

                const start = new Date(timeslot.start)
                const now = new Date()
                return start > now
            async createRepetitionSchedule() {
                const {onlyBusinessDays, addNoOfDays} = this.getRepetitionParameters()
                let {first_date, time_start, time_end, rrule, last_date, default_playlist_id, automation_id, by_weekday} = this.schedule

                if (this.repetitionTime.length > 0) {
                  const newStartTime = `${this.repetitionTime}:00`
                  const newStartTimeNs = this.hmsToNanoseconds(newStartTime)
                  const oldStartTimeNs = this.hmsToNanoseconds(time_start)
                  const oldEndTimeNs = this.hmsToNanoseconds(time_end)
                  time_start = newStartTime
                  time_end = this.prettyNanoseconds(newStartTimeNs + (oldEndTimeNs - oldStartTimeNs))

                const newSchedule = {
                    schedule: {
                        first_date,
                        time_start,
                        time_end,
                        rrule,
                        automation_id,
                        is_repetition: true,
                        add_business_days_only: onlyBusinessDays,
                        add_days_no: parseInt(addNoOfDays, 10),
                this.serverErrors = []
                try {
                    await this.$store.dispatch('shows/submitSchedule', {
                        showId: this.selectedShow.id,
                        schedule: newSchedule,
                    })
                    this.$parent.renderView(null)
                } catch (e) {
                    if (e.response?.status === 409) {
                        this.$log.debug('Timeslot conflict. Switching to resolve mode.')
                        this.$parent.resolve(e.response.data)
                    } else {
                        this.serverErrors = e.errors ?? []
                    }
                } finally {
                    this.$refs.modalEmissionManagerEdit.hide()
                }
            },

            deleteFullSchedule(id) {
                this.$store.dispatch('shows/deleteSchedule', {
                    show: this.selectedShow.id,
                    schedule: id,
                    callback: () => {
                        this.$refs.modalEmissionManagerEdit.hide()
                        this.$parent.renderView(null)
                    }
                })
            },

            deleteSingleTimeslot(scheduleId, timeslotId) {
                this.$store.dispatch('shows/deleteTimeslot', {
                    show: this.selectedShow.id,
                    schedule: scheduleId,
                    timeslot: timeslotId,
                    callback: () => {
                        this.$refs.modalEmissionManagerEdit.hide()
                        this.$parent.renderView(null)
                    }
                })
            },

            deleteAllFutureTimeslots(scheduleId) {
                let startDate = new Date(this.timeslot.start)
                let toDelete = []
                for (let slot of this.scheduleTimeslots) {
                    if (new Date(slot.start) >= startDate) {
                        toDelete.push(slot.id)
                    }
                }

                if (toDelete.length === this.scheduleTimeslots.length) {
                    this.$log.debug('deleting full schedule')
                    this.deleteFullSchedule(scheduleId)
                } else {
                    this.deletion.amount = toDelete.length
                    this.deletion.count = 0
                    this.$refs.modalEmissionManagerDeleteTimeslots.show()

                    for (let i in toDelete) {
                        this.$log.debug('Deleting timeslot', toDelete[i])
                        this.$store.dispatch('shows/deleteTimeslot', {
                            show: this.selectedShow.id,
                            schedule: scheduleId,
                            timeslot: toDelete[i],
                            callback: () => {
                                this.deletion.count++
                                this.$log.debug('deleted ' + this.deletion.count + ' timeslots')
                                if (this.deletion.count === this.deletion.amount) {
                                    this.$parent.renderView(null)
                                    this.$refs.modalEmissionManagerDeleteTimeslots.hide()
                                    this.$refs.modalEmissionManagerEdit.hide()
                                }
                            }
                        })
                    }
                }
            },

            loadSchedule(scheduleId) {
                this.$store.dispatch('shows/fetchSchedule', {
                    show: this.selectedShow.id,
                    schedule: scheduleId,
                    callback: () => {
                        this.loadScheduleTimeslots(scheduleId)
                    }
                })
            },

            loadScheduleTimeslots(scheduleId) {
                this.$store.dispatch('shows/fetchTimeslots', {
                    id: this.selectedShow.id,
                    schedule: scheduleId,
                    start: this.schedule.first_date,
                    end: this.schedule.last_date,
                })
            },

            getRepetitionParameters() {
                if (this.repetitionRule == 1) {
                    return {
                        onlyBusinessDays: false,
                        addNoOfDays: 1,
                    }
                }

                if (this.repetitionRule == 2) {
                    return {
                        onlyBusinessDays: true,
                        addNoOfDays: 1,
                    }
                }

                return {
                    onlyBusinessDays: this.onlyBusinessDays,
                    addNoOfDays: this.addNoOfDays,
                }
            },

            // initialise a new schedule and open the modal
            open(timeslot) {
                const timeslotIndex = this.scheduleTimeslots.findIndex(item => item.id === timeslot.id)
                let timeslotPage = Math.ceil(timeslotIndex / this.perPage)
                const timeslotIsFirstEntryOnPage = timeslotIndex === ((timeslotPage) * this.perPage)

                // The math above is slightly off for every first entry on the page
                // So we add 1 to adjust the page to the correct one
                if (timeslotIsFirstEntryOnPage) {
                    timeslotPage += 1
                this.timeslot = timeslot
                this.currentPage = timeslotPage
                this.$refs.modalEmissionManagerEdit.show()
                this.loadSchedule(timeslot.schedule)
            },