Newer
Older
import { StorageSerializers, useStorage } from '@vueuse/core'
APIListUnpaginated,
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 { steeringAuthInit, useAuthStore, useOnAuthBehaviour } from '@/stores/auth'
import { KeysFrom, Show } from '@/types'
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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),
selectedShowId,
selectedShow,