feat(front): [WIP] couple tagsList to query
This commit is contained in:
parent
c2c0a2aa79
commit
e9e42c53b9
|
@ -48,8 +48,9 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
|
||||
const page = usePage()
|
||||
|
||||
const tags = useRouteQuery<string[]>('tag', [])
|
||||
const tagList = useTags().model(tags.value)
|
||||
const tags = useRouteQuery<string[]>('tag', [], { transform: (param: string | string[] | null) => (param === null ? [] : Array.isArray(param) ? param : [param]).filter(p => p.trim() !== '') })
|
||||
|
||||
const tagList = useTags(tags)
|
||||
|
||||
const q = useRouteQuery('query', '')
|
||||
const query = ref(q.value ?? '')
|
||||
|
@ -152,6 +153,7 @@ const paginateOptions = computed(() => sortedUniq([12, 30, 50, paginateBy.value]
|
|||
autofocus
|
||||
:placeholder="labels.searchPlaceholder"
|
||||
/>
|
||||
{{ tagList }}
|
||||
<Pills
|
||||
v-model="tagList"
|
||||
:label="t('components.library.Albums.label.tags')"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { paths } from '~/generated/types.ts'
|
||||
|
||||
import { computed, ref } from 'vue'
|
||||
import { computed, ref, type Ref } from 'vue'
|
||||
import { useStore } from '~/store'
|
||||
import axios from 'axios'
|
||||
|
||||
|
@ -8,19 +8,15 @@ type Item = { type: 'custom' | 'preset', label: string }
|
|||
type Model = { currents: Item[], others?: Item[] }
|
||||
|
||||
/**
|
||||
* Load and cache all tags
|
||||
* Load and cache all tags.
|
||||
* - Two-way binding with store (any change to the store will be reflected in `others`)
|
||||
* - Two-way binding with ref
|
||||
* @param currents Selected tags
|
||||
* @returns an object with `currents` and `others`, ready to be used inside
|
||||
*/
|
||||
export const useTags = <T> () => {
|
||||
export const useTags = (currents: Ref<string[], string[]>) => {
|
||||
const store = useStore()
|
||||
|
||||
// Two-way bind with store
|
||||
const tags = computed({
|
||||
get: () => store.state.ui.tags || [],
|
||||
set: function(value) {
|
||||
store.commit('ui/tags', value)
|
||||
}
|
||||
})
|
||||
|
||||
// Ignore quick successive fetch triggers
|
||||
const ignorePeriod = 500
|
||||
|
||||
|
@ -30,11 +26,13 @@ export const useTags = <T> () => {
|
|||
// Wait after changing a tag before re-fetching
|
||||
const refetchInterval = 6000
|
||||
|
||||
// Number of tags to load on one page
|
||||
const maxTags = 100000
|
||||
|
||||
const lastFetched = ref<number>(0)
|
||||
|
||||
const fetch = async () => {
|
||||
// console.log('FETCH TAGS')
|
||||
// Ignore subsequent fetch commands triggered in quick succession
|
||||
if (lastFetched.value + ignorePeriod > Date.now())
|
||||
return
|
||||
|
@ -50,40 +48,48 @@ export const useTags = <T> () => {
|
|||
{ params: { page: 1, page_size: maxTags } }
|
||||
)
|
||||
|
||||
tags.value = response.data.results
|
||||
// console.log('TAGS RESPONSE.data.results', response.data.results)
|
||||
store.commit('ui/tags', response.data.results)
|
||||
}
|
||||
|
||||
return ({
|
||||
fetch();
|
||||
|
||||
/**
|
||||
* @param currents Initial selected tags
|
||||
* @returns v-model for `Pills` component
|
||||
*/
|
||||
model: (currents: string[] = []) => {
|
||||
fetch();
|
||||
return computed({
|
||||
|
||||
// Get currents initially from parameter. Get others from backend.
|
||||
get: (): Model => ({
|
||||
currents: currents.map(tag => ({
|
||||
get () {
|
||||
// console.log("GET TAGS")
|
||||
return ({
|
||||
// Get `currents` from parameter
|
||||
currents: currents.value.map(tag => ({
|
||||
label: tag,
|
||||
type: tags.value.some(({ name }) => tag === name) ? 'preset' : 'custom'
|
||||
})),
|
||||
others: tags.value
|
||||
.filter(({ name }) => !currents.includes(name))
|
||||
type: (store.state.ui.tags || []).some(({ name }) => tag === name) ? 'preset' : 'custom'
|
||||
} as const)),
|
||||
|
||||
// Get `others` from cache
|
||||
others: (store.state.ui.tags || [])
|
||||
.filter(({ name }) => !currents.value.includes(name))
|
||||
.map(({ name }) => ({
|
||||
label: name,
|
||||
type: 'preset'
|
||||
}))
|
||||
}),
|
||||
} as const))
|
||||
})},
|
||||
|
||||
set (model) {
|
||||
// console.log('SET TAGS', response.data.results)
|
||||
|
||||
// Set parameter `currents` from `model.currents`
|
||||
currents.value = model.currents.map(({ label }) => label)
|
||||
|
||||
// Set runtime-only options from `model.others` and `model.current`
|
||||
// TODO: Broadcast new custom tags so that other pills components can use them
|
||||
|
||||
// Re-fetch after each new setting
|
||||
set: function (_) {
|
||||
window.setTimeout(fetch, refetchInterval)
|
||||
// TODO: Broadcast new custom tags so that other pills components can use them
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// alternative ways to generate tags
|
||||
// ...
|
||||
|
|
Loading…
Reference in New Issue