diff --git a/src/views/gallery/gallery-list.vue b/src/views/gallery/gallery-list.vue index 8dec3df..3ad0a04 100644 --- a/src/views/gallery/gallery-list.vue +++ b/src/views/gallery/gallery-list.vue @@ -2,7 +2,7 @@ import { onMounted, ref } from 'vue' import { type RouteRecordRaw, useRouter } from 'vue-router' -import type { GalleryEntries, GalleryList } from './gallery' +import type { GalleryDisplayedEntries, GalleryList } from './gallery' import { type GalleryListDefinition } from 'content/routes.js' import { amendVariantsWithDefaults } from './gallery-utilities' import { fetchAndParseYaml, storage } from 'src/utilities/fetch' @@ -26,13 +26,30 @@ const globalConfig = routeStore._globals const storageId = `${globalConfig.id}` const router = useRouter() let config: GalleryList = null! +const tagsToggled: string[] = [] const ready = ref(false) const galleryReady = ref(false) -const entries = ref({} as GalleryEntries) +const entries = ref({} as GalleryDisplayedEntries) const variants = ref(validateVariants(props.variants)) const hasWarnings = ref(false) const hideWarnings = defineModel('showWarnings', { type: Boolean }) +const tagsByCategory = ref({} as { [category: string]: Record }) + +const onLoadTags = () => { + tagsByCategory.value = { 'NoCategory': {}} + Object.keys(config.tags).forEach(id => { + const tag = config.tags[id] + if (!!tag.category) { + if (!tagsByCategory.value[tag.category]) { + tagsByCategory.value[tag.category] = {} + } + tagsByCategory.value[tag.category][id] = tag.displayName || id + } else { + tagsByCategory.value['NoCategory'][id] = tag.displayName || id + } + }) +} const onDisplayEntries = () => { galleryReady.value = false @@ -83,10 +100,33 @@ const onHideWarningsToggled = (event: Event) => { storage.write(`${storageId}::hideWarnings`, (event.target as HTMLInputElement).checked) } +const onToggleTag = (event: Event, tagId: string) => { + if ((event.target as HTMLInputElement).checked) { + tagsToggled.push(tagId) + } else { + const index = tagsToggled.indexOf(tagId) + if (index > -1) { + tagsToggled.splice(index, 1) + } + } + + if (tagsToggled.length < 1) { + Object.keys(entries.value).forEach(entryId => { + entries.value[entryId].hidden = false + }) + } else { + Object.keys(entries.value).forEach(entryId => { + entries.value[entryId].hidden = !entries.value[entryId].tags.some(own => tagsToggled.includes(own)) + }) + } +} + onMounted(async () => { + ready.value = false config = await fetchAndParseYaml(routeConfig.config) document.title = routeConfig.title hideWarnings.value = storage.read(`${storageId}::hideWarnings`) || false + onLoadTags() onDisplayEntries() ready.value = true }) @@ -115,17 +155,44 @@ onMounted(async () => { v-model='hideWarnings' @input='onHideWarningsToggled($event)' ) + Transition + .filters( + v-if='galleryReady' + ) + .category( + v-for='(tags, category) in tagsByCategory' + :id='category' + ) + h2( + v-if='category !== "NoCategory"' + ) {{ category }} + .input.labeled-checkbox( + v-for='(tagDisplayName, tagId) in tags' + :id='tagId' + ) + label( + :for='`${tagId}-toggle`' + ) {{ tagDisplayName }} + input( + type='checkbox' + :name='`${tagId}-toggle`' + :id='`${tagId}-toggle`' + @input='onToggleTag($event, tagId)' + ) Transition .gallery( v-if='galleryReady' ) - GalleryTile( + Transition( v-for='(entry, id) in entries' - :entry='entry' - :id='id' - :hideWarnings='hideWarnings' - @click='onTileClicked($event)' ) + GalleryTile( + v-if='!entry.hidden' + :entry='entry' + :id='id' + :hideWarnings='hideWarnings' + @click='onTileClicked($event)' + )