From a49dd83c5ce03c0b461f07591d5d6a0c69c456ca Mon Sep 17 00:00:00 2001 From: Dorian Date: Thu, 5 Mar 2026 08:06:07 +0000 Subject: [PATCH] feat: add local search filter to My Apps view Adds a search input to the Apps page that filters installed apps by title, description, or app ID. Styled consistently with the Marketplace search bar. Co-Authored-By: Claude Opus 4.6 --- .claude/plans/reflective-meandering-castle.md | 2 +- neode-ui/src/views/Apps.vue | 30 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.claude/plans/reflective-meandering-castle.md b/.claude/plans/reflective-meandering-castle.md index 24e65b80..f078efd8 100644 --- a/.claude/plans/reflective-meandering-castle.md +++ b/.claude/plans/reflective-meandering-castle.md @@ -79,7 +79,7 @@ After getting Claude Max OAuth working on the live server, hardening the deploy - **Change**: Compare `get_app_config()` port mappings with nginx proxies. Add missing nginx proxies for: Grafana (3000), Jellyfin (8096), Uptime Kuma (3001), Portainer (9000), OnlyOffice (9980). Add to both HTTP and HTTPS blocks. Verify `extract_lan_address()` correctness. - **Verify**: Each app launches correctly from Apps page -### Task 14: Local search within Apps view +### Task 14: Local search within Apps view [DONE] - **Files**: `neode-ui/src/views/Apps.vue` - **Change**: Add search input with `ref('')`. Filter `sortedPackageEntries` by query against `manifest.title` and `manifest.description.short`. Style like Marketplace search. - **Verify**: Type in search — only matching apps shown diff --git a/neode-ui/src/views/Apps.vue b/neode-ui/src/views/Apps.vue index 3032e236..3caada3c 100644 --- a/neode-ui/src/views/Apps.vue +++ b/neode-ui/src/views/Apps.vue @@ -5,6 +5,16 @@

Manage your installed applications

+ +
+ +
+
@@ -22,10 +32,15 @@
+ +
+

No apps matching "{{ searchQuery }}"

+
+
>({}) @@ -199,6 +217,16 @@ const sortedPackageEntries = computed(() => { ) }) +const filteredPackageEntries = computed(() => { + if (!searchQuery.value) return sortedPackageEntries.value + const q = searchQuery.value.toLowerCase() + return sortedPackageEntries.value.filter(([id, pkg]) => + (pkg.manifest?.title ?? '').toLowerCase().includes(q) || + (pkg.manifest?.description?.short ?? '').toLowerCase().includes(q) || + id.toLowerCase().includes(q) + ) +}) + const uninstallModal = ref({ show: false, appId: '',