From c271517eb58d000a420d6bf8842949cea5823067 Mon Sep 17 00:00:00 2001 From: Lightling Date: Fri, 3 May 2024 18:35:52 -0400 Subject: [PATCH] introduce tag filtering on project-list --- .../src/views/project/project-list.vue | 52 ++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/projects/frontend/src/views/project/project-list.vue b/projects/frontend/src/views/project/project-list.vue index 2281331..504715d 100644 --- a/projects/frontend/src/views/project/project-list.vue +++ b/projects/frontend/src/views/project/project-list.vue @@ -10,21 +10,51 @@ import { fetchAndParseYaml } from 'src/utilities/fetch' import { getCurrentRoute } from 'src/utilities/vuetils' import { useRouteStore } from 'src/routes' +import FilterPanel from 'src/components/shared/filter-panel.vue' import ProjectTile from './project-tile.vue' +/** + * A wrapper around {@link GalleryEntries} for the app's use only which adds additional fields + * in order for the app to effectively display the entries. + */ + type ProjectDisplayedEntries = { [idOrTitle: string]: ProjectListingInfo & { + /** + * specifies whether the entry is hidden by the tags selected by a visitor + */ + hidden?: boolean +}} + const projectIds = ref([] as string[]) -const projects = ref({} as { [key: string]: ProjectListingInfo }) +const projects = ref({} as ProjectDisplayedEntries) const ready = ref(false) const currentRoute = getCurrentRoute() const routeStore = useRouteStore() const routeConfig = routeStore._routes[currentRoute.path] as ProjectListDefinition +const config = ref(null as ProjectList | null) + +/** + * Handler for a tag being selected; + * updates the visibility state of the current entries + * @param tagsToggled: the tags currently toggled in the filter panel + */ + const onToggledTagsChanged = (tagsToggled: string[]) => { + if (tagsToggled.length < 1) { + Object.keys(projects.value).forEach(entryId => { + projects.value[entryId].hidden = false + }) + } else { + Object.keys(projects.value).forEach(entryId => { + projects.value[entryId].hidden = !projects.value[entryId].tags?.some(own => tagsToggled.includes(own)) + }) + } +} onMounted(async () => { - const config = await fetchAndParseYaml(routeConfig.config) - projectIds.value = Object.keys(config.projects) + config.value = await fetchAndParseYaml(routeConfig.config) + projectIds.value = Object.keys(config.value.projects) for (let i = 0; i < projectIds.value.length; ++i) { const id = projectIds.value[i] - projects.value[id] = await fetchAndParseYaml(config.projects[id].config) + projects.value[id] = await fetchAndParseYaml(config.value.projects[id].config) } document.title = routeConfig.title ready.value = true @@ -36,11 +66,19 @@ onMounted(async () => { #projects( v-if='ready' ) - ProjectTile( + Transition( v-for='id in projectIds' - :id='id' - :info='projects[id]' ) + ProjectTile( + v-if='!projects[id].hidden' + :id='id' + :info='projects[id]' + ) + FilterPanel( + v-if='ready && !!config.tags' + :tags='config.tags' + @toggledTagsChanged='onToggledTagsChanged($event)' + )