feat: enhance search functionality in Proxmox help view by adding keyword matching and auto-expanding categories for improved navigation

This commit is contained in:
2025-12-01 11:16:17 -05:00
parent 913b59d466
commit a5acc4bdfb

View File

@@ -8,9 +8,46 @@
'reference': false
},
searchQuery: '',
matchesQuery(label) {
matchesQuery(label, keywords = '') {
if (!this.searchQuery) return true;
return label.toLowerCase().includes(this.searchQuery.toLowerCase());
const query = this.searchQuery.toLowerCase();
const labelLower = label.toLowerCase();
const keywordsLower = keywords.toLowerCase();
return labelLower.includes(query) || keywordsLower.includes(query);
},
sectionMatchesContent(sectionId) {
if (!this.searchQuery) return true;
const query = this.searchQuery.toLowerCase();
const sectionElement = document.querySelector(`[data-section-id='${sectionId}']`);
if (!sectionElement) return false;
const textContent = sectionElement.textContent.toLowerCase();
return textContent.includes(query);
},
shouldShowSection(sectionId, label, keywords = '') {
if (!this.searchQuery) return true;
return this.matchesQuery(label, keywords) || this.sectionMatchesContent(sectionId);
},
init() {
this.$watch('searchQuery', (value) => {
if (value) {
// Auto-expand categories when searching
Object.keys(this.expandedCategories).forEach(key => {
this.expandedCategories[key] = true;
});
// Auto-switch to first matching section
const sections = ['overview', 'quick-start', 'boot-settings', 'network', 'subdomain', 'cloud-init', 'display', 'statistics', 'system', 'backups', 'console', 'bgp', 'glossary', 'rfc-standards', 'troubleshooting'];
for (const section of sections) {
const sectionElement = document.querySelector(`[data-section-id='${section}']`);
if (sectionElement) {
const textContent = sectionElement.textContent.toLowerCase();
if (textContent.includes(value.toLowerCase())) {
this.activeSection = section;
break;
}
}
}
}
});
}
}">
<!-- Sidebar Navigation -->
@@ -49,14 +86,14 @@
</button>
<div x-show="expandedCategories['getting-started']" x-transition class="ml-4 mt-1 space-y-1">
<button @click="activeSection = 'overview'"
x-show="matchesQuery('overview getting started basics')"
x-show="shouldShowSection('overview', 'overview getting started basics', 'overview getting started basics dashboard')"
:class="activeSection === 'overview' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-dashboard-line class="size-4" />
<span>Overview</span>
</button>
<button @click="activeSection = 'quick-start'"
x-show="matchesQuery('quick start guide first time setup')"
x-show="shouldShowSection('quick-start', 'quick start guide first time setup', 'quick start guide first time setup')"
:class="activeSection === 'quick-start' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-rocket-line class="size-4" />
@@ -79,42 +116,42 @@
</button>
<div x-show="expandedCategories['configuration']" x-transition class="ml-4 mt-1 space-y-1">
<button @click="activeSection = 'boot-settings'"
x-show="matchesQuery('boot settings order firmware efi bios')"
x-show="shouldShowSection('boot-settings', 'boot settings order firmware efi bios', 'boot settings order firmware efi bios')"
:class="activeSection === 'boot-settings' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-restart-line class="size-4" />
<span>Boot Settings</span>
</button>
<button @click="activeSection = 'network'"
x-show="matchesQuery('network ip address mtu gateway routes firewall')"
x-show="shouldShowSection('network', 'network ip address mtu gateway routes firewall', 'network ip address mtu gateway routes firewall')"
:class="activeSection === 'network' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-wifi-line class="size-4" />
<span>Network</span>
</button>
<button @click="activeSection = 'subdomain'"
x-show="matchesQuery('subdomain dns records a aaaa hostnames')"
x-show="shouldShowSection('subdomain', 'subdomain dns records a aaaa hostnames', 'subdomain dns records a aaaa hostnames')"
:class="activeSection === 'subdomain' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-global-line class="size-4" />
<span>Subdomain</span>
</button>
<button @click="activeSection = 'cloud-init'"
x-show="matchesQuery('cloud-init user data metadata ssh keys')"
x-show="shouldShowSection('cloud-init', 'cloud-init user data metadata ssh keys', 'cloud-init user data metadata ssh keys')"
:class="activeSection === 'cloud-init' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-cloud-line class="size-4" />
<span>Cloud-init</span>
</button>
<button @click="activeSection = 'display'"
x-show="matchesQuery('display console resolution vnc xterm')"
x-show="shouldShowSection('display', 'display console resolution vnc xterm', 'display console resolution vnc xterm')"
:class="activeSection === 'display' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-computer-line class="size-4" />
<span>Display</span>
</button>
<button @click="activeSection = 'statistics'"
x-show="matchesQuery('statistics graphs telemetry cpu memory disk network analysis')"
x-show="shouldShowSection('statistics', 'statistics graphs telemetry cpu memory disk network analysis', 'statistics graphs telemetry cpu memory disk network analysis')"
:class="activeSection === 'statistics' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-bar-chart-line class="size-4" />
@@ -137,28 +174,28 @@
</button>
<div x-show="expandedCategories['advanced']" x-transition class="ml-4 mt-1 space-y-1">
<button @click="activeSection = 'system'"
x-show="matchesQuery('system advanced cpu memory disk tpm efi')"
x-show="shouldShowSection('system', 'system advanced cpu memory disk tpm efi', 'system advanced cpu memory disk tpm efi')"
:class="activeSection === 'system' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-cpu-line class="size-4" />
<span>System</span>
</button>
<button @click="activeSection = 'backups'"
x-show="matchesQuery('backups snapshots restore schedule retention')"
x-show="shouldShowSection('backups', 'backups snapshots restore schedule retention', 'backups snapshots restore schedule retention')"
:class="activeSection === 'backups' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-database-line class="size-4" />
<span>Backups</span>
</button>
<button @click="activeSection = 'console'"
x-show="matchesQuery('console access vnc xterm ssh serial')"
x-show="shouldShowSection('console', 'console access vnc xterm ssh serial', 'console access vnc xterm ssh serial')"
:class="activeSection === 'console' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-terminal-box-line class="size-4" />
<span>Console Access</span>
</button>
<button @click="activeSection = 'bgp'"
x-show="matchesQuery('bgp routing core router network analysis')"
x-show="shouldShowSection('bgp', 'bgp routing core router network analysis', 'bgp routing core router network analysis')"
:class="activeSection === 'bgp' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-router-line class="size-4" />
@@ -181,21 +218,21 @@
</button>
<div x-show="expandedCategories['reference']" x-transition class="ml-4 mt-1 space-y-1">
<button @click="activeSection = 'glossary'"
x-show="matchesQuery('glossary terminology definitions acronyms')"
x-show="shouldShowSection('glossary', 'glossary terminology definitions acronyms', 'glossary terminology definitions acronyms')"
:class="activeSection === 'glossary' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-book-2-line class="size-4" />
<span>Glossary</span>
</button>
<button @click="activeSection = 'rfc-standards'"
x-show="matchesQuery('rfc standards protocols ipv4 ipv6 dns ssh http')"
x-show="shouldShowSection('rfc-standards', 'rfc standards protocols ipv4 ipv6 dns ssh http', 'rfc standards protocols ipv4 ipv6 dns ssh http')"
:class="activeSection === 'rfc-standards' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-file-paper-line class="size-4" />
<span>RFC Standards</span>
</button>
<button @click="activeSection = 'troubleshooting'"
x-show="matchesQuery('troubleshooting errors issues network connectivity boot problems')"
x-show="shouldShowSection('troubleshooting', 'troubleshooting errors issues network connectivity boot problems', 'troubleshooting errors issues network connectivity boot problems')"
:class="activeSection === 'troubleshooting' ? 'bg-background text-base font-semibold' : 'text-base/70 hover:text-base'"
class="w-full text-left px-3 py-2 rounded-md transition-colors flex items-center gap-2">
<x-ri-tools-line class="size-4" />
@@ -211,7 +248,7 @@
<div class="lg:col-span-3">
<div class="bg-background-secondary border border-neutral rounded-lg p-6 space-y-6">
<!-- Quick Start Guide -->
<div x-show="activeSection === 'quick-start'" x-transition style="display: none;">
<div x-show="activeSection === 'quick-start'" x-transition style="display: none;" data-section-id="quick-start">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-rocket-line class="size-5 text-primary" />
@@ -280,7 +317,7 @@
</div>
<!-- Overview Section -->
<div x-show="activeSection === 'overview'" x-transition>
<div x-show="activeSection === 'overview'" x-transition data-section-id="overview">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-dashboard-line class="size-5 text-primary" />
@@ -806,7 +843,7 @@ preserve_hostname: false</code></pre>
</div>
<!-- Boot Settings Section - Expanded -->
<div x-show="activeSection === 'boot-settings'" x-transition style="display: none;">
<div x-show="activeSection === 'boot-settings'" x-transition style="display: none;" data-section-id="boot-settings">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-restart-line class="size-5 text-primary" />
@@ -1052,7 +1089,7 @@ preserve_hostname: false</code></pre>
<!-- I'll continue with a few more key sections to show the pattern, then you can see the full implementation -->
<!-- Network Section with Tables -->
<div x-show="activeSection === 'network'" x-transition style="display: none;">
<div x-show="activeSection === 'network'" x-transition style="display: none;" data-section-id="network">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-wifi-line class="size-5 text-primary" />
@@ -1344,7 +1381,7 @@ iface vmbr0 inet static
</div>
<!-- RFC Standards Section -->
<div x-show="activeSection === 'rfc-standards'" x-transition style="display: none;">
<div x-show="activeSection === 'rfc-standards'" x-transition style="display: none;" data-section-id="rfc-standards">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-file-paper-line class="size-5 text-primary" />
@@ -1443,7 +1480,7 @@ iface vmbr0 inet static
</div>
<!-- Troubleshooting Section -->
<div x-show="activeSection === 'troubleshooting'" x-transition style="display: none;">
<div x-show="activeSection === 'troubleshooting'" x-transition style="display: none;" data-section-id="troubleshooting">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-tools-line class="size-5 text-primary" />
@@ -1494,7 +1531,7 @@ iface vmbr0 inet static
</div>
<!-- Subdomain Section -->
<div x-show="activeSection === 'subdomain'" x-transition style="display: none;">
<div x-show="activeSection === 'subdomain'" x-transition style="display: none;" data-section-id="subdomain">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-global-line class="size-5 text-primary" />
@@ -1642,7 +1679,7 @@ Answer Section
</div>
<!-- Cloud-init Section -->
<div x-show="activeSection === 'cloud-init'" x-transition style="display: none;">
<div x-show="activeSection === 'cloud-init'" x-transition style="display: none;" data-section-id="cloud-init">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-cloud-line class="size-5 text-primary" />
@@ -1811,7 +1848,7 @@ network:
</div>
<!-- Display Section -->
<div x-show="activeSection === 'display'" x-transition style="display: none;">
<div x-show="activeSection === 'display'" x-transition style="display: none;" data-section-id="display">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-computer-line class="size-5 text-primary" />
@@ -2363,7 +2400,7 @@ network:
</div>
<!-- Statistics Section -->
<div x-show="activeSection === 'statistics'" x-transition style="display: none;">
<div x-show="activeSection === 'statistics'" x-transition style="display: none;" data-section-id="statistics">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-bar-chart-line class="size-5 text-primary" />
@@ -2754,7 +2791,7 @@ ORDER BY DateTime DESC;</code></pre>
</div>
<!-- System Section -->
<div x-show="activeSection === 'system'" x-transition style="display: none;">
<div x-show="activeSection === 'system'" x-transition style="display: none;" data-section-id="system">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-cpu-line class="size-5 text-primary" />
@@ -3437,7 +3474,7 @@ POST /api2/json/cluster/ha/resources
</div>
<!-- Backups Section -->
<div x-show="activeSection === 'backups'" x-transition style="display: none;">
<div x-show="activeSection === 'backups'" x-transition style="display: none;" data-section-id="backups">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-database-line class="size-5 text-primary" />
@@ -3538,7 +3575,7 @@ GET /api2/json/config/backup
</div>
<!-- Console Section -->
<div x-show="activeSection === 'console'" x-transition style="display: none;">
<div x-show="activeSection === 'console'" x-transition style="display: none;" data-section-id="console">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-terminal-box-line class="size-5 text-primary" />
@@ -3651,7 +3688,7 @@ PVE:username@realm:timestamp:signature
</div>
<!-- BGP Routing Section -->
<div x-show="activeSection === 'bgp'" x-transition style="display: none;">
<div x-show="activeSection === 'bgp'" x-transition style="display: none;" data-section-id="bgp">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-router-line class="size-5 text-primary" />
@@ -4190,7 +4227,7 @@ filter strict_import {
</div>
<!-- Glossary Section - Expanded -->
<div x-show="activeSection === 'glossary'" x-transition style="display: none;">
<div x-show="activeSection === 'glossary'" x-transition style="display: none;" data-section-id="glossary">
<div class="flex items-center gap-3 mb-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
<x-ri-book-2-line class="size-5 text-primary" />