Skip to content
Snippets Groups Projects
shows.js 19.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • import { APIError, callOrReturn, handleApiError } from '../api-helper'
    
    const cloneMinimalShowObject = function (show) {
    
        /* returns a new minimal object from the current show object with all
        properties needed for a PUT request to the /show/ endpoint */
        let s = {}
        s.name = show.name
        s.slug = show.slug
        s.short_description = show.short_description
        s.fundingcategory = show.fundingcategory
        s.type = show.type
        // we do not want the arrays do be passed as references, because the
        // current show object should not get modified when the update object
        // gets modified, therefore we use slice to clone the arrays
        s.category = show.category.slice()
        s.hosts = show.hosts.slice()
        s.owners = show.owners.slice()
        s.language = show.language.slice()
        s.topic = show.topic.slice()
        s.musicfocus = show.musicfocus.slice()
        return s
    
        shows: [],
        schedule: null,
        schedules: [],
        scheduleTimeslots: [],
        timeslots: [],
        notes: [],
        types: [],
        fundingcategories: [],
        categories: [],
        topics: [],
        musicfocus: [],
        languages: [],
        hosts: [],
        loaded: {
            shows: false,
            timeslots: false,
            notes: false,
            schedule: false,
            scheduleTimeslots: false,
            schedules: false,
            types: false,
            fundingcategories: false,
            categories: false,
            topics: false,
            musicfocus: false,
            languages: false,
            hosts: false,
        },
        selected: {
            index: 0, // index of the currently selected show in our shows array
            id: 0,    // actual id of the currently selected show
        }
    
        shows: state => state.shows,
        selectedShow: state => state.shows[state.selected.index],
        schedule: state => state.schedule,
        schedules: state => state.schedules,
        scheduleTimeslots: state => state.scheduleTimeslots,
        timeslots: state => state.timeslots,
        notes: state => state.notes,
        types: state => state.types,
        fundingcategories: state => state.fundingcategories,
        categories: state => state.categories,
        topics: state => state.topics,
        musicfocus: state => state.musicfocus,
        languages: state => state.languages,
        hosts: state => state.hosts,
        getShowByDataParam: state => data => {
            let show
            if (data.id !== undefined) {
                show = state.shows.find(s => s.id === data.id)
                if (show === undefined) {
                    console.log('[ERROR] getShowByDataParam: ID not found in store!')
                }
            } else if (data.index !== undefined) {
                show = state.shows[data.index]
            } else {
                console.log('[ERROR] getShowByDataParam: no ID or index was provided')
            }
            return show
        },
        getTimeslotById: state => id => {
            return state.timeslots.find(s => s.id === id)
    
        loading(state, item) {
            state.loaded[item] = false
        },
        finishLoading(state, item) {
            state.loaded[item] = true
        },
    
        setShows(state, shows) {
            state.shows = shows
        },
        addShow(state, show) {
            state.shows.push(show)
            state.shows.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase())
        },
    
        setSchedule(state, schedule) {
            state.schedule = schedule
        },
        setSchedules(state, schedules) {
            state.schedules = schedules
        },
        setScheduleTimeslots(state, slots) {
            state.scheduleTimeslots = slots
        },
    
        setTimeslots(state, slots) {
            state.timeslots = slots
        },
        setTimeslot(state, slot) {
            let index = state.timeslots.findIndex(s => s.id === slot.id)
            state.timeslots.splice(index, 1, slot)
        },
    
        setNotes(state, notes) {
            state.notes = notes
        },
        addNote(state, note) {
            state.notes.push(note)
        },
        setNote(state, note) {
            let index = state.notes.findIndex(n => n.id === note.id)
            state.notes.splice(index, 1, note)
        },
    
        setName(state, data) {
            let index = state.shows.findIndex(s => s.id === data.id)
            state.shows[index].name = data.text
        },
        setShortDescription(state, data) {
            let index = state.shows.findIndex(s => s.id === data.id)
            state.shows[index].short_description = data.text
        },
        setDescription(state, data) {
            let index = state.shows.findIndex(s => s.id === data.id)
            state.shows[index].description = data.text
        },
        setActive(state, data) {
            let index = state.shows.findIndex(s => s.id === data.id)
            state.shows[index].is_active = data.active
        },
        setProperty(state, data) {
            let index = state.shows.findIndex(s => s.id === data.id)
            state.shows[index][data.property] = data.value
        },
    
        setMetaArray(state, data) {
            state[data.property] = data.value
        },
    
        switchShow(state, index) {
            if (state.loaded.shows) {
                state.selected.index = index
                state.selected.id = state.shows[index].id
            }
        },
        switchShowById(state, id) {
            if (state.loaded.shows) {
                state.selected.index = state.shows.findIndex(s => s.id === id)
                state.selected.id = id
            }
        },
    
        fetchShows(ctx, data) {
    
            const user = ctx.rootState.auth.user.steeringUser
    
            ctx.commit('loading', 'shows')
            let uri = process.env.VUE_APP_API_STEERING + 'shows'
            // normal users should only see their own shows, only superusers see all shows
            if (user && !user.is_superuser) {
                uri += '?owner=' + ctx.rootState.auth.user.steeringUser.id
            }
            axios.get(uri, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(response => {
                ctx.commit('setShows', response.data)
                ctx.commit('finishLoading', 'shows')
                if (data && typeof (data.callback) === 'function') {
                    data.callback()
                }
            }).catch(error => {
                handleApiError(this, error, 'could not load shows')
    
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
            })
        },
    
        fetchSchedule(ctx, data) {
            ctx.commit('loading', 'schedule')
            let uri = process.env.VUE_APP_API_STEERING + 'shows/' + data.show +
                '/schedules/' + data.schedule + '/'
            axios.get(uri, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(response => {
                ctx.commit('setSchedule', response.data)
                ctx.commit('finishLoading', 'schedule')
                if (data && typeof (data.callback) === 'function') {
                    data.callback(response)
                }
            }).catch(error => {
                handleApiError(this, error, 'could not load schedule')
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
            })
        },
    
        fetchSchedules(ctx, data) {
            ctx.commit('loading', 'schedule')
            let uri = process.env.VUE_APP_API_STEERING + 'shows/' + data.show + '/schedules/'
    
            axios.get(uri, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(response => {
                ctx.commit('setSchedules', response.data)
                ctx.commit('finishLoading', 'schedule')
                if (data && typeof (data.callback) === 'function') {
                    data.callback(response)
                }
            }).catch(error => {
                handleApiError(this, error, 'could not load schedule')
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
            })
        },
    
        fetchTimeslots(ctx, data) {
            if (data.schedule !== undefined) {
                ctx.commit('loading', 'scheduleTimeslots')
    
                ctx.commit('loading', 'timeslots')
            }
    
            let uri
            if (data.id !== undefined) {
                uri = process.env.VUE_APP_API_STEERING + 'shows/' + data.id
    
                if (data.schedule !== undefined) {
                    uri += '/schedules/' + data.schedule + '/timeslots/?'
                } else {
                    uri += '/timeslots/?'
                }
    
    
                if (data.surrounding) {
                    uri += 'surrounding'
                }
    
            } else {
                uri = process.env.VUE_APP_API_STEERING + 'timeslots?'
            }
    
    
            if (!data.surrounding) {
                uri += 'start=' + data.start
                uri += '&end=' + data.end
                if (data.limit) {
                    uri += '&limit=' + data.limit
                }
                if (data.offset) {
                    uri += '&offset=' + data.offset
                }
    
            axios.get(uri, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(response => {
                if (data.schedule !== undefined) {
                    ctx.commit('setScheduleTimeslots', response.data)
                    ctx.commit('finishLoading', 'scheduleTimeslots')
                } else {
                    if (data.limit) {
                        ctx.commit('setTimeslots', response.data.results)
                    } else {
                        ctx.commit('setTimeslots', response.data)
                    }
                    ctx.commit('finishLoading', 'timeslots')
                }
                if (data && typeof (data.callback) === 'function') {
                    data.callback(response)
                }
            }).catch(error => {
                handleApiError(this, error, 'could not load timeslots')
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
            })
        },
    
        fetchNotes(ctx, data) {
            ctx.commit('loading', 'notes')
            // we only have to make an API call if there are actually any notes
            // otherwise the notes are just and empty array
            if (data.notes.length === 0) {
                ctx.commit('setNotes', [])
                ctx.commit('finishLoading', 'notes')
                return
            }
            let uri = process.env.VUE_APP_API_STEERING_SHOWS + data.id + '/notes/?ids='
            for (let id of data.notes) {
                uri += id + ','
            }
            uri = uri.slice(0, -1) // now remove trailing ','
            this.$log.debug('fetchNotes: uri:', uri)
            axios.get(uri, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(response => {
                ctx.commit('setNotes', response.data)
                ctx.commit('finishLoading', 'notes')
                if (data && typeof (data.callback) === 'function') {
                    data.callback(response)
                }
            }).catch(error => {
                handleApiError(this, error, 'could not load notes')
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
            })
        },
    
        fetchMetaArray(ctx, data) {
            ctx.commit('loading', data.property)
            let uri = process.env.VUE_APP_API_STEERING + data.property + '/'
            if (data.onlyActive === true) {
                uri += '?active=true'
            }
            axios.get(uri, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(response => {
                ctx.commit('setMetaArray', {property: data.property, value: response.data})
                ctx.commit('finishLoading', data.property)
                if (data && typeof (data.callback) === 'function') {
                    data.callback()
                }
            }).catch(error => {
                handleApiError(this, error, 'could not load ' + data.property)
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
            })
        },
    
        submitSchedule(ctx, data) {
            ctx.commit('loading', 'schedules')
            let uri = process.env.VUE_APP_API_STEERING_SHOWS + data.showId + '/schedules/'
    
            return axios.post(uri, data.schedule, {
    
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(response => {
                ctx.commit('finishLoading', 'schedules')
    
                return callOrReturn(response, data?.callback)
    
            }).catch(error => {
    
                APIError.handle(error, 'Unable to submit schedule', data, this)
    
            })
        },
    
        submitShow(ctx, data) {
            let uri = process.env.VUE_APP_API_STEERING_SHOWS
            axios.post(uri, data.show, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(response => {
                ctx.commit('addShow', response.data)
                if (data && typeof (data.callback) === 'function') {
                    data.callback(response)
                }
            }).catch(error => {
                handleApiError(this, error, 'could not add new show')
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
            })
        },
    
        submitNote(ctx, data) {
    
            const NON_UPDATEABLE_PROPERTIES = ['thumbnails', 'width', 'height']
    
            let uri = process.env.VUE_APP_API_STEERING_SHOWS + data.id +
                '/schedules/' + data.scheduleID +
                '/timeslots/' + data.timeslotID +
                '/note/'
            if (data.update) {
                uri += data.note.id + '/'
            }
    
            let method = data.update ? 'put' : 'post'
    
            let formData = new FormData()
    
    
            // We serialize the data to a FormData object, so we can send the image
            // as binary blob to the Steering API.
            for (const [key, value] of Object.entries(data.note)) {
                // When we're updating we don't want to include some properties that cause errors.
                if (data.update && NON_UPDATEABLE_PROPERTIES.includes(key)) {
    
                    continue
    
                formData.append(key, value)
    
            }
    
            axios.request({
                url: uri,
                method: method,
                data: formData,
                responseType: 'json',  // we need this explicitly here, as it does not seem to work automagically as in GET and PUT requests
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(response => {
                if (data.update) {
                    ctx.commit('setNote', response.data)
                } else {
                    ctx.commit('addNote', response.data)
                }
                if (data && typeof (data.callback) === 'function') {
                    data.callback(response)
                }
            }).catch(error => {
                let msg = data.update ? 'could not update note' : 'could not add new note'
                handleApiError(this, error, msg)
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
            })
        },
    
        updateShow(ctx, data) {
            let uri = process.env.VUE_APP_API_STEERING_SHOWS + data.id + '/'
            axios.put(uri, data.show, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(response => {
                if (data && typeof (data.callback) === 'function') {
                    data.callback(response)
                }
            }).catch(error => {
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel(error.response)
                }
            })
        },
    
        updateProperty(ctx, data) {
            let show = cloneMinimalShowObject(ctx.getters.getShowByDataParam(data))
            show[data.property] = data.value
            ctx.dispatch('updateShow', {
                id: data.id,
                show: show,
                callback: () => {
                    ctx.commit('setProperty', {
                        id: data.id,
                        property: data.property,
                        value: data.value
                    })
    
                    if (typeof (data.callback) === 'function') {
                        data.callback()
                    }
                },
                callbackCancel: error => {
                    if (typeof (data.callbackCancel) === 'function') {
                        data.callbackCancel(error)
                    }
                }
            })
        },
    
        updateImage(ctx, data) {
            let show = ctx.getters.getShowByDataParam(data)
            let uri = process.env.VUE_APP_API_STEERING_SHOWS + data.id + '/'
            let formData = new FormData()
            // these propoerties have to be sent always (and they must not be null)
            formData.append('name', show.name)
            formData.append('slug', show.slug)
            formData.append('short_description', show.short_description)
            formData.append('type', show.type)
            formData.append('fundingcategory', show.fundingcategory)
            formData.append('is_active', show.is_active)
            // now we append the new logo/image file (signified by data.type)
            formData.append(data.type, data.file, data.file.name)
            axios.put(uri, formData, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(response => {
                ctx.commit('setProperty', {
                    id: data.id,
                    property: data.type,
                    // when updating images of a show the steering API does not return
                    // the full URI but only the path on the server
                    // TODO: create an issue in steering, to create consistency
                    value: process.env.VUE_APP_BASEURI_STEERING + response.data[data.type]
                })
                if (data && typeof (data.callback) === 'function') {
                    data.callback(response)
                }
            }).catch(error => {
                handleApiError(this, error, 'could not update show ' + data.type)
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
            })
        },
    
        updateTimeslot(ctx, data) {
            let uri = process.env.VUE_APP_API_STEERING + 'shows/' + data.show +
                '/schedules/' + data.schedule +
                '/timeslots/' + data.timeslot.id + '/'
            axios.put(uri, data.timeslot, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(() => {
                ctx.commit('setTimeslot', data.timeslot)
                if (data && typeof (data.callback) === 'function') {
                    data.callback()
                }
            }).catch(error => {
                handleApiError(this, error, 'could not update timeslot')
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
    
        },
    
        deleteSchedule(ctx, data) {
            let uri = process.env.VUE_APP_API_STEERING +
                'shows/' + data.show +
                '/schedules/' + data.schedule + '/'
            axios.delete(uri, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(() => {
                if (data && typeof (data.callback) === 'function') {
                    data.callback()
                }
            }).catch(error => {
                handleApiError(this, error, 'could not delete full schedule')
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
            })
        },
    
        deleteTimeslot(ctx, data) {
            let uri = process.env.VUE_APP_API_STEERING +
                'shows/' + data.show +
                '/schedules/' + data.schedule +
                '/timeslots/' + data.timeslot + '/'
            axios.delete(uri, {
                headers: {'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token}
            }).then(() => {
                if (data && typeof (data.callback) === 'function') {
                    data.callback()
                }
            }).catch(error => {
                handleApiError(this, error, 'could not delete single timeslot')
                if (data && typeof (data.callbackCancel) === 'function') {
                    data.callbackCancel()
                }
            })
        },
    
        namespaced: true,
        state,
        getters,
        actions,
        mutations,