mirror of
https://github.com/tiennm99/HugoBlox-kit.git
synced 2026-10-11 03:12:56 +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>
|
||||
|
||||
|
||||
Generated
+64
@@ -14,6 +14,9 @@ importers:
|
||||
'@tailwindcss/typography':
|
||||
specifier: ^0.5.10
|
||||
version: 0.5.16(tailwindcss@4.1.12)
|
||||
pagefind:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
preact:
|
||||
specifier: ^10.27.2
|
||||
version: 10.27.2
|
||||
@@ -43,6 +46,36 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.30':
|
||||
resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
|
||||
|
||||
'@pagefind/darwin-arm64@1.4.0':
|
||||
resolution: {integrity: sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@pagefind/darwin-x64@1.4.0':
|
||||
resolution: {integrity: sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@pagefind/freebsd-x64@1.4.0':
|
||||
resolution: {integrity: sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@pagefind/linux-arm64@1.4.0':
|
||||
resolution: {integrity: sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@pagefind/linux-x64@1.4.0':
|
||||
resolution: {integrity: sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@pagefind/windows-x64@1.4.0':
|
||||
resolution: {integrity: sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
@@ -368,6 +401,10 @@ packages:
|
||||
node-addon-api@7.1.1:
|
||||
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||
|
||||
pagefind@1.4.0:
|
||||
resolution: {integrity: sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==}
|
||||
hasBin: true
|
||||
|
||||
picocolors@1.1.1:
|
||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||
|
||||
@@ -433,6 +470,24 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
||||
'@pagefind/darwin-arm64@1.4.0':
|
||||
optional: true
|
||||
|
||||
'@pagefind/darwin-x64@1.4.0':
|
||||
optional: true
|
||||
|
||||
'@pagefind/freebsd-x64@1.4.0':
|
||||
optional: true
|
||||
|
||||
'@pagefind/linux-arm64@1.4.0':
|
||||
optional: true
|
||||
|
||||
'@pagefind/linux-x64@1.4.0':
|
||||
optional: true
|
||||
|
||||
'@pagefind/windows-x64@1.4.0':
|
||||
optional: true
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
@@ -680,6 +735,15 @@ snapshots:
|
||||
|
||||
node-addon-api@7.1.1: {}
|
||||
|
||||
pagefind@1.4.0:
|
||||
optionalDependencies:
|
||||
'@pagefind/darwin-arm64': 1.4.0
|
||||
'@pagefind/darwin-x64': 1.4.0
|
||||
'@pagefind/freebsd-x64': 1.4.0
|
||||
'@pagefind/linux-arm64': 1.4.0
|
||||
'@pagefind/linux-x64': 1.4.0
|
||||
'@pagefind/windows-x64': 1.4.0
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
|
||||
picomatch@2.3.1: {}
|
||||
|
||||
Reference in new issue
Block a user