From 9ec6b4763c8dfd73a7f88edb7464621d527bea36 Mon Sep 17 00:00:00 2001 From: Jonathan Atta Date: Wed, 11 Mar 2026 17:28:42 +0100 Subject: [PATCH] feat: add search functionality for processes and improve pagination controls --- frontend/src/App.tsx | 66 ++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4ee6180..da53314 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState, useCallback, useRef } from 'react' import { EventsOn, EventsOff } from '../wailsjs/runtime/runtime' -import { Activity, Cpu, Database, Monitor, ChevronDown, ChevronRight, Layers, X, RefreshCw, OctagonX } from 'lucide-react' +import { Activity, Cpu, Database, Monitor, ChevronDown, ChevronRight, Layers, X, RefreshCw, OctagonX, Search } from 'lucide-react' import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card' import { Progress } from '@/components/ui/progress' import { cn } from '@/lib/utils' @@ -525,6 +525,7 @@ export default function App() { const [gpuOpen, setGpuOpen] = useState(true) const [gpuSortBy, setGpuSortBy] = useState<'vram' | 'ram'>('vram') const [navStack, setNavStack] = useState([]) + const [search, setSearch] = useState('') const openDetail = useCallback((pid: number) => { setSelectedPid(pid) @@ -554,15 +555,18 @@ export default function App() { : 0 const gpuUtilPct = metrics?.gpu_util_percent ?? 0 - const gpuProcesses = [...(metrics?.gpu_processes ?? [])].sort((a, b) => - gpuSortBy === 'vram' ? b.vram_mb - a.vram_mb : b.ram - a.ram - ) + const searchLower = search.toLowerCase() + const gpuProcesses = [...(metrics?.gpu_processes ?? [])] + .filter(p => !search || p.name.toLowerCase().includes(searchLower) || String(p.pid).includes(search)) + .sort((a, b) => gpuSortBy === 'vram' ? b.vram_mb - a.vram_mb : b.ram - a.ram) const gpuTotalPages = Math.ceil(gpuProcesses.length / gpuPageSize) const safeGpuPage = Math.min(gpuPage, Math.max(0, gpuTotalPages - 1)) const pagedGpuProcesses = gpuProcesses.slice(safeGpuPage * gpuPageSize, (safeGpuPage + 1) * gpuPageSize) const sortedProcesses = metrics - ? [...metrics.processes].sort((a, b) => b[sortBy] - a[sortBy]) + ? [...metrics.processes] + .filter(p => !search || p.name.toLowerCase().includes(searchLower) || String(p.pid).includes(search)) + .sort((a, b) => b[sortBy] - a[sortBy]) : [] const totalPages = Math.ceil(sortedProcesses.length / pageSize) const safePage = Math.min(page, Math.max(0, totalPages - 1)) @@ -590,6 +594,26 @@ export default function App() {
+ {/* Search */} +
+ + { setSearch(e.target.value); setPage(0); setGpuPage(0) }} + className="w-full bg-zinc-900/60 border border-zinc-800 rounded-lg pl-8 pr-8 py-2 text-sm text-zinc-300 placeholder-zinc-700 focus:outline-none focus:border-zinc-600 transition-colors" + /> + {search && ( + + )} +
+ {/* Processes */} {safePage * pageSize + 1}–{Math.min((safePage + 1) * pageSize, sortedProcesses.length)} of {sortedProcesses.length} - +
+ {[10, 20, 50, 100].map(n => ( + + ))} +
+ ))} +