Fix front settings fetching
This commit is contained in:
parent
9d7327a45f
commit
3dff9c74d9
|
@ -1,3 +1,55 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { BackendError, Album } from '~/types'
|
||||||
|
|
||||||
|
import { clone } from 'lodash-es'
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
import axios from 'axios'
|
||||||
|
import ChannelSerieCard from '~/components/audio/ChannelSerieCard.vue'
|
||||||
|
import AlbumCard from '~/components/audio/album/Card.vue'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
filters: object
|
||||||
|
isPodcast?: boolean
|
||||||
|
limit?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
isPodcast: true,
|
||||||
|
limit: 5
|
||||||
|
})
|
||||||
|
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const errors = ref([] as string[])
|
||||||
|
|
||||||
|
const albums = reactive([] as Album[])
|
||||||
|
const nextPage = ref()
|
||||||
|
const count = ref(0)
|
||||||
|
|
||||||
|
const fetchData = async (url = 'albums/') => {
|
||||||
|
isLoading.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
...clone(props.filters),
|
||||||
|
page_size: props.limit,
|
||||||
|
include_channels: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await axios.get(url, { params })
|
||||||
|
nextPage.value = response.data.next
|
||||||
|
count.value = response.data.count
|
||||||
|
albums.push(...response.data.results)
|
||||||
|
} catch (error) {
|
||||||
|
errors.value = (error as BackendError).backendErrors
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchData()
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<slot />
|
<slot />
|
||||||
|
@ -10,7 +62,7 @@
|
||||||
</div>
|
</div>
|
||||||
<template v-if="isPodcast">
|
<template v-if="isPodcast">
|
||||||
<channel-serie-card
|
<channel-serie-card
|
||||||
v-for="serie in objects"
|
v-for="serie in albums"
|
||||||
:key="serie.id"
|
:key="serie.id"
|
||||||
:serie="serie"
|
:serie="serie"
|
||||||
/>
|
/>
|
||||||
|
@ -20,7 +72,7 @@
|
||||||
class="ui app-cards cards"
|
class="ui app-cards cards"
|
||||||
>
|
>
|
||||||
<album-card
|
<album-card
|
||||||
v-for="album in objects"
|
v-for="album in albums"
|
||||||
:key="album.id"
|
:key="album.id"
|
||||||
:album="album"
|
:album="album"
|
||||||
/>
|
/>
|
||||||
|
@ -37,10 +89,10 @@
|
||||||
</translate>
|
</translate>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="!isLoading && objects.length === 0">
|
<template v-if="!isLoading && albums.length === 0">
|
||||||
<empty-state
|
<empty-state
|
||||||
:refresh="true"
|
:refresh="true"
|
||||||
@refresh="fetchData('albums/')"
|
@refresh="fetchData()"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
<translate translate-context="Content/Channels/*">
|
<translate translate-context="Content/Channels/*">
|
||||||
|
@ -51,55 +103,3 @@
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { clone } from 'lodash-es'
|
|
||||||
import axios from 'axios'
|
|
||||||
import ChannelSerieCard from '~/components/audio/ChannelSerieCard.vue'
|
|
||||||
import AlbumCard from '~/components/audio/album/Card.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
ChannelSerieCard,
|
|
||||||
AlbumCard
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
filters: { type: Object, required: true },
|
|
||||||
isPodcast: { type: Boolean, default: true },
|
|
||||||
limit: { type: Number, default: 5 }
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
objects: [],
|
|
||||||
count: 0,
|
|
||||||
isLoading: false,
|
|
||||||
errors: null,
|
|
||||||
nextPage: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
this.fetchData('albums/')
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
fetchData (url) {
|
|
||||||
if (!url) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.isLoading = true
|
|
||||||
const self = this
|
|
||||||
const params = clone(this.filters)
|
|
||||||
params.page_size = this.limit
|
|
||||||
params.include_channels = true
|
|
||||||
axios.get(url, { params }).then((response) => {
|
|
||||||
self.nextPage = response.data.next
|
|
||||||
self.isLoading = false
|
|
||||||
self.objects = self.objects.concat(response.data.results)
|
|
||||||
self.count = response.data.count
|
|
||||||
}, error => {
|
|
||||||
self.isLoading = false
|
|
||||||
self.errors = error.backendErrors
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
|
@ -1,3 +1,53 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { BackendError, Channel } from '~/types'
|
||||||
|
|
||||||
|
import { clone } from 'lodash-es'
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
import axios from 'axios'
|
||||||
|
import ChannelCard from '~/components/audio/ChannelCard.vue'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
filters: object
|
||||||
|
limit?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(['fetched'])
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
limit: 5
|
||||||
|
})
|
||||||
|
|
||||||
|
const channels = reactive([] as Channel[])
|
||||||
|
const errors = ref([] as string[])
|
||||||
|
const nextPage = ref()
|
||||||
|
const count = ref(0)
|
||||||
|
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const fetchData = async (url = 'channels/') => {
|
||||||
|
isLoading.value = true
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
...clone(props.filters),
|
||||||
|
page_size: props.limit,
|
||||||
|
include_channels: true
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.get(url, { params })
|
||||||
|
nextPage.value = response.data.next
|
||||||
|
count.value = response.data.count
|
||||||
|
channels.push(...response.data.results)
|
||||||
|
emit('fetched', response.data)
|
||||||
|
} catch (error) {
|
||||||
|
errors.value = (error as BackendError).backendErrors
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchData()
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<slot />
|
<slot />
|
||||||
|
@ -10,7 +60,7 @@
|
||||||
<div class="ui loader" />
|
<div class="ui loader" />
|
||||||
</div>
|
</div>
|
||||||
<channel-card
|
<channel-card
|
||||||
v-for="object in objects"
|
v-for="object in channels"
|
||||||
:key="object.uuid"
|
:key="object.uuid"
|
||||||
:object="object"
|
:object="object"
|
||||||
/>
|
/>
|
||||||
|
@ -27,7 +77,7 @@
|
||||||
</translate>
|
</translate>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="!isLoading && objects.length === 0">
|
<template v-if="!isLoading && channels.length === 0">
|
||||||
<empty-state
|
<empty-state
|
||||||
:refresh="true"
|
:refresh="true"
|
||||||
@refresh="fetchData('channels/')"
|
@refresh="fetchData('channels/')"
|
||||||
|
@ -35,53 +85,3 @@
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { clone } from 'lodash-es'
|
|
||||||
import axios from 'axios'
|
|
||||||
import ChannelCard from '~/components/audio/ChannelCard.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
ChannelCard
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
filters: { type: Object, required: true },
|
|
||||||
limit: { type: Number, default: 5 }
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
objects: [],
|
|
||||||
count: 0,
|
|
||||||
isLoading: false,
|
|
||||||
errors: null,
|
|
||||||
nextPage: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
this.fetchData('channels/')
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
fetchData (url) {
|
|
||||||
if (!url) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.isLoading = true
|
|
||||||
const self = this
|
|
||||||
const params = clone(this.filters)
|
|
||||||
params.page_size = this.limit
|
|
||||||
params.include_channels = true
|
|
||||||
axios.get(url, { params }).then((response) => {
|
|
||||||
self.nextPage = response.data.next
|
|
||||||
self.isLoading = false
|
|
||||||
self.objects = self.objects.concat(response.data.results)
|
|
||||||
self.count = response.data.count
|
|
||||||
self.$emit('fetched', response.data)
|
|
||||||
}, error => {
|
|
||||||
self.isLoading = false
|
|
||||||
self.errors = error.backendErrors
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
|
@ -1,3 +1,73 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Artist, Album } from '~/types'
|
||||||
|
|
||||||
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
import { ref, computed, reactive, watch, onMounted } from 'vue'
|
||||||
|
import { refDebounced } from '@vueuse/core'
|
||||||
|
|
||||||
|
import axios from 'axios'
|
||||||
|
import AlbumCard from '~/components/audio/album/Card.vue'
|
||||||
|
import ArtistCard from '~/components/audio/artist/Card.vue'
|
||||||
|
import useLogger from '~/composables/useLogger'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
autofocus?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
autofocus: false
|
||||||
|
})
|
||||||
|
|
||||||
|
const logger = useLogger()
|
||||||
|
const { $pgettext } = useGettext()
|
||||||
|
|
||||||
|
const query = ref('')
|
||||||
|
const queryDebounced = refDebounced(query, 500)
|
||||||
|
|
||||||
|
const results = reactive({
|
||||||
|
artists: [] as Artist[],
|
||||||
|
albums: [] as Album[]
|
||||||
|
})
|
||||||
|
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const search = async () => {
|
||||||
|
if (queryDebounced.value.length < 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading.value = true
|
||||||
|
logger.debug(`Searching track matching "${queryDebounced.value}"`)
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
query: queryDebounced.value
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.get('search/', { params })
|
||||||
|
results.artists = response.data.artists
|
||||||
|
results.albums = response.data.albums
|
||||||
|
} catch (error) {
|
||||||
|
// TODO (wvffle): Handle error
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(queryDebounced, search, { immediate: true })
|
||||||
|
|
||||||
|
const searchInput = ref()
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.autofocus) {
|
||||||
|
searchInput.value.focus()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const labels = computed(() => ({
|
||||||
|
searchPlaceholder: $pgettext('*/Search/Input.Placeholder', 'Artist, album, track…')
|
||||||
|
}))
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h2>
|
<h2>
|
||||||
|
@ -9,7 +79,7 @@
|
||||||
<div class="ui icon big input">
|
<div class="ui icon big input">
|
||||||
<i class="search icon" />
|
<i class="search icon" />
|
||||||
<input
|
<input
|
||||||
ref="search"
|
ref="searchInput"
|
||||||
v-model.trim="query"
|
v-model.trim="query"
|
||||||
class="prompt"
|
class="prompt"
|
||||||
:placeholder="labels.searchPlaceholder"
|
:placeholder="labels.searchPlaceholder"
|
||||||
|
@ -67,76 +137,3 @@
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { debounce } from 'lodash-es'
|
|
||||||
import axios from 'axios'
|
|
||||||
import AlbumCard from '~/components/audio/album/Card.vue'
|
|
||||||
import ArtistCard from '~/components/audio/artist/Card.vue'
|
|
||||||
import useLogger from '~/composables/useLogger'
|
|
||||||
|
|
||||||
const logger = useLogger()
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
AlbumCard,
|
|
||||||
ArtistCard
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
autofocus: { type: Boolean, default: false }
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
query: '',
|
|
||||||
results: {
|
|
||||||
albums: [],
|
|
||||||
artists: []
|
|
||||||
},
|
|
||||||
isLoading: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
labels () {
|
|
||||||
return {
|
|
||||||
searchPlaceholder: this.$pgettext('*/Search/Input.Placeholder', 'Artist, album, track…')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
query () {
|
|
||||||
this.search()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
if (this.autofocus) {
|
|
||||||
this.$refs.search.focus()
|
|
||||||
}
|
|
||||||
this.search()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
search: debounce(function () {
|
|
||||||
if (this.query.length < 1) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const self = this
|
|
||||||
self.isLoading = true
|
|
||||||
logger.debug('Searching track matching "' + this.query + '"')
|
|
||||||
const params = {
|
|
||||||
query: this.query
|
|
||||||
}
|
|
||||||
axios.get('search', {
|
|
||||||
params
|
|
||||||
}).then((response) => {
|
|
||||||
self.results = self.castResults(response.data)
|
|
||||||
self.isLoading = false
|
|
||||||
})
|
|
||||||
}, 500),
|
|
||||||
castResults (results) {
|
|
||||||
return {
|
|
||||||
albums: results.albums,
|
|
||||||
artists: results.artists
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
|
@ -183,7 +183,7 @@ const store: Module<State, RootState> = {
|
||||||
payload?.callback?.()
|
payload?.callback?.()
|
||||||
},
|
},
|
||||||
async fetchFrontSettings ({ state }) {
|
async fetchFrontSettings ({ state }) {
|
||||||
const response = await axios.get('/front/settings.json')
|
const response = await axios.get(`${import.meta.env.BASE_URL}settings.json`)
|
||||||
.catch(() => logger.error('Error when fetching front-end configuration (or no customization available)'))
|
.catch(() => logger.error('Error when fetching front-end configuration (or no customization available)'))
|
||||||
|
|
||||||
if (!response) return
|
if (!response) return
|
||||||
|
|
Loading…
Reference in New Issue