Fix search and dynamic ordering (#1567)

environments/review-front-deve-otr6gc/deployments/13419
wvffle 2022-09-03 14:51:20 +00:00 zatwierdzone przez Georg Krause
rodzic fb27bccaa3
commit fb4f94fb73
49 zmienionych plików z 685 dodań i 813 usunięć

Wyświetl plik

@ -24,6 +24,7 @@
"@vue/runtime-core": "3.2.38",
"@vueuse/core": "9.1.1",
"@vueuse/integrations": "9.1.1",
"@vueuse/router": "9.1.1",
"axios": "0.27.2",
"axios-auth-refresh": "3.3.3",
"diff": "5.1.0",

Wyświetl plik

@ -1,5 +1,5 @@
<script setup lang="ts">
import type { ContentCategory, Channel, BackendError, Tag } from '~/types'
import type { ContentCategory, Channel, BackendError } from '~/types'
import { slugify } from 'transliteration'
import { reactive, computed, ref, watchEffect, watch } from 'vue'
@ -34,7 +34,7 @@ const { $pgettext } = useGettext()
const newValues = reactive({
name: props.object?.artist?.name ?? '',
username: props.object?.actor.preferred_username ?? '',
tags: props.object?.artist?.tags?.map(name => ({ name } as Tag)) ?? [] as Tag[],
tags: props.object?.artist?.tags ?? [] as string[],
description: props.object?.artist?.description?.text ?? '',
cover: props.object?.artist?.cover?.uuid ?? null,
content_category: props.object?.artist?.content_category ?? 'podcast',

Wyświetl plik

@ -13,7 +13,7 @@ import useFormData from '~/composables/useFormData'
interface Props {
clientId: string
redirectUri: string
scope: string
scope: 'me' | 'all'
responseType: string
nonce: string
state: string

Wyświetl plik

@ -1,5 +1,5 @@
<script setup lang="ts">
import type { Upload, Tag, Track } from '~/types'
import type { Upload, Track } from '~/types'
import { reactive, computed, watch } from 'vue'
@ -21,16 +21,12 @@ const props = withDefaults(defineProps<Props>(), {
values: null
})
const newValues = reactive<Omit<Values, 'tags'> & { tags: Tag[] }>({
...(props.values ?? props.upload.import_metadata ?? {}) as Values,
tags: ((props.values ?? props.upload.import_metadata)?.tags?.map(name => ({ name })) ?? []) as Tag[]
const newValues = reactive<Values>({
...(props.values ?? props.upload.import_metadata ?? {}) as Values
})
const isLoading = computed(() => !props.upload)
watch(newValues, (values) => emit('update:values', {
...values,
tags: values.tags?.map(({ name }) => name)
}), { immediate: true })
watch(newValues, (values) => emit('update:values', values), { immediate: true })
</script>
<template>

Wyświetl plik

@ -1,11 +1,12 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import type { Track } from '~/types'
import type { OrderingProps } from '~/composables/useOrdering'
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { onBeforeRouteUpdate, useRouter } from 'vue-router'
import { useGettext } from 'vue3-gettext'
import { sortedUniq } from 'lodash-es'
import { useStore } from '~/store'
import axios from 'axios'
@ -16,24 +17,24 @@ import RadioButton from '~/components/radios/Button.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
import useLogger from '~/composables/useLogger'
interface Props extends OrderingProps {
defaultPage?: number
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
}
const props = withDefaults(defineProps<Props>(), {
defaultPage: 1
defaultPage: 1,
orderingConfigName: undefined
})
const store = useStore()
const page = ref(+props.defaultPage)
const page = usePage()
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],
@ -45,19 +46,7 @@ const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
const logger = useLogger()
const sharedLabels = useSharedLabels()
const router = useRouter()
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const updateQueryString = () => router.replace({
query: {
page: page.value,
paginateBy: paginateBy.value,
ordering: orderingString.value
}
})
watch(page, updateQueryString)
onOrderingUpdate(updateQueryString)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const results = reactive<Track[]>([])
const nextLink = ref()
@ -97,15 +86,22 @@ const fetchFavorites = async () => {
}
}
onBeforeRouteUpdate(fetchFavorites)
watch(page, fetchFavorites)
fetchFavorites()
onOrderingUpdate(() => {
page.value = 1
fetchFavorites()
})
onMounted(() => $('.ui.dropdown').dropdown())
const { $pgettext } = useGettext()
const labels = computed(() => ({
title: $pgettext('Head/Favorites/Title', 'Your Favorites')
}))
const paginateOptions = computed(() => sortedUniq([12, 25, 50, paginateBy.value].sort((a, b) => a - b)))
</script>
<template>
@ -194,14 +190,12 @@ const labels = computed(() => ({
v-model="paginateBy"
class="ui dropdown"
>
<option :value="12">
12
</option>
<option :value="25">
25
</option>
<option :value="50">
50
<option
v-for="opt in paginateOptions"
:key="opt"
:value="opt"
>
{{ opt }}
</option>
</select>
</div>

Wyświetl plik

@ -1,10 +1,14 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/useOrdering'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { Album, BackendResponse } from '~/types'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { onBeforeRouteUpdate, useRouter } from 'vue-router'
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { computed, onMounted, ref, watch } from 'vue'
import { useRouteQuery } from '@vueuse/router'
import { useGettext } from 'vue3-gettext'
import { syncRef } from '@vueuse/core'
import { sortedUniq } from 'lodash-es'
import { useStore } from '~/store'
import axios from 'axios'
@ -16,32 +20,32 @@ import AlbumCard from '~/components/audio/album/Card.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
import useLogger from '~/composables/useLogger'
interface Props extends OrderingProps {
defaultPage?: number
defaultQuery?: string
defaultTags?: string[]
scope?: string
scope?: 'me' | 'all'
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
}
const props = withDefaults(defineProps<Props>(), {
defaultPage: 1,
defaultQuery: '',
defaultTags: () => [],
scope: 'all'
scope: 'all',
orderingConfigName: undefined
})
const page = ref(+props.defaultPage)
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const query = ref(props.defaultQuery)
const tags = reactive(props.defaultTags.map(name => ({ name })))
const page = usePage()
const tags = useRouteQuery<string[]>('tag', [])
const q = useRouteQuery('query', '')
const query = ref(q.value)
syncRef(q, query, { direction: 'ltr' })
const result = ref<BackendResponse<Album>>()
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],
@ -52,21 +56,7 @@ const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
const logger = useLogger()
const sharedLabels = useSharedLabels()
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const router = useRouter()
const updateQueryString = () => router.replace({
query: {
query: query.value,
page: page.value,
tag: tags.map(({ name }) => name),
paginateBy: paginateBy.value,
ordering: orderingString.value
}
})
watch(page, updateQueryString)
onOrderingUpdate(updateQueryString)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const isLoading = ref(false)
const fetchData = async () => {
@ -78,7 +68,7 @@ const fetchData = async () => {
q: query.value,
ordering: orderingString.value,
playable: 'true',
tag: tags,
tag: tags.value,
include_channels: 'true',
content_category: 'music'
}
@ -95,7 +85,7 @@ const fetchData = async () => {
result.value = response.data
} catch (error) {
useErrorHandler(error as Error)
result.value = null
result.value = undefined
} finally {
logger.timeEnd('Fetching albums')
isLoading.value = false
@ -104,9 +94,19 @@ const fetchData = async () => {
const store = useStore()
watch(() => store.state.moderation.lastUpdate, fetchData)
onBeforeRouteUpdate(fetchData)
watch(page, fetchData)
fetchData()
const search = () => {
page.value = 1
q.value = query.value
}
onOrderingUpdate(() => {
page.value = 1
fetchData()
})
onMounted(() => $('.ui.dropdown').dropdown())
const { $pgettext } = useGettext()
@ -114,6 +114,8 @@ const labels = computed(() => ({
searchPlaceholder: $pgettext('Content/Search/Input.Placeholder', 'Enter album title…'),
title: $pgettext('*/*/*', 'Albums')
}))
const paginateOptions = computed(() => sortedUniq([12, 25, 50, paginateBy.value].sort((a, b) => a - b)))
</script>
<template>
@ -126,7 +128,7 @@ const labels = computed(() => ({
</h2>
<form
:class="['ui', {'loading': isLoading}, 'form']"
@submit.prevent="page = props.defaultPage"
@submit.prevent="search"
>
<div class="fields">
<div class="field">
@ -196,14 +198,12 @@ const labels = computed(() => ({
v-model="paginateBy"
class="ui dropdown"
>
<option :value="12">
12
</option>
<option :value="25">
25
</option>
<option :value="50">
50
<option
v-for="opt in paginateOptions"
:key="opt"
:value="opt"
>
{{ opt }}
</option>
</select>
</div>

Wyświetl plik

@ -1,10 +1,14 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/useOrdering'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { Artist, BackendResponse } from '~/types'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { computed, reactive, ref, watch, onMounted } from 'vue'
import { onBeforeRouteUpdate, useRouter } from 'vue-router'
import { computed, ref, watch, onMounted } from 'vue'
import { useRouteQuery } from '@vueuse/router'
import { useGettext } from 'vue3-gettext'
import { syncRef } from '@vueuse/core'
import { sortedUniq } from 'lodash-es'
import { useStore } from '~/store'
import axios from 'axios'
@ -16,32 +20,32 @@ import ArtistCard from '~/components/audio/artist/Card.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
import useLogger from '~/composables/useLogger'
interface Props extends OrderingProps {
defaultPage?: number
defaultQuery?: string
defaultTags?: string[]
scope?: string
scope?: 'me' | 'all'
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
}
const props = withDefaults(defineProps<Props>(), {
defaultPage: 1,
defaultQuery: '',
defaultTags: () => [],
scope: 'all'
scope: 'all',
orderingConfigName: undefined
})
const page = ref(+props.defaultPage)
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const query = ref(props.defaultQuery)
const tags = reactive(props.defaultTags.map(name => ({ name })))
const page = usePage()
const tags = useRouteQuery<string[]>('tag', [])
const q = useRouteQuery('query', '')
const query = ref(q.value)
syncRef(q, query, { direction: 'ltr' })
const result = ref<BackendResponse<Artist>>()
const excludeCompilation = ref(true)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
@ -52,23 +56,7 @@ const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
const logger = useLogger()
const sharedLabels = useSharedLabels()
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const router = useRouter()
const updateQueryString = () => router.replace({
query: {
query: query.value,
page: page.value,
tag: tags.map(({ name }) => name),
paginateBy: paginateBy.value,
ordering: orderingString.value,
content_category: 'music',
include_channels: 'true'
}
})
watch(page, updateQueryString)
onOrderingUpdate(updateQueryString)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const isLoading = ref(false)
const fetchData = async () => {
@ -80,7 +68,7 @@ const fetchData = async () => {
q: query.value,
ordering: orderingString.value,
playable: 'true',
tag: tags,
tag: tags.value,
include_channels: 'true',
content_category: 'music',
has_albums: excludeCompilation.value
@ -98,7 +86,7 @@ const fetchData = async () => {
result.value = response.data
} catch (error) {
useErrorHandler(error as Error)
result.value = null
result.value = undefined
} finally {
logger.timeEnd('Fetching artists')
isLoading.value = false
@ -107,9 +95,19 @@ const fetchData = async () => {
const store = useStore()
watch([() => store.state.moderation.lastUpdate, excludeCompilation], fetchData)
onBeforeRouteUpdate(fetchData)
watch(page, fetchData)
fetchData()
const search = () => {
page.value = 1
q.value = query.value
}
onOrderingUpdate(() => {
page.value = 1
fetchData()
})
onMounted(() => $('.ui.dropdown').dropdown())
const { $pgettext } = useGettext()
@ -117,6 +115,8 @@ const labels = computed(() => ({
searchPlaceholder: $pgettext('Content/Search/Input.Placeholder', 'Search…'),
title: $pgettext('*/*/*/Noun', 'Artists')
}))
const paginateOptions = computed(() => sortedUniq([12, 30, 50, paginateBy.value].sort((a, b) => a - b)))
</script>
<template>
@ -129,7 +129,7 @@ const labels = computed(() => ({
</h2>
<form
:class="['ui', {'loading': isLoading}, 'form']"
@submit.prevent="page = props.defaultPage"
@submit.prevent="search"
>
<div class="fields">
<div class="field">
@ -199,14 +199,12 @@ const labels = computed(() => ({
v-model="paginateBy"
class="ui dropdown"
>
<option :value="12">
12
</option>
<option :value="30">
30
</option>
<option :value="50">
50
<option
v-for="opt in paginateOptions"
:key="opt"
:value="opt"
>
{{ opt }}
</option>
</select>
</div>

Wyświetl plik

@ -1,6 +1,6 @@
<script setup lang="ts">
import type { VueUploadItem } from 'vue-upload-component'
import type { BackendError, Library, FileSystem } from '~/types'
import type { VueUploadItem } from 'vue-upload-component'
import { computed, ref, reactive, watch, nextTick } from 'vue'
import { useEventListener, useIntervalFn } from '@vueuse/core'
@ -268,7 +268,8 @@ const inputFile = (newFile: VueUploadItem) => {
}
}
const retry = (files: VueUploadItem[]) => {
// NOTE: For some weird reason typescript thinks that xhr field is not compatible with the same type
const retry = (files: Omit<VueUploadItem, 'xhr'>[]) => {
for (const file of files) {
upload.value.update(file, { error: '', progress: '0.00' })
}

Wyświetl plik

@ -1,5 +1,5 @@
<template>
<div class="main pusher page-library">
<router-view :key="$route.fullPath" />
<router-view />
</div>
</template>

Wyświetl plik

@ -1,10 +1,14 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/useOrdering'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { Artist, BackendResponse } from '~/types'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { computed, reactive, ref, watch, onMounted } from 'vue'
import { onBeforeRouteUpdate, useRouter } from 'vue-router'
import { computed, ref, watch, onMounted } from 'vue'
import { useRouteQuery } from '@vueuse/router'
import { useGettext } from 'vue3-gettext'
import { syncRef } from '@vueuse/core'
import { sortedUniq } from 'lodash-es'
import { useStore } from '~/store'
import axios from 'axios'
@ -18,33 +22,32 @@ import ArtistCard from '~/components/audio/artist/Card.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
import useLogger from '~/composables/useLogger'
interface Props extends OrderingProps {
defaultPage?: number
defaultQuery?: string
defaultTags?: string[]
scope?: string
scope?: 'me' | 'all'
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
}
const props = withDefaults(defineProps<Props>(), {
defaultPage: 1,
defaultQuery: '',
defaultTags: () => [],
scope: 'all'
scope: 'all',
orderingConfigName: undefined
})
const page = ref(+props.defaultPage)
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const query = ref(props.defaultQuery)
const tags = reactive(props.defaultTags.map(name => ({ name })))
const page = usePage()
const tags = useRouteQuery<string[]>('tag', [])
const q = useRouteQuery('query', '')
const query = ref(q.value)
syncRef(q, query, { direction: 'ltr' })
const result = ref<BackendResponse<Artist>>()
const showSubscribeModal = ref(false)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
@ -55,23 +58,7 @@ const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
const logger = useLogger()
const sharedLabels = useSharedLabels()
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const router = useRouter()
const updateQueryString = () => router.replace({
query: {
query: query.value,
page: page.value,
tag: tags.map(({ name }) => name),
paginateBy: paginateBy.value,
ordering: orderingString.value,
content_category: 'podcast',
include_channels: 'true'
}
})
watch(page, updateQueryString)
onOrderingUpdate(updateQueryString)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const isLoading = ref(false)
const fetchData = async () => {
@ -83,7 +70,7 @@ const fetchData = async () => {
q: query.value,
ordering: orderingString.value,
playable: 'true',
tag: tags,
tag: tags.value,
include_channels: 'true',
content_category: 'podcast'
}
@ -100,7 +87,7 @@ const fetchData = async () => {
result.value = response.data
} catch (error) {
useErrorHandler(error as Error)
result.value = null
result.value = undefined
} finally {
logger.timeEnd('Fetching podcasts')
isLoading.value = false
@ -109,9 +96,19 @@ const fetchData = async () => {
const store = useStore()
watch(() => store.state.moderation.lastUpdate, fetchData)
onBeforeRouteUpdate(fetchData)
watch(page, fetchData)
fetchData()
const search = () => {
page.value = 1
q.value = query.value
}
onOrderingUpdate(() => {
page.value = 1
fetchData()
})
onMounted(() => $('.ui.dropdown').dropdown())
const { $pgettext } = useGettext()
@ -119,6 +116,8 @@ const labels = computed(() => ({
searchPlaceholder: $pgettext('Content/Search/Input.Placeholder', 'Search…'),
title: $pgettext('*/*/*/Noun', 'Podcasts')
}))
const paginateOptions = computed(() => sortedUniq([12, 30, 50, paginateBy.value].sort((a, b) => a - b)))
</script>
<template>
@ -131,7 +130,7 @@ const labels = computed(() => ({
</h2>
<form
:class="['ui', {'loading': isLoading}, 'form']"
@submit.prevent="page = props.defaultPage"
@submit.prevent="search"
>
<div class="fields">
<div class="field">
@ -201,14 +200,12 @@ const labels = computed(() => ({
v-model="paginateBy"
class="ui dropdown"
>
<option :value="12">
12
</option>
<option :value="30">
30
</option>
<option :value="50">
50
<option
v-for="opt in paginateOptions"
:key="opt"
:value="opt"
>
{{ opt }}
</option>
</select>
</div>

Wyświetl plik

@ -1,10 +1,14 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/useOrdering'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { Radio, BackendResponse } from '~/types'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { onBeforeRouteUpdate, useRouter } from 'vue-router'
import { computed, ref, watch, onMounted } from 'vue'
import { computed, onMounted, ref, watch } from 'vue'
import { useRouteQuery } from '@vueuse/router'
import { useGettext } from 'vue3-gettext'
import { syncRef } from '@vueuse/core'
import { sortedUniq } from 'lodash-es'
import { useStore } from '~/store'
import axios from 'axios'
@ -14,30 +18,30 @@ import Pagination from '~/components/vui/Pagination.vue'
import RadioCard from '~/components/radios/Card.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
import useLogger from '~/composables/useLogger'
interface Props extends OrderingProps {
defaultPage?: number
defaultQuery?: string
scope?: string
scope?: 'me' | 'all'
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
}
const props = withDefaults(defineProps<Props>(), {
defaultPage: 1,
defaultQuery: '',
scope: 'all'
scope: 'all',
orderingConfigName: undefined
})
const page = ref(+props.defaultPage)
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const query = ref(props.defaultQuery)
const page = usePage()
const q = useRouteQuery('query', '')
const query = ref(q.value)
syncRef(q, query, { direction: 'ltr' })
const result = ref<BackendResponse<Radio>>()
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],
@ -47,20 +51,7 @@ const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
const logger = useLogger()
const sharedLabels = useSharedLabels()
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const router = useRouter()
const updateQueryString = () => router.replace({
query: {
query: query.value,
page: page.value,
paginateBy: paginateBy.value,
ordering: orderingString.value
}
})
watch(page, updateQueryString)
onOrderingUpdate(updateQueryString)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const isLoading = ref(false)
const fetchData = async () => {
@ -82,7 +73,7 @@ const fetchData = async () => {
result.value = response.data
} catch (error) {
useErrorHandler(error as Error)
result.value = null
result.value = undefined
} finally {
logger.timeEnd('Fetching radios')
isLoading.value = false
@ -93,9 +84,19 @@ const store = useStore()
const isAuthenticated = computed(() => store.state.auth.authenticated)
const hasFavorites = computed(() => store.state.favorites.count > 0)
onBeforeRouteUpdate(fetchData)
watch(page, fetchData)
fetchData()
const search = () => {
page.value = 1
q.value = query.value
}
onOrderingUpdate(() => {
page.value = 1
fetchData()
})
onMounted(() => $('.ui.dropdown').dropdown())
const { $pgettext } = useGettext()
@ -103,6 +104,8 @@ const labels = computed(() => ({
searchPlaceholder: $pgettext('Content/Search/Input.Placeholder', 'Enter a radio name…'),
title: $pgettext('*/*/*', 'Radios')
}))
const paginateOptions = computed(() => sortedUniq([12, 25, 50, paginateBy.value].sort((a, b) => a - b)))
</script>
<template>
@ -157,7 +160,7 @@ const labels = computed(() => ({
<div class="ui hidden divider" />
<form
:class="['ui', {'loading': isLoading}, 'form']"
@submit.prevent="page = props.defaultPage"
@submit.prevent="search"
>
<div class="fields">
<div class="field">
@ -221,14 +224,12 @@ const labels = computed(() => ({
v-model="paginateBy"
class="ui dropdown"
>
<option :value="12">
12
</option>
<option :value="25">
25
</option>
<option :value="50">
50
<option
v-for="opt in paginateOptions"
:key="opt"
:value="opt"
>
{{ opt }}
</option>
</select>
</div>

Wyświetl plik

@ -8,11 +8,11 @@ import { useStore } from '~/store'
import $ from 'jquery'
interface Events {
(e: 'update:modelValue', tags: Tag[]): void
(e: 'update:modelValue', tags: string[]): void
}
interface Props {
modelValue: Tag[]
modelValue: string[]
}
const emit = defineEmits<Events>()

Wyświetl plik

@ -1,7 +1,8 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { OrderingProps } from '~/composables/useOrdering'
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { computed, ref, watch } from 'vue'
import { useGettext } from 'vue3-gettext'
@ -11,16 +12,17 @@ import axios from 'axios'
import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends SmartSearchProps, OrderingProps {
filters?: object
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
defaultQuery?: string
updateUrl?: boolean
}
@ -28,16 +30,17 @@ interface Props extends SmartSearchProps, OrderingProps {
const props = withDefaults(defineProps<Props>(), {
defaultQuery: '',
updateUrl: false,
filters: () => ({})
filters: () => ({}),
orderingConfigName: undefined
})
const page = ref(1)
const page = usePage()
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const search = ref()
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],

Wyświetl plik

@ -1,7 +1,8 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { OrderingProps } from '~/composables/useOrdering'
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { computed, ref, watch } from 'vue'
import { useGettext } from 'vue3-gettext'
@ -11,16 +12,17 @@ import axios from 'axios'
import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends SmartSearchProps, OrderingProps {
filters?: object
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
defaultQuery?: string
updateUrl?: boolean
}
@ -28,17 +30,18 @@ interface Props extends SmartSearchProps, OrderingProps {
const props = withDefaults(defineProps<Props>(), {
defaultQuery: '',
updateUrl: false,
filters: () => ({})
filters: () => ({}),
orderingConfigName: undefined
})
const search = ref()
const page = ref(1)
const page = usePage()
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const { onSearch, query, addSearchToken } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onSearch, query, addSearchToken } = useSmartSearch(props)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],

Wyświetl plik

@ -1,7 +1,8 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/useOrdering'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { ref, computed, watch } from 'vue'
import { useGettext } from 'vue3-gettext'
@ -11,16 +12,17 @@ import axios from 'axios'
import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends SmartSearchProps, OrderingProps {
filters?: object
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
defaultQuery?: string
updateUrl?: boolean
}
@ -28,17 +30,18 @@ interface Props extends SmartSearchProps, OrderingProps {
const props = withDefaults(defineProps<Props>(), {
defaultQuery: '',
updateUrl: false,
filters: () => ({})
filters: () => ({}),
orderingConfigName: undefined
})
const search = ref()
const page = ref(1)
const page = usePage()
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],

Wyświetl plik

@ -1,9 +1,10 @@
<script setup lang="ts">
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { EditObjectType } from '~/composables/moderation/useEditConfigs'
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { OrderingProps } from '~/composables/useOrdering'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { ReviewState, Review } from '~/types'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { ref, reactive, watch, computed } from 'vue'
import { useGettext } from 'vue3-gettext'
@ -15,16 +16,17 @@ import Pagination from '~/components/vui/Pagination.vue'
import EditCard from '~/components/library/EditCard.vue'
import useEditConfigs from '~/composables/moderation/useEditConfigs'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends SmartSearchProps, OrderingProps {
filters?: object
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
defaultQuery?: string
updateUrl?: boolean
}
@ -32,20 +34,21 @@ interface Props extends SmartSearchProps, OrderingProps {
const props = withDefaults(defineProps<Props>(), {
defaultQuery: '',
updateUrl: false,
filters: () => ({})
filters: () => ({}),
orderingConfigName: undefined
})
const configs = useEditConfigs()
const search = ref()
const page = ref(1)
const page = usePage()
type StateTarget = Review['target']
type ResponseType = { count: number, results: Review[] }
const result = ref<null | ResponseType>(null)
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],

Wyświetl plik

@ -1,7 +1,8 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { OrderingProps } from '~/composables/useOrdering'
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import type { PrivacyLevel } from '~/types'
import { computed, ref, watch } from 'vue'
@ -12,15 +13,16 @@ import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends SmartSearchProps, OrderingProps {
filters?: object
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
defaultQuery?: string
updateUrl?: boolean
}
@ -28,17 +30,18 @@ interface Props extends SmartSearchProps, OrderingProps {
const props = withDefaults(defineProps<Props>(), {
defaultQuery: '',
updateUrl: false,
filters: () => ({})
filters: () => ({}),
orderingConfigName: undefined
})
const search = ref()
const page = ref(1)
const page = usePage()
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],

Wyświetl plik

@ -1,7 +1,8 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { OrderingProps } from '~/composables/useOrdering'
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { computed, ref, watch } from 'vue'
import { truncate } from '~/utils/filters'
@ -14,15 +15,16 @@ import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends SmartSearchProps, OrderingProps {
filters?: object
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
defaultQuery?: string
updateUrl?: boolean
}
@ -30,17 +32,18 @@ interface Props extends SmartSearchProps, OrderingProps {
const props = withDefaults(defineProps<Props>(), {
defaultQuery: '',
updateUrl: false,
filters: () => ({})
filters: () => ({}),
orderingConfigName: undefined
})
const search = ref()
const page = ref(1)
const page = usePage()
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const { onSearch, query } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onSearch, query } = useSmartSearch(props)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],

Wyświetl plik

@ -1,7 +1,8 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { OrderingProps } from '~/composables/useOrdering'
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { ref, computed, watch } from 'vue'
import { useGettext } from 'vue3-gettext'
@ -12,15 +13,16 @@ import useSharedLabels from '~/composables/locale/useSharedLabels'
import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends SmartSearchProps, OrderingProps {
filters?: object
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
defaultQuery?: string
updateUrl?: boolean
}
@ -28,17 +30,18 @@ interface Props extends SmartSearchProps, OrderingProps {
const props = withDefaults(defineProps<Props>(), {
defaultQuery: '',
updateUrl: false,
filters: () => ({})
filters: () => ({}),
orderingConfigName: undefined
})
const search = ref()
const page = ref(1)
const page = usePage()
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const { onSearch, query, addSearchToken } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onSearch, query, addSearchToken } = useSmartSearch(props)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date']

Wyświetl plik

@ -1,8 +1,9 @@
<script setup lang="ts">
import type { ImportStatus, PrivacyLevel, Upload, BackendResponse } from '~/types'
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { OrderingProps } from '~/composables/useOrdering'
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { humanSize, truncate } from '~/utils/filters'
import { ref, computed, watch } from 'vue'
@ -14,16 +15,17 @@ import ImportStatusModal from '~/components/library/ImportStatusModal.vue'
import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends SmartSearchProps, OrderingProps {
filters?: object
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
defaultQuery?: string
updateUrl?: boolean
}
@ -31,16 +33,17 @@ interface Props extends SmartSearchProps, OrderingProps {
const props = withDefaults(defineProps<Props>(), {
defaultQuery: '',
updateUrl: false,
filters: () => ({})
filters: () => ({}),
orderingConfigName: undefined
})
const search = ref()
const page = ref(1)
const page = usePage()
const result = ref<BackendResponse<Upload>>()
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],

Wyświetl plik

@ -1,7 +1,8 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/useOrdering'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { ref, computed, watch } from 'vue'
import { useGettext } from 'vue3-gettext'
@ -12,15 +13,16 @@ import useSharedLabels from '~/composables/locale/useSharedLabels'
import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends SmartSearchProps, OrderingProps {
filters?: object
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
defaultQuery?: string
updateUrl?: boolean
}
@ -28,17 +30,18 @@ interface Props extends SmartSearchProps, OrderingProps {
const props = withDefaults(defineProps<Props>(), {
defaultQuery: '',
updateUrl: false,
filters: () => ({})
filters: () => ({}),
orderingConfigName: undefined
})
const search = ref()
const page = ref(1)
const page = usePage()
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const { onSearch, query, addSearchToken } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onSearch, query, addSearchToken } = useSmartSearch(props)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'first_seen'],

Wyświetl plik

@ -1,6 +1,7 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/useOrdering'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { watchDebounced } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
@ -12,27 +13,29 @@ import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends OrderingProps {
filters?: object
allowListEnabled?: boolean
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
}
const props = withDefaults(defineProps<Props>(), {
filters: () => ({}),
allowListEnabled: false
allowListEnabled: false,
orderingConfigName: undefined
})
const page = ref(1)
const page = usePage()
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['name', 'name'],

Wyświetl plik

@ -1,6 +1,7 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/useOrdering'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { watchDebounced } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
@ -13,25 +14,27 @@ import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends OrderingProps {
filters?: object
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
}
const props = withDefaults(defineProps<Props>(), {
filters: () => ({})
filters: () => ({}),
orderingConfigName: undefined
})
const page = ref(1)
const page = usePage()
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const { onOrderingUpdate, orderingString, paginateBy, ordering } = useOrdering(props.orderingConfigName)
const { onOrderingUpdate, orderingString, paginateBy, ordering } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['expiration_date', 'expiration_date'],

Wyświetl plik

@ -1,6 +1,7 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/useOrdering'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { watchDebounced } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
@ -13,17 +14,18 @@ import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useErrorHandler from '~/composables/useErrorHandler'
import useOrdering from '~/composables/useOrdering'
import useOrdering from '~/composables/navigation/useOrdering'
interface Props extends OrderingProps {
filters?: object
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
}
const props = withDefaults(defineProps<Props>(), {
filters: () => ({})
filters: () => ({}),
orderingConfigName: undefined
})
const page = ref(1)
@ -31,7 +33,7 @@ const query = ref('')
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['date_joined', 'date_joined'],

Wyświetl plik

@ -4,6 +4,8 @@ import { range, clamp } from 'lodash-es'
import { computed } from 'vue'
import { useGettext } from 'vue3-gettext'
const RANGE = 2
interface Events {
(e: 'update:current', page: number): void
}
@ -24,7 +26,6 @@ const props = withDefaults(defineProps<Props>(), {
const current = useVModel(props, 'current', emit)
const RANGE = 2
const pages = computed(() => {
const start = range(1, 1 + RANGE)
const end = range(maxPage.value - RANGE + 1, maxPage.value + 1)
@ -33,6 +34,13 @@ const pages = computed(() => {
clamp(props.current + RANGE, 1, maxPage.value)
).filter(i => !start.includes(i) && !end.includes(i))
if (end[0] - 1 <= start[RANGE - 1]) {
return [
...start,
...end.filter(i => i > start[RANGE - 1])
]
}
return [
...start,
middle.length === 0 && 'skip',

Wyświetl plik

@ -0,0 +1,73 @@
import type { RouteRecordName } from 'vue-router'
import { toRefs, useStorage, syncRef } from '@vueuse/core'
import { useRouteQuery } from '@vueuse/router'
import { useRoute } from 'vue-router'
import { ref, watch } from 'vue'
export interface OrderingProps {
orderingConfigName?: RouteRecordName
}
export default (props: OrderingProps) => {
const route = useRoute()
const preferences = useStorage(`route-preferences:${props.orderingConfigName?.toString() ?? route.name?.toString() ?? '*'}`, {
orderingDirection: route.meta.orderingDirection ?? '-',
ordering: route.meta.ordering ?? 'creation_date',
paginateBy: route.meta.paginateBy ?? 50
})
const {
orderingDirection: perfOrderingDirection,
paginateBy: perfPaginateBy,
ordering: perfOrdering
} = toRefs(preferences)
const queryPaginateBy = useRouteQuery<string>('paginateBy', perfPaginateBy.value.toString())
const paginateBy = ref()
syncRef(queryPaginateBy, paginateBy, {
transform: {
ltr: (left) => +left,
rtl: (right) => right.toString()
}
})
const queryOrdering = useRouteQuery('ordering', perfOrderingDirection.value + perfOrdering.value)
console.log(queryOrdering.value)
watch(queryOrdering, (ordering) => {
perfOrderingDirection.value = ordering[0] === '-' ? '-' : '+'
perfOrdering.value = ordering[0] === '-' || ordering[0] === '+'
? ordering.slice(1)
: ordering
})
watch(perfOrderingDirection, (direction) => {
if (direction === '-') {
queryOrdering.value = direction + perfOrdering.value
return
}
queryOrdering.value = perfOrdering.value
})
watch(perfOrdering, (field) => {
const direction = perfOrderingDirection.value
queryOrdering.value = (direction === '-' ? '-' : '') + field
})
watch(queryPaginateBy, (paginateBy) => {
perfPaginateBy.value = +paginateBy
})
const onOrderingUpdate = (fn: () => void) => watch(preferences, fn)
return {
paginateBy,
ordering: perfOrdering,
orderingDirection: perfOrderingDirection,
orderingString: queryOrdering,
onOrderingUpdate
}
}

Wyświetl plik

@ -0,0 +1,16 @@
import { useRouteQuery } from '@vueuse/router'
import { syncRef } from '@vueuse/core'
import { ref } from 'vue'
export default () => {
const pageQuery = useRouteQuery<string>('page', '1')
const page = ref()
syncRef(pageQuery, page, {
transform: {
ltr: (left) => +left,
rtl: (right) => right.toString()
}
})
return page
}

Wyświetl plik

@ -1,18 +1,17 @@
import type { MaybeRef } from '@vueuse/core'
import type { Token } from '~/utils/search'
import { refWithControl } from '@vueuse/core'
import { computed, ref, unref, watch } from 'vue'
import { useRouter } from 'vue-router'
import { compileTokens, normalizeQuery, parseTokens } from '~/utils/search'
import { refWithControl } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
export interface SmartSearchProps {
defaultQuery?: string
updateUrl?: boolean
}
export default (defaultQuery: MaybeRef<string>, updateUrl: MaybeRef<boolean>) => {
const query = refWithControl(unref(defaultQuery))
export default (props: SmartSearchProps) => {
const query = refWithControl(props.defaultQuery ?? '')
const tokens = ref([] as Token[])
watch(query, (value) => {
@ -28,7 +27,7 @@ export default (defaultQuery: MaybeRef<string>, updateUrl: MaybeRef<boolean>) =>
const router = useRouter()
watch(tokens, (value) => {
const newQuery = compileTokens(value)
if (unref(updateUrl)) {
if (props.updateUrl) {
return router.replace({ query: { q: newQuery } })
}
@ -67,7 +66,6 @@ export default (defaultQuery: MaybeRef<string>, updateUrl: MaybeRef<boolean>) =>
return
}
// TODO (wvffle): Check if triggers reactivity
for (const token of existing) {
token.value = value
}

Wyświetl plik

@ -54,6 +54,10 @@ async function useErrorHandler (error: Error | BackendError, eventId?: string):
}
}
if ('isHandled' in error && error.isHandled) {
return
}
store.commit('ui/addMessage', {
content,
date,

Wyświetl plik

@ -1,44 +0,0 @@
import type { OrderingDirection, OrderingField, RouteWithPreferences } from '~/store/ui'
import type { MaybeRef } from '@vueuse/core'
import { reactiveComputed, toRefs } from '@vueuse/core'
import { computed, unref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { useStore } from '~/store'
export interface OrderingProps {
orderingConfigName: RouteWithPreferences | null
}
export default (orderingConfigName: MaybeRef<RouteWithPreferences | null>) => {
const store = useStore()
const route = useRoute()
const config = reactiveComputed(() => {
const name = unref(orderingConfigName) ?? route.name as RouteWithPreferences
return { ...store.state.ui.routePreferences[name] }
})
const { paginateBy, ordering, orderingDirection } = toRefs(config)
const orderingString = computed(() => {
if (orderingDirection.value === '-') return `-${ordering.value}`
return ordering.value
})
const getOrderingFromString = (str: string) => ({
direction: (str[0] === '-' ? '-' : '+') as OrderingDirection,
field: (str[0] === '-' || str[0] === '+' ? str.slice(1) : str) as OrderingField
})
const onOrderingUpdate = (fn: () => void) => watch(config, fn)
return {
paginateBy,
ordering,
orderingDirection,
orderingString,
getOrderingFromString,
onOrderingUpdate
}
}

Wyświetl plik

@ -30,6 +30,7 @@ export const install: InitModule = ({ store, router }) => {
return response
}, async (error: BackendError) => {
error.backendErrors = []
error.isHandled = false
if (store.state.auth.authenticated && !store.state.auth.oauth.accessToken && error.response?.status === 401) {
store.commit('auth/authenticated', false)
@ -40,8 +41,10 @@ export const install: InitModule = ({ store, router }) => {
switch (error.response?.status) {
case 404:
error.backendErrors.push('Resource not found')
error.isHandled = true
store.commit('ui/addMessage', {
content: error.response?.data,
// @ts-expect-error TS does not know about .data structure
content: error.response?.data?.detail ?? error.response?.data,
class: 'error'
})
break
@ -71,6 +74,7 @@ export const install: InitModule = ({ store, router }) => {
}
error.backendErrors.push(message)
error.isHandled = true
store.commit('ui/addMessage', {
content: message,
date: new Date(),

Wyświetl plik

@ -54,13 +54,7 @@ export default [
{
path: '/search',
name: 'search',
component: () => import('~/views/Search.vue'),
props: route => ({
initialId: route.query.id,
initialType: route.query.type || 'artists',
initialQuery: route.query.q,
initialPage: route.query.page ? +route.query.page : undefined
})
component: () => import('~/views/Search.vue')
},
...auth,
...settings,

Wyświetl plik

@ -20,96 +20,60 @@ export default [
path: 'artists/',
name: 'library.artists.browse',
component: () => import('~/components/library/Artists.vue'),
props: route => ({
defaultOrdering: route.query.ordering,
defaultQuery: route.query.query,
defaultTags: Array.isArray(route.query.tag || [])
? route.query.tag
: [route.query.tag],
defaultPage: route.query.page ? +route.query.page : undefined,
orderingConfigName: null
})
meta: {
paginateBy: 30
}
},
{
path: 'me/artists',
name: 'library.artists.me',
component: () => import('~/components/library/Artists.vue'),
props: route => ({
scope: 'me',
defaultOrdering: route.query.ordering,
defaultQuery: route.query.query,
defaultTags: Array.isArray(route.query.tag || [])
? route.query.tag
: [route.query.tag],
defaultPage: route.query.page ? +route.query.page : undefined,
orderingConfigName: null
})
props: { scope: 'me' },
meta: {
paginateBy: 30
}
},
{
path: 'albums/',
name: 'library.albums.browse',
component: () => import('~/components/library/Albums.vue'),
props: route => ({
defaultOrdering: route.query.ordering,
defaultQuery: route.query.query,
defaultTags: Array.isArray(route.query.tag || [])
? route.query.tag
: [route.query.tag],
defaultPage: route.query.page ? +route.query.page : undefined,
orderingConfigName: null
})
},
{
path: 'podcasts/',
name: 'library.podcasts.browse',
component: () => import('~/components/library/Podcasts.vue'),
props: route => ({
defaultOrdering: route.query.ordering,
defaultQuery: route.query.query,
defaultTags: Array.isArray(route.query.tag || [])
? route.query.tag
: [route.query.tag],
defaultPage: route.query.page ? +route.query.page : undefined,
orderingConfigName: null
})
meta: {
paginateBy: 25
}
},
{
path: 'me/albums',
name: 'library.albums.me',
component: () => import('~/components/library/Albums.vue'),
props: route => ({
scope: 'me',
defaultOrdering: route.query.ordering,
defaultQuery: route.query.query,
defaultTags: Array.isArray(route.query.tag || [])
? route.query.tag
: [route.query.tag],
defaultPage: route.query.page ? +route.query.page : undefined,
orderingConfigName: null
})
props: { scope: 'me' },
meta: {
paginateBy: 25
}
},
{
path: 'podcasts/',
name: 'library.podcasts.browse',
component: () => import('~/components/library/Podcasts.vue'),
meta: {
paginateBy: 30
}
},
{
path: 'radios/',
name: 'library.radios.browse',
component: () => import('~/components/library/Radios.vue'),
props: route => ({
defaultOrdering: route.query.ordering,
defaultQuery: route.query.query,
defaultPage: route.query.page ? +route.query.page : undefined,
orderingConfigName: null
})
meta: {
paginateBy: 12
}
},
{
path: 'me/radios/',
name: 'library.radios.me',
component: () => import('~/components/library/Radios.vue'),
props: route => ({
scope: 'me',
defaultOrdering: route.query.ordering,
defaultQuery: route.query.query,
defaultPage: route.query.page ? +route.query.page : undefined,
orderingConfigName: null
})
props: { scope: 'me' },
meta: {
paginateBy: 12
}
},
{
path: 'radios/build',
@ -133,24 +97,18 @@ export default [
path: 'playlists/',
name: 'library.playlists.browse',
component: () => import('~/views/playlists/List.vue'),
props: route => ({
defaultOrdering: route.query.ordering,
defaultQuery: route.query.query,
defaultPage: route.query.page ? +route.query.page : undefined,
orderingConfigName: null
})
meta: {
paginateBy: 25
}
},
{
path: 'me/playlists/',
name: 'library.playlists.me',
component: () => import('~/views/playlists/List.vue'),
props: route => ({
scope: 'me',
defaultOrdering: route.query.ordering,
defaultQuery: route.query.query,
defaultPage: route.query.page ? +route.query.page : undefined,
orderingConfigName: null
})
props: { scope: 'me' },
meta: {
paginateBy: 25
}
},
{
path: 'playlists/:id',

Wyświetl plik

@ -157,7 +157,9 @@ export default [
path: 'reports',
name: 'manage.moderation.reports.list',
component: () => import('~/views/admin/moderation/ReportsList.vue'),
props: route => ({ defaultQuery: route.query.q, updateUrl: true, orderingConfigName: null })
meta: {
paginateBy: 25
}
},
{
path: 'reports/:id',
@ -169,7 +171,9 @@ export default [
path: 'requests',
name: 'manage.moderation.requests.list',
component: () => import('~/views/admin/moderation/RequestsList.vue'),
props: route => ({ defaultQuery: route.query.q, updateUrl: true, orderingConfigName: null })
meta: {
paginateBy: 25
}
},
{
path: 'requests/:id',

Wyświetl plik

@ -0,0 +1,9 @@
import 'vue-router'
declare module 'vue-router' {
interface RouteMeta {
orderingDirection?: '-' | '+'
ordering?: OrderingField
paginateBy?: number
}
}

Wyświetl plik

@ -1,6 +1,6 @@
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}

Wyświetl plik

@ -7,15 +7,6 @@ import moment from 'moment'
type SupportedExtension = 'flac' | 'ogg' | 'mp3' | 'opus' | 'aac' | 'm4a' | 'aiff' | 'aif'
export type RouteWithPreferences = 'library.artists.browse' | 'library.podcasts.browse' | 'library.radios.browse'
| 'library.playlists.browse' | 'library.albums.me' | 'library.artists.me' | 'library.radios.me'
| 'library.playlists.me' | 'content.libraries.files' | 'library.detail.upload' | 'library.detail.edit'
| 'library.detail' | 'favorites' | 'manage.channels' | 'manage.library.tags' | 'manage.library.uploads'
| 'manage.library.libraries' | 'manage.library.tracks' | 'manage.library.albums' | 'manage.library.artists'
| 'manage.library.edits' | 'manage.users.users.list' | 'manage.users.invitations.list'
| 'manage.moderation.accounts.list' | 'manage.moderation.domains.list' | 'manage.moderation.requests.list'
| 'manage.moderation.reports.list' | 'library.albums.browse'
export type WebSocketEventName = 'inbox.item_added' | 'import.status_updated' | 'mutation.created' | 'mutation.updated'
| 'report.created' | 'user_request.created' | 'Listen'
@ -26,12 +17,6 @@ export type OrderingField = 'creation_date' | 'title' | 'album__title' | 'artist
| 'last_activity' | 'username'
export type OrderingDirection = '-' | '+'
interface RoutePreferences {
paginateBy: number
orderingDirection: OrderingDirection
ordering: OrderingField
}
interface WebSocketEvent {
type: WebSocketEventName
}
@ -63,7 +48,6 @@ export interface State {
notifications: Record<NotificationsKey, number>
websocketEventsHandlers: Record<WebSocketEventName, WebSocketHandlers>
routePreferences: Record<RouteWithPreferences, RoutePreferences>
}
const store: Module<State, RootState> = {
@ -97,149 +81,7 @@ const store: Module<State, RootState> = {
'user_request.created': {},
Listen: {}
},
pageTitle: null,
routePreferences: {
'library.albums.browse': {
paginateBy: 25,
orderingDirection: '-',
ordering: 'creation_date'
},
'library.artists.browse': {
paginateBy: 30,
orderingDirection: '-',
ordering: 'creation_date'
},
'library.podcasts.browse': {
paginateBy: 30,
orderingDirection: '-',
ordering: 'creation_date'
},
'library.radios.browse': {
paginateBy: 12,
orderingDirection: '-',
ordering: 'creation_date'
},
'library.playlists.browse': {
paginateBy: 25,
orderingDirection: '-',
ordering: 'creation_date'
},
'library.albums.me': {
paginateBy: 25,
orderingDirection: '-',
ordering: 'creation_date'
},
'library.artists.me': {
paginateBy: 30,
orderingDirection: '-',
ordering: 'creation_date'
},
'library.radios.me': {
paginateBy: 12,
orderingDirection: '-',
ordering: 'creation_date'
},
'library.playlists.me': {
paginateBy: 25,
orderingDirection: '-',
ordering: 'creation_date'
},
'content.libraries.files': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'library.detail.upload': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'library.detail.edit': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'library.detail': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
favorites: {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.channels': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.library.tags': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.library.uploads': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.library.libraries': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.library.tracks': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.library.albums': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.library.artists': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.library.edits': {
paginateBy: 25,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.users.users.list': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.users.invitations.list': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.moderation.accounts.list': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.moderation.domains.list': {
paginateBy: 50,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.moderation.requests.list': {
paginateBy: 25,
orderingDirection: '-',
ordering: 'creation_date'
},
'manage.moderation.reports.list': {
paginateBy: 25,
orderingDirection: '-',
ordering: 'creation_date'
}
}
pageTitle: null
},
getters: {
showInstanceSupportMessage: (state, getters, rootState) => {

Wyświetl plik

@ -218,6 +218,7 @@ export interface Listening {
export interface APIErrorResponse extends Record<string, APIErrorResponse | string[] | { code: string }[]> {}
export interface BackendError extends AxiosError {
isHandled: boolean
backendErrors: string[]
rawPayload?: APIErrorResponse
}

Wyświetl plik

@ -1,39 +1,42 @@
<script setup lang="ts">
import type { RadioConfig } from '~/store/radios'
import { ref, reactive, computed, watch } from 'vue'
import { useRouteQuery } from '@vueuse/router'
import { useGettext } from 'vue3-gettext'
import { syncRef } from '@vueuse/core'
import axios from 'axios'
import PlaylistCardList from '~/components/playlists/CardList.vue'
import RemoteSearchForm from '~/components/RemoteSearchForm.vue'
import ArtistCard from '~/components/audio/artist/Card.vue'
import AlbumCard from '~/components/audio/album/Card.vue'
import TrackTable from '~/components/audio/track/Table.vue'
import AlbumCard from '~/components/audio/album/Card.vue'
import Pagination from '~/components/vui/Pagination.vue'
import PlaylistCardList from '~/components/playlists/CardList.vue'
import RadioCard from '~/components/radios/Card.vue'
import RadioButton from '~/components/radios/Button.vue'
import RadioCard from '~/components/radios/Card.vue'
import TagsList from '~/components/tags/List.vue'
import { ref, reactive, computed, watch } from 'vue'
import { useRouter, onBeforeRouteUpdate } from 'vue-router'
import { useGettext } from 'vue3-gettext'
import axios from 'axios'
import useErrorHandler from '~/composables/useErrorHandler'
type QueryType = 'artists' | 'albums' | 'tracks' | 'playlists' | 'tags' | 'radios' | 'podcasts' | 'series' | 'rss'
interface Props {
initialId?: string
initialType?: QueryType
initialQuery?: string
initialPage?: number
}
const type = useRouteQuery<QueryType>('type', 'artists')
const id = useRouteQuery<string>('id')
const props = withDefaults(defineProps<Props>(), {
initialId: '',
initialType: 'artists',
initialQuery: '',
initialPage: 1
const pageQuery = useRouteQuery<string>('page', '1')
const page = ref(+pageQuery.value)
syncRef(pageQuery, page, {
transform: {
ltr: (left) => +left,
rtl: (right) => right.toString()
}
})
const query = ref(props.initialQuery)
const type = ref(props.initialType)
const page = ref(props.initialPage)
const q = useRouteQuery('q', '')
const query = ref(q.value)
syncRef(q, query, { direction: 'ltr' })
type ResponseType = { count: number, results: any[] }
const results = reactive({
@ -122,19 +125,12 @@ const axiosParams = computed(() => {
const currentResults = computed(() => results[currentType.value?.id ?? 'artists'])
const router = useRouter()
const updateQueryString = () => router.replace({
query: {
q: query.value,
page: page.value,
type: type.value
}
})
const isLoading = ref(false)
const search = async () => {
if (!currentType.value) return
q.value = query.value
if (!query.value) {
for (const type of types.value) {
results[type.id] = null
@ -144,11 +140,16 @@ const search = async () => {
}
isLoading.value = true
const response = await axios.get(currentType.value.endpoint ?? currentType.value.id, {
params: axiosParams.value
})
results[currentType.value.id] = response.data
try {
const response = await axios.get(currentType.value.endpoint ?? currentType.value.id, {
params: axiosParams.value
})
results[currentType.value.id] = response.data
} catch (error) {
useErrorHandler(error as Error)
}
isLoading.value = false
@ -164,25 +165,20 @@ const search = async () => {
}
}).then(response => {
results[type.id] = response.data
})
}).catch(() => undefined)
}
}
}
watch(type, () => (page.value = 1))
watch(page, updateQueryString)
watch(type, () => {
page.value = 1
search()
})
onBeforeRouteUpdate(search)
// TODO: (wvffle): Check if it's needed
// watch: {
// '$route.query.q': async function (v) {
// this.query = v
// }
// },
search()
const labels = computed(() => ({
title: props.initialId
title: id.value
? (
type.value === 'rss'
? $pgettext('Head/Fetch/Title', 'Subscribe to a podcast RSS feed')
@ -224,13 +220,13 @@ const radioConfig = computed(() => {
>
<section class="ui vertical stripe segment">
<div
v-if="initialId"
v-if="id"
class="ui small text container"
>
<h2>{{ labels.title }}</h2>
<remote-search-form
:initial-id="initialId"
:type="initialType"
:initial-id="id"
:type="type"
/>
</div>
<div

Wyświetl plik

@ -54,58 +54,44 @@ const title = computed(() => labels.value[props.type])
v-if="type === 'accounts'"
:update-url="true"
:default-query="defaultQuery"
:ordering-config-name="null"
/>
<albums-table
v-else-if="type === 'albums'"
:update-url="true"
:default-query="defaultQuery"
:ordering-config-name="null"
/>
<artists-table
v-else-if="type === 'artists'"
:update-url="true"
:default-query="defaultQuery"
:ordering-config-name="null"
/>
<channels-table
v-else-if="type === 'channels'"
:update-url="true"
:default-query="defaultQuery"
:ordering-config-name="null"
/>
<invitations-table
v-else-if="type === 'invitations'"
:ordering-config-name="null"
/>
<invitations-table v-else-if="type === 'invitations'" />
<libraries-table
v-else-if="type === 'libraries'"
:update-url="true"
:default-query="defaultQuery"
:ordering-config-name="null"
/>
<tags-table
v-else-if="type === 'tags'"
:update-url="true"
:default-query="defaultQuery"
:ordering-config-name="null"
/>
<tracks-table
v-else-if="type === 'tracks'"
:update-url="true"
:default-query="defaultQuery"
:ordering-config-name="null"
/>
<uploads-table
v-else-if="type === 'uploads'"
:update-url="true"
:default-query="defaultQuery"
:ordering-config-name="null"
/>
<users-table
v-else-if="type === 'users'"
:ordering-config-name="null"
/>
<users-table v-else-if="type === 'users'" />
</section>
</main>
</template>

Wyświetl plik

@ -24,7 +24,6 @@ const labels = computed(() => ({
<edits-card-list
:update-url="true"
:default-query="defaultQuery"
:ordering-config-name="null"
>
<h2 class="ui header">
<translate translate-context="Content/Admin/Title/Noun">

Wyświetl plik

@ -113,10 +113,7 @@ const createDomain = async () => {
</div>
</form>
<div class="ui clearing hidden divider" />
<domains-table
:ordering-config-name="null"
:allow-list-enabled="allowListEnabled"
/>
<domains-table :allow-list-enabled="allowListEnabled" />
</section>
</main>
</template>

Wyświetl plik

@ -1,7 +1,9 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { OrderingProps } from '~/composables/useOrdering'
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { Report, BackendResponse } from '~/types'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { computed, ref, watch } from 'vue'
import { useGettext } from 'vue3-gettext'
@ -13,35 +15,33 @@ import ReportCategoryDropdown from '~/components/moderation/ReportCategoryDropdo
import ReportCard from '~/components/manage/moderation/ReportCard.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends SmartSearchProps, OrderingProps {
mode?: 'card'
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
defaultQuery?: string
orderingConfigName?: RouteRecordName
updateUrl?: boolean
}
const props = withDefaults(defineProps<Props>(), {
defaultQuery: '',
updateUrl: false,
mode: 'card'
mode: 'card',
orderingConfigName: undefined
})
const search = ref()
// TODO (wvffle): Make sure everything is it's own type
const page = ref(1)
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const page = usePage()
const result = ref<BackendResponse<Report>>()
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],
@ -74,7 +74,7 @@ const fetchData = async () => {
}
} catch (error) {
useErrorHandler(error as Error)
result.value = null
result.value = undefined
} finally {
isLoading.value = false
}

Wyświetl plik

@ -1,7 +1,9 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/useOrdering'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { UserRequest, BackendResponse } from '~/types'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { ref, computed, watch } from 'vue'
import { useGettext } from 'vue3-gettext'
@ -12,32 +14,30 @@ import axios from 'axios'
import UserRequestCard from '~/components/manage/moderation/UserRequestCard.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Props extends SmartSearchProps, OrderingProps {
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
defaultQuery?: string
orderingConfigName?: RouteRecordName
updateUrl?: boolean
}
const props = withDefaults(defineProps<Props>(), {
defaultQuery: '',
updateUrl: false
updateUrl: false,
orderingConfigName: undefined
})
const search = ref()
// TODO (wvffle): Make sure everything is it's own type
const page = ref(1)
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const page = usePage()
const result = ref<BackendResponse<UserRequest>>()
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],
@ -70,7 +70,7 @@ const fetchData = async () => {
}
} catch (error) {
useErrorHandler(error as Error)
result.value = null
result.value = undefined
} finally {
isLoading.value = false
}

Wyświetl plik

@ -10,9 +10,6 @@ defineProps<Props>()
<template>
<section class="ui vertical aligned stripe segment">
<library-files-table
:ordering-config-name="null"
:default-query="query"
/>
<library-files-table :default-query="query" />
</section>
</template>

Wyświetl plik

@ -1,8 +1,9 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { SmartSearchProps } from '~/composables/useSmartSearch'
import type { OrderingProps } from '~/composables/useOrdering'
import type { ImportStatus } from '~/types'
import type { SmartSearchProps } from '~/composables/navigation/useSmartSearch'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { ImportStatus, BackendResponse, Upload } from '~/types'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { humanSize, truncate } from '~/utils/filters'
import { computed, ref, watch } from 'vue'
@ -16,9 +17,10 @@ import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useSmartSearch from '~/composables/useSmartSearch'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
interface Events {
(e: 'fetch-start'): void
@ -30,7 +32,7 @@ interface Props extends SmartSearchProps, OrderingProps {
customObjects?: any[]
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
defaultQuery?: string
updateUrl?: boolean
}
@ -41,18 +43,17 @@ const props = withDefaults(defineProps<Props>(), {
updateUrl: false,
filters: () => ({}),
needsRefresh: false,
customObjects: () => []
customObjects: () => [],
orderingConfigName: undefined
})
const search = ref()
// TODO (wvffle): Make sure everything is it's own type
const page = ref(1)
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const page = usePage()
const result = ref<BackendResponse<Upload>>()
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props.defaultQuery, props.updateUrl)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const { onSearch, query, addSearchToken, getTokenValue } = useSmartSearch(props)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],
@ -79,8 +80,7 @@ const actions = computed(() => [
label: $pgettext('Content/Library/Dropdown/Verb', 'Restart import'),
isDangerous: true,
allowAll: true,
// TODO (wvffle): Find correct type
filterCheckable: (filter: { import_status: string }) => {
filterCheckable: (filter: { import_status: ImportStatus }) => {
return filter.import_status !== 'finished'
}
}
@ -107,7 +107,7 @@ const fetchData = async () => {
result.value = response.data
} catch (error) {
useErrorHandler(error as Error)
result.value = null
result.value = undefined
} finally {
isLoading.value = false
}

Wyświetl plik

@ -63,10 +63,7 @@ const updateApproved = async (follow: LibraryFollow, approved: boolean) => {
Library contents
</translate>
</h2>
<library-files-table
:filters="{library: object.uuid}"
:ordering-config-name="null"
/>
<library-files-table :filters="{ library: object.uuid }" />
<div class="ui hidden divider" />
<h2 class="ui header">

Wyświetl plik

@ -1,41 +1,46 @@
<script setup lang="ts">
import type { RouteWithPreferences, OrderingField } from '~/store/ui'
import type { OrderingProps } from '~/composables/useOrdering'
import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { Playlist, BackendResponse } from '~/types'
import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui'
import { computed, onMounted, ref, watch } from 'vue'
import { useRouteQuery } from '@vueuse/router'
import { useGettext } from 'vue3-gettext'
import { syncRef } from '@vueuse/core'
import { sortedUniq } from 'lodash-es'
import axios from 'axios'
import $ from 'jquery'
import { useRouter, onBeforeRouteUpdate } from 'vue-router'
import { computed, ref, watch, onMounted } from 'vue'
import { useGettext } from 'vue3-gettext'
import PlaylistCardList from '~/components/playlists/CardList.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler'
import useOrdering from '~/composables/useOrdering'
import usePage from '~/composables/navigation/usePage'
import useLogger from '~/composables/useLogger'
interface Props extends OrderingProps {
defaultPage?: number
defaultQuery?: string
scope?: string
scope?: 'me' | 'all'
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
orderingConfigName: RouteWithPreferences | null
orderingConfigName?: RouteRecordName
}
const props = withDefaults(defineProps<Props>(), {
defaultPage: 1,
defaultQuery: '',
scope: 'all'
scope: 'all',
orderingConfigName: undefined
})
const page = ref(+props.defaultPage)
type ResponseType = { count: number, results: any[] }
const result = ref<null | ResponseType>(null)
const query = ref(props.defaultQuery)
const page = usePage()
const q = useRouteQuery('query', '')
const query = ref(q.value)
syncRef(q, query, { direction: 'ltr' })
const result = ref<BackendResponse<Playlist>>()
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
['creation_date', 'creation_date'],
@ -46,20 +51,7 @@ const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
const logger = useLogger()
const sharedLabels = useSharedLabels()
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props.orderingConfigName)
const router = useRouter()
const updateQueryString = () => router.replace({
query: {
query: query.value,
page: page.value,
paginateBy: paginateBy.value,
ordering: orderingString.value
}
})
watch(page, updateQueryString)
onOrderingUpdate(updateQueryString)
const { onOrderingUpdate, orderingString, paginateBy, ordering, orderingDirection } = useOrdering(props)
const isLoading = ref(false)
const fetchData = async () => {
@ -82,15 +74,25 @@ const fetchData = async () => {
result.value = response.data
} catch (error) {
useErrorHandler(error as Error)
result.value = null
result.value = undefined
} finally {
logger.timeEnd('Fetching albums')
isLoading.value = false
}
}
onBeforeRouteUpdate(fetchData)
watch(page, fetchData)
fetchData()
const search = () => {
page.value = 1
q.value = query.value
}
onOrderingUpdate(() => {
page.value = 1
fetchData()
})
onMounted(() => $('.ui.dropdown').dropdown())
const { $pgettext } = useGettext()
@ -98,6 +100,8 @@ const labels = computed(() => ({
playlists: $pgettext('*/*/*', 'Playlists'),
searchPlaceholder: $pgettext('Content/Playlist/Placeholder/Call to action', 'Enter playlist name…')
}))
const paginateOptions = computed(() => sortedUniq([12, 25, 50, paginateBy.value].sort((a, b) => a - b)))
</script>
<template>
@ -121,7 +125,7 @@ const labels = computed(() => ({
</template>
<form
:class="['ui', {'loading': isLoading}, 'form']"
@submit.prevent="updateQueryString();fetchData()"
@submit.prevent="search"
>
<div class="fields">
<div class="field">
@ -185,14 +189,12 @@ const labels = computed(() => ({
v-model="paginateBy"
class="ui dropdown"
>
<option :value="12">
12
</option>
<option :value="25">
25
</option>
<option :value="50">
50
<option
v-for="opt in paginateOptions"
:key="opt"
:value="opt"
>
{{ opt }}
</option>
</select>
</div>

Wyświetl plik

@ -1905,6 +1905,14 @@
resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-9.1.1.tgz#b3fe4b97e62096f7566cd8eb107c503998b2c9a6"
integrity sha512-XZ2KtSW+85LLHB/IdGILPAtbIVHasPsAW7aqz3BRMzJdAQWRiM/FGa1OKBwLbXtUw/AmjKYFlZJo7eOFIBXRog==
"@vueuse/router@^9.1.1":
version "9.1.1"
resolved "https://registry.yarnpkg.com/@vueuse/router/-/router-9.1.1.tgz#356946b97e2499d96d8e9b5cfced5f778edd63c9"
integrity sha512-1HE09QYoHEUF2vWJqGEV1GgoFy6ti7gxzahiN9o/GJpyWM11koQd03BhP4RjVbUx3ua2wTYNSmaCKvLJGCnNGg==
dependencies:
"@vueuse/shared" "9.1.1"
vue-demi "*"
"@vueuse/shared@9.1.1":
version "9.1.1"
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-9.1.1.tgz#811f47629e281a19013ae6dcdf11ed3e1e91e023"