Skip to content
Snippets Groups Projects
shows.ts 5 KiB
Newer Older
  • Learn to ignore specific revisions
  • import { StorageSerializers, useStorage } from '@vueuse/core'
    
    import {
      APICreate,
      APIListPaginated,
    
      APIRemove,
      APIRetrieve,
      APIUpdate,
      createExtendableAPI,
    
    } from '@rokoli/bnb/drf'
    import { defineStore } from 'pinia'
    
    import { computed, Ref, watch } from 'vue'
    
    import { useStore } from 'vuex'
    import { useRoute, useRouter } from 'vue-router'
    
    
    import { createSteeringURL } from '@/api'
    
    import { components } from '@/steering-types'
    
    import { steeringAuthInit, useAuthStore, useOnAuthBehaviour } from '@/stores/auth'
    
    import { KeysFrom, Show } from '@/types'
    
    
    type ReadonlyAttrs = KeysFrom<Show, 'id' | 'createdAt' | 'createdBy' | 'updatedAt' | 'updatedBy'>
    type ShowCreateData = Omit<Show, ReadonlyAttrs>
    type ShowUpdateData = ShowCreateData
    type ShowPartialUpdateData = components['schemas']['PatchedShow']
    export type NewShow = ShowCreateData
    
    export function newShow(): NewShow {
      return {
        name: '',
        slug: '',
        description: '',
        shortDescription: '',
        email: '',
        internalNote: '',
        typeId: -1,
        fundingCategoryId: -1,
        isActive: true,
        isPublic: true,
        predecessorId: null,
        defaultPlaylistId: null,
        cbaSeriesId: null,
        imageId: null,
        logoId: null,
        links: [],
        topicIds: [],
        categoryIds: [],
        musicFocusIds: [],
        ownerIds: [],
        hostIds: [],
        languageIds: [],
      }
    }
    
    
    function useSelectedShowBehaviour(api: ExtendableAPI<Show>) {
      const authStore = useAuthStore()
      const { retrieve } = APIRetrieve(api)
    
      const selectedShowId = useStorage<number | null>('aura:selected-show', null, undefined, {
        serializer: StorageSerializers.number,
      })
    
      const selectedShow = computed(() =>
        selectedShowId.value !== null ? api.itemMap.value.get(selectedShowId.value) ?? null : null,
      )
    
      // Ensure that we always have the currently selected show in the store
      watch(
        [selectedShowId, () => authStore.currentUser],
        ([showId, user]) => {
          if (showId && user) void retrieve(showId, { useCached: true })
        },
        { immediate: true },
      )
    
      return { selectedShowId, selectedShow }
    }
    
    function useLegacyVuexStoreSyncBehaviour(
      shows: Ref<Show[]>,
      selectedShowId: Ref<Show['id'] | null>,
      selectedShow: Ref<Show | null>,
    ) {
      const authStore = useAuthStore()
    
      const store = useStore()
    
    
      watch(shows, (newShows) => {
        store.commit('shows/setShows', newShows)
      })
    
      // updated selected show in legacy vuex store when changed in pinia story
    
      watch(selectedShowId, (newShowId) => {
        store.commit('shows/switchShowById', newShowId)
      })
    
      // updated selected show in pinia store when changed in legacy vuex store
      watch(
        () => store.state.shows.selected.id,
        (newId) => {
          if (newId !== selectedShowId.value) {
            selectedShowId.value = newId
          }
        },
      )
      // fetch playlists when a show is selected
    
      watch(
        [() => selectedShow.value?.slug, () => authStore.currentUser],
        ([showSlug, user], [oldShowSlug]) => {
          if (showSlug && user && showSlug !== oldShowSlug) {
            void store.dispatch('playlists/fetch', { showSlug })
          }
        },
        { immediate: true },
      )
    }
    
    function useRouteSyncBehaviour(
      selectedShowId: Ref<Show['id'] | null>,
      selectedShow: Ref<Show | null>,
    ) {
      const route = useRoute()
      const router = useRouter()
    
      // watch changes to the selected show and apply them to the current route
      // so that fast context switches between multiple shows on show editor pages are possible
      watch(selectedShow, (show, oldShow) => {
        if (!oldShow) return
        const newShowId = show?.id ?? null
        const oldShowId = oldShow?.id ?? null
    
        if (newShowId === oldShowId) return
    
    
        if (show && route.name && route.params.showId) {
    
          void router.replace({ name: route.name, params: { ...route.params, showId: newShowId } })
    
        }
      })
    
      // Change the selected show if the user accessed a route for a particular show.
      // This is made so the show selector and the current route don’t have mismatching shows, which may cause confusion.
      watch(
        () => route.params.showId,
        (showId) => {
          if (showId) {
            selectedShowId.value = parseInt(showId as string)
          }
        },
        { immediate: true },
      )
    }
    
    
    export const useShowStore = defineStore('shows', () => {
      const endpoint = createSteeringURL.prefix('shows')
    
      const { api, base } = createExtendableAPI<Show>(endpoint, steeringAuthInit)
    
      const { selectedShow, selectedShowId } = useSelectedShowBehaviour(api)
      useRouteSyncBehaviour(selectedShowId, selectedShow)
      // TODO: remove once we get rid of the Vuex stores
      useLegacyVuexStoreSyncBehaviour(base.items, selectedShowId, selectedShow)
    
      // Make sure the store contains a list of all shows, which are
      // required on a number of pages and in the show selector.
      useOnAuthBehaviour(() => void APIListUnpaginated(api).list())
    
    
      return {
        ...base,
        ...APIListPaginated(api),
        ...APIRetrieve(api),
        ...APICreate<Show, ShowCreateData>(api),
        ...APIUpdate<Show, ShowUpdateData, ShowPartialUpdateData>(api),
        ...APIRemove(api),