mirror of
https://github.com/tiennm99/HugoBlox-kit.git
synced 2026-10-13 18:15:09 +00:00
fix(search): filters + metadata across collection layouts
Fixes https://github.com/HugoBlox/hugo-blox-builder/discussions/3292
This commit is contained in:
1 parent
1c1d54bdc3
commit
d95cd5fac8
7 files changed
+160
-123
No files matched your search
@@ -267,6 +267,7 @@
|
||||
selectedIndex: -1,
|
||||
activeFilter: null,
|
||||
availableFilters: [],
|
||||
allFilters: [],
|
||||
trendingSearches: {{ site.Params.hugoblox.search.suggestions | default (slice "Search term 1" "Search term 2") | jsonify }},
|
||||
pagefind: null,
|
||||
pagefindModulePath: window.hbb?.assetPaths?.pagefind ?? '/pagefind/pagefind.js',
|
||||
@@ -336,6 +337,62 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
buildFilters(filterIndex) {
|
||||
const filters = [];
|
||||
|
||||
if (filterIndex?.type) {
|
||||
Object.entries(filterIndex.type).forEach(([value, count]) => {
|
||||
filters.push({
|
||||
category: 'type',
|
||||
value,
|
||||
label: this.typeLabels[value] || value.charAt(0).toUpperCase() + value.slice(1),
|
||||
count,
|
||||
filterKey: `type:${value}`
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (filterIndex?.category) {
|
||||
Object.entries(filterIndex.category).forEach(([value, count]) => {
|
||||
filters.push({
|
||||
category: 'category',
|
||||
value,
|
||||
label: value,
|
||||
count,
|
||||
filterKey: `category:${value}`
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (filterIndex?.difficulty) {
|
||||
Object.entries(filterIndex.difficulty).forEach(([value, count]) => {
|
||||
filters.push({
|
||||
category: 'difficulty',
|
||||
value,
|
||||
label: value,
|
||||
count,
|
||||
filterKey: `difficulty:${value}`
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return filters;
|
||||
},
|
||||
|
||||
mergeFilterCounts(filterCounts) {
|
||||
if (!this.allFilters.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.allFilters.map((filter) => {
|
||||
const count = filterCounts?.[filter.category]?.[filter.value];
|
||||
return {
|
||||
...filter,
|
||||
count: typeof count === 'number' ? count : 0
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
async search() {
|
||||
if (!this.query.trim()) {
|
||||
@@ -374,72 +431,14 @@
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
// Extract unique filters from results themselves
|
||||
const filterCounts = { type: {}, category: {}, difficulty: {} };
|
||||
|
||||
this.results.forEach(result => {
|
||||
if (result.filters) {
|
||||
// Count type filters
|
||||
if (result.filters.type) {
|
||||
result.filters.type.forEach(val => {
|
||||
filterCounts.type[val] = (filterCounts.type[val] || 0) + 1;
|
||||
});
|
||||
}
|
||||
// Count category filters
|
||||
if (result.filters.category) {
|
||||
result.filters.category.forEach(val => {
|
||||
filterCounts.category[val] = (filterCounts.category[val] || 0) + 1;
|
||||
});
|
||||
}
|
||||
// Count difficulty filters
|
||||
if (result.filters.difficulty) {
|
||||
result.filters.difficulty.forEach(val => {
|
||||
filterCounts.difficulty[val] = (filterCounts.difficulty[val] || 0) + 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Extracted filter counts from results:', filterCounts);
|
||||
|
||||
// Build filter list
|
||||
const filters = [];
|
||||
|
||||
// Add type filters with i18n labels
|
||||
Object.entries(filterCounts.type).forEach(([value, count]) => {
|
||||
filters.push({
|
||||
category: 'type',
|
||||
value,
|
||||
label: this.typeLabels[value] || value.charAt(0).toUpperCase() + value.slice(1),
|
||||
count,
|
||||
filterKey: `type:${value}`
|
||||
});
|
||||
});
|
||||
|
||||
// Add category filters
|
||||
Object.entries(filterCounts.category).forEach(([value, count]) => {
|
||||
filters.push({
|
||||
category: 'category',
|
||||
value,
|
||||
label: value,
|
||||
count,
|
||||
filterKey: `category:${value}`
|
||||
});
|
||||
});
|
||||
|
||||
// Add difficulty filters
|
||||
Object.entries(filterCounts.difficulty).forEach(([value, count]) => {
|
||||
filters.push({
|
||||
category: 'difficulty',
|
||||
value,
|
||||
label: value,
|
||||
count,
|
||||
filterKey: `difficulty:${value}`
|
||||
});
|
||||
});
|
||||
|
||||
this.availableFilters = filters;
|
||||
|
||||
const filterCounts = search.totalFilters || search.filters || {};
|
||||
|
||||
if (this.allFilters.length) {
|
||||
this.availableFilters = this.mergeFilterCounts(filterCounts);
|
||||
} else {
|
||||
this.availableFilters = this.buildFilters(filterCounts);
|
||||
}
|
||||
console.log('Final availableFilters array:', this.availableFilters);
|
||||
|
||||
// Set first result as selected for keyboard navigation
|
||||
@@ -456,52 +455,13 @@
|
||||
},
|
||||
|
||||
async loadFilters() {
|
||||
// Pre-load available filters by doing an empty search
|
||||
// Pre-load available filters from the full Pagefind index
|
||||
try {
|
||||
const search = await this.pagefind.search('');
|
||||
console.log('Available Pagefind filters:', search.filters);
|
||||
|
||||
const filters = [];
|
||||
|
||||
// Load type filters (questions, faq, docs)
|
||||
if (search.filters && search.filters.type) {
|
||||
Object.entries(search.filters.type).forEach(([value, count]) => {
|
||||
filters.push({
|
||||
category: 'type',
|
||||
value,
|
||||
label: value.charAt(0).toUpperCase() + value.slice(1),
|
||||
count,
|
||||
filterKey: `type:${value}`
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Load category filters
|
||||
if (search.filters && search.filters.category) {
|
||||
Object.entries(search.filters.category).forEach(([value, count]) => {
|
||||
filters.push({
|
||||
category: 'category',
|
||||
value,
|
||||
label: value,
|
||||
count,
|
||||
filterKey: `category:${value}`
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Load difficulty filters (for questions)
|
||||
if (search.filters && search.filters.difficulty) {
|
||||
Object.entries(search.filters.difficulty).forEach(([value, count]) => {
|
||||
filters.push({
|
||||
category: 'difficulty',
|
||||
value,
|
||||
label: value,
|
||||
count,
|
||||
filterKey: `difficulty:${value}`
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const filterIndex = await this.pagefind.filters();
|
||||
console.log('Available Pagefind filters:', filterIndex);
|
||||
|
||||
const filters = this.buildFilters(filterIndex);
|
||||
this.allFilters = filters;
|
||||
this.availableFilters = filters;
|
||||
console.log('Processed filters:', this.availableFilters);
|
||||
} catch (error) {
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
{{ end }}
|
||||
|
||||
{{/* Pagefind metadata for search filtering */}}
|
||||
<div class="content" data-pagefind-body data-pagefind-meta="title:{{ .Title }}">
|
||||
<h1>{{ .Title }}</h1>
|
||||
<div class="content" data-pagefind-body>
|
||||
<h1 data-pagefind-meta="title">{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
|
||||
{{/* Use hidden spans for filter values - best practice per Pagefind docs */}}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
<h1 class="{{ if $has_overlap_icon }}mt-12{{ else }}mt-2{{ end }} text-4xl font-bold tracking-tight text-slate-900 dark:text-slate-100">
|
||||
<h1 class="{{ if $has_overlap_icon }}mt-12{{ else }}mt-2{{ end }} text-4xl font-bold tracking-tight text-slate-900 dark:text-slate-100" data-pagefind-meta="title" data-pagefind-body>
|
||||
{{/* Inline icon before title if specified */}}
|
||||
{{ if $cover }}
|
||||
{{ $icon_config := .Params.cover.icon | default (dict) }}
|
||||
@@ -375,7 +375,13 @@
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="prose prose-slate lg:prose-xl dark:prose-invert">
|
||||
<div class="prose prose-slate lg:prose-xl dark:prose-invert" data-pagefind-body>
|
||||
{{ with .Section }}
|
||||
<span data-pagefind-filter="type" style="display:none;">{{ . }}</span>
|
||||
{{ end }}
|
||||
{{ with .Params.categories }}
|
||||
<span data-pagefind-filter="category" style="display:none;">{{ index . 0 }}</span>
|
||||
{{ end }}
|
||||
{{ .Content }}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{{ .Page.Store.Set "has_alpine" true }}
|
||||
|
||||
{{/* Pagefind metadata for search filtering */}}
|
||||
<div data-pagefind-body data-pagefind-meta="title:{{ .Title }}">
|
||||
<div data-pagefind-body>
|
||||
{{/* Use hidden spans for filter values - best practice per Pagefind docs */}}
|
||||
<span data-pagefind-filter="type" style="display:none;">faq</span>
|
||||
{{ with .Params.categories }}
|
||||
@@ -23,7 +23,7 @@
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<h1>{{ .Title }}</h1>
|
||||
<h1 data-pagefind-meta="title">{{ .Title }}</h1>
|
||||
|
||||
{{ with .Content }}
|
||||
<div class="lead mb-8">
|
||||
@@ -138,4 +138,4 @@
|
||||
|
||||
</div>{{/* End Pagefind metadata wrapper */}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -1,8 +1,7 @@
|
||||
{{- define "main" -}}
|
||||
|
||||
{{/* Pagefind metadata for search filtering */}}
|
||||
<div data-pagefind-body
|
||||
{{ with .Params.question }}data-pagefind-meta="title:{{ . }}"{{ end }}>
|
||||
<div data-pagefind-body>
|
||||
{{/* Use hidden spans for filter values - best practice per Pagefind docs */}}
|
||||
<span data-pagefind-filter="type" style="display:none;">questions</span>
|
||||
{{ with .Params.categories }}
|
||||
@@ -26,7 +25,7 @@
|
||||
|
||||
{{/* Question as title */}}
|
||||
<div class="qa-question mb-6">
|
||||
<h1 class="text-4xl font-bold text-slate-900 dark:text-slate-100 mb-4">
|
||||
<h1 class="text-4xl font-bold text-slate-900 dark:text-slate-100 mb-4" data-pagefind-meta="title">
|
||||
{{ .Params.question | default .Title }}
|
||||
</h1>
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
<h1 class="{{ if $has_overlap_icon }}mt-12{{ else }}mt-2{{ end }} text-4xl font-bold tracking-tight text-slate-900 dark:text-slate-100">
|
||||
<h1 class="{{ if $has_overlap_icon }}mt-12{{ else }}mt-2{{ end }} text-4xl font-bold tracking-tight text-slate-900 dark:text-slate-100" data-pagefind-meta="title" data-pagefind-body>
|
||||
{{/* Inline icon before title if specified */}}
|
||||
{{ if $cover }}
|
||||
{{ $icon_config := .Params.cover.icon | default (dict) }}
|
||||
@@ -201,6 +201,7 @@
|
||||
<img srcset="{{ $responsive.srcset }}"
|
||||
sizes="{{ $sizes_attr }}"
|
||||
src="{{ $responsive.fallback.RelPermalink }}"
|
||||
data-pagefind-meta="image[src]"
|
||||
width="{{ $fitted_image.Width }}"
|
||||
height="{{ $fitted_image.Height }}"
|
||||
alt="{{ with $image_params.alt_text }}{{.}}{{ end }}"
|
||||
@@ -222,6 +223,7 @@
|
||||
<div class="article-header {{$image_container}} featured-image-wrapper mt-4 mb-16" style="max-width: {{$image.Width}}px; max-height: {{$image.Height}}px;">
|
||||
<div style="position: relative">
|
||||
<img src="{{ $image.RelPermalink }}"
|
||||
data-pagefind-meta="image[src]"
|
||||
width="{{ $image.Width }}"
|
||||
height="{{ $image.Height }}"
|
||||
alt="{{ with $image_params.alt_text }}{{.}}{{ end }}"
|
||||
@@ -288,7 +290,13 @@
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="prose prose-slate lg:prose-xl dark:prose-invert">
|
||||
<div class="prose prose-slate lg:prose-xl dark:prose-invert" data-pagefind-body>
|
||||
{{ with .Section }}
|
||||
<span data-pagefind-filter="type" style="display:none;">{{ . }}</span>
|
||||
{{ end }}
|
||||
{{ with .Params.categories }}
|
||||
<span data-pagefind-filter="category" style="display:none;">{{ index . 0 }}</span>
|
||||
{{ end }}
|
||||
{{ .Content }}
|
||||
</div>
|
||||
|
||||
|
||||
Reference in new issue
Block a user