Skip to content
Snippets Groups Projects
shows.js 16.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • import { APIError, callOrReturn, handleApiError } from '../api-helper'
    
    import { getISODateString, has } from '@/utilities'
    
    import { useAuthStore } from '@/stores/auth'
    
    import { createSteeringURL } from '@/api'
    
    const cloneMinimalShowObject = function (show) {
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
      /* returns a new minimal object from the current show object with all
    
        properties needed for a PUT request to the /show/ endpoint */
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
      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
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
      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
      },
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
      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.error('getShowByDataParam: ID not found in store!')
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          }
        } else if (data.index !== undefined) {
          show = state.shows[data.index]
        } else {
    
          console.error('getShowByDataParam: no ID or index was provided')
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        return show
      },
      getTimeslotById: (state) => (id) => {
        return state.timeslots.find((s) => s.id === id)
      },
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
      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) {
    
        const index = state.timeslots.findIndex((s) => s.id === slot.id)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        state.timeslots.splice(index, 1, slot)
      },
    
      setNotes(state, notes) {
        state.notes = notes
      },
      addNote(state, note) {
        state.notes.push(note)
      },
      setNote(state, note) {
    
        const index = state.notes.findIndex((n) => n.id === note.id)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        state.notes.splice(index, 1, note)
      },
    
      setName(state, data) {
    
        const index = state.shows.findIndex((s) => s.id === data.id)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        state.shows[index].name = data.text
      },
      setShortDescription(state, data) {
    
        const index = state.shows.findIndex((s) => s.id === data.id)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        state.shows[index].short_description = data.text
      },
      setDescription(state, data) {
    
        const index = state.shows.findIndex((s) => s.id === data.id)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        state.shows[index].description = data.text
      },
      setActive(state, data) {
    
        const index = state.shows.findIndex((s) => s.id === data.id)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        state.shows[index].is_active = data.active
      },
      setProperty(state, data) {
    
        const index = state.shows.findIndex((s) => s.id === data.id)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        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
        }
      },
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
      fetchShows(ctx, data) {
    
        const authStore = useAuthStore()
        const user = authStore.steeringUser
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        ctx.commit('loading', 'shows')
    
        let uri = createSteeringURL('shows')
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        // normal users should only see their own shows, only superusers see all shows
    
        if (!authStore.isSuperuser) {
          uri += '?owner=' + user.id
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .then((response) => {
            ctx.commit('setShows', response.data)
            ctx.commit('finishLoading', 'shows')
            if (data && typeof data.callback === 'function') {
              data.callback()
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          })
          .catch((error) => {
            handleApiError(this, error, 'could not load shows')
    
            console.error(error)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
            if (data && typeof data.callbackCancel === 'function') {
              data.callbackCancel()
            }
          })
      },
    
      fetchSchedule(ctx, data) {
        ctx.commit('loading', 'schedule')
    
        const uri = createSteeringURL('shows', data.show, 'schedules', data.schedule)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        axios
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .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')
    
        const uri = createSteeringURL('shows', data.show, 'schedules')
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        axios
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .then((response) => {
            ctx.commit('setSchedules', response.data)
            ctx.commit('finishLoading', 'schedule')
            if (data && typeof data.callback === 'function') {
              data.callback(response)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          })
          .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')
        } else {
          ctx.commit('loading', 'timeslots')
        }
    
        const query = new URLSearchParams()
        if (data.surrounding) {
          const date = data.surrounding instanceof Date ? data.surrounding : new Date()
          query.set('surrounding', getISODateString(date))
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        } else {
    
          if (has(data, 'start')) query.set('start', data.start)
          if (has(data, 'end')) query.set('end', data.end)
          if (has(data, 'limit')) query.set('limit', data.limit)
          if (has(data, 'offset')) query.set('offset', data.offset)
    
        const uri =
          data.id && data.schedule
            ? createSteeringURL('shows', data.id, 'schedules', data.schedule, 'timeslots', query)
            : data.id
            ? createSteeringURL('shows', data.id, 'timeslots', query)
            : createSteeringURL('timeslots', query)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        axios
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .then((response) => {
            if (data.schedule !== undefined) {
              ctx.commit('setScheduleTimeslots', response.data)
              ctx.commit('finishLoading', 'scheduleTimeslots')
    
            } else {
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
              if (data.limit) {
                ctx.commit('setTimeslots', response.data.results)
              } else {
                ctx.commit('setTimeslots', response.data)
              }
              ctx.commit('finishLoading', 'timeslots')
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
            if (data && typeof data.callback === 'function') {
              data.callback(response)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          })
          .catch((error) => {
            handleApiError(this, error, 'could not load timeslots')
            if (data && typeof data.callbackCancel === 'function') {
              data.callbackCancel()
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          })
      },
    
      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
        }
    
        const uri = createSteeringURL(
          'shows',
          data.id,
          'notes',
          new URLSearchParams({ ids: data.notes.join(',') }),
        )
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        this.$log.debug('fetchNotes: uri:', uri)
        axios
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .then((response) => {
            ctx.commit('setNotes', response.data)
            ctx.commit('finishLoading', 'notes')
            if (data && typeof data.callback === 'function') {
              data.callback(response)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          })
          .catch((error) => {
            handleApiError(this, error, 'could not load notes')
            if (data && typeof data.callbackCancel === 'function') {
              data.callbackCancel()
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          })
      },
    
      fetchMetaArray(ctx, data) {
        ctx.commit('loading', data.property)
    
        let uri = createSteeringURL(data.property)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        if (data.onlyActive === true) {
          uri += '?active=true'
        }
        axios
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .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()
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          })
      },
    
      submitSchedule(ctx, data) {
        ctx.commit('loading', 'schedules')
    
        const uri = createSteeringURL('shows', data.showId, 'schedules')
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        return axios
    
          .post(uri, data.schedule)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .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) {
    
        const uri = createSteeringURL('shows')
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        axios
    
          .post(uri, data.show)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .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 = createSteeringURL(
          'shows',
          data.id,
          'schedules',
          data.scheduleID,
          'timeslots',
          data.timeslotID,
          'note',
        )
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        if (data.update) {
          uri += data.note.id + '/'
        }
    
        const method = data.update ? 'put' : 'post'
        const formData = new FormData()
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        // 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
          }
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          formData.append(key, value)
        }
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        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
          })
          .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) => {
    
            const msg = data.update ? 'could not update note' : 'could not add new note'
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
            handleApiError(this, error, msg)
            if (data && typeof data.callbackCancel === 'function') {
              data.callbackCancel()
            }
          })
      },
    
      updateShow(ctx, data) {
    
        const uri = createSteeringURL('shows', data.id)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        axios
    
          .put(uri, data.show)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .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) {
    
        const show = cloneMinimalShowObject(ctx.getters.getShowByDataParam(data))
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        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,
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
            if (typeof data.callback === 'function') {
              data.callback()
            }
          },
          callbackCancel: (error) => {
            if (typeof data.callbackCancel === 'function') {
              data.callbackCancel(error)
            }
          },
        })
      },
    
      updateImage(ctx, data) {
    
        const show = ctx.getters.getShowByDataParam(data)
    
        const uri = createSteeringURL('shows', data.id)
    
        const formData = new FormData()
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        // 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)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .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: import.meta.env.VUE_APP_BASEURI_STEERING + response.data[data.type],
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
            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) {
    
        const uri = createSteeringURL(
          'shows',
          data.show,
          'schedules',
          data.schedule,
          'timeslots',
          data.timeslot.id,
        )
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        axios
    
          .put(uri, data.timeslot)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .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) {
    
        const uri = createSteeringURL('shows', data.show, 'schedules', data.schedule)
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        axios
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .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) {
    
        const uri = createSteeringURL(
          'shows',
          data.show,
          'schedules',
          data.schedule,
          'timeslots',
          data.timeslot,
        )
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
        axios
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
          .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()
            }
          })
      },
    
    Konrad Mohrfeldt's avatar
    Konrad Mohrfeldt committed
      namespaced: true,
      state,
      getters,
      actions,
      mutations,