From f26f72642b1e61d072aa47024e2dee4205ee67cb Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Fri, 10 Apr 2026 12:32:52 +0200 Subject: [PATCH] added search to OpsEvents --- .../app/admin/components/OpsEventsSection.tsx | 66 +++++++++++++++---- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/src/Web/autopilot-monitor-web/app/admin/components/OpsEventsSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/OpsEventsSection.tsx index 581699c3..775d02c3 100644 --- a/src/Web/autopilot-monitor-web/app/admin/components/OpsEventsSection.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/components/OpsEventsSection.tsx @@ -101,6 +101,7 @@ export function OpsEventsSection({ const [loading, setLoading] = useState(false); const [selectedEvent, setSelectedEvent] = useState(null); const [categoryFilter, setCategoryFilter] = useState(""); + const [searchQuery, setSearchQuery] = useState(""); const [currentPage, setCurrentPage] = useState(0); const pageSize = 15; @@ -134,13 +135,29 @@ export function OpsEventsSection({ } }; + // Search filter (client-side across key fields) + const filteredEvents = searchQuery.trim() + ? events.filter((e) => { + const q = searchQuery.toLowerCase(); + return ( + e.eventType.toLowerCase().includes(q) || + e.message.toLowerCase().includes(q) || + (e.details?.toLowerCase().includes(q) ?? false) || + (e.tenantId?.toLowerCase().includes(q) ?? false) || + (e.userId?.toLowerCase().includes(q) ?? false) || + e.severity.toLowerCase().includes(q) || + e.category.toLowerCase().includes(q) + ); + }) + : events; + // Summary stats - const categoryCounts = events.reduce>((acc, e) => { + const categoryCounts = filteredEvents.reduce>((acc, e) => { acc[e.category] = (acc[e.category] ?? 0) + 1; return acc; }, {}); - const severityCounts = events.reduce>((acc, e) => { + const severityCounts = filteredEvents.reduce>((acc, e) => { acc[e.severity] = (acc[e.severity] ?? 0) + 1; return acc; }, {}); @@ -185,11 +202,11 @@ export function OpsEventsSection({ {/* Summary Cards */} - {!loading && events.length > 0 && ( + {!loading && filteredEvents.length > 0 && (
-
{events.length}
+
{filteredEvents.length}
Total Events
0 ? 'border-red-300 dark:border-red-600' : 'border-gray-200 dark:border-gray-600'}`}> @@ -239,8 +256,31 @@ export function OpsEventsSection({
- {/* Category Filter */} + {/* Search & Category Filter */}
+
+ + + + { setSearchQuery(e.target.value); setCurrentPage(0); }} + className="w-52 pl-8 pr-7 py-1 text-xs border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-2 focus:ring-slate-500 focus:border-slate-500" + /> + {searchQuery && ( + + )} +
+
Filter:
- ) : events.length === 0 ? ( + ) : filteredEvents.length === 0 ? (
-

No operational events recorded yet.

+

+ {searchQuery ? `No events matching "${searchQuery}".` : "No operational events recorded yet."} +

) : (
@@ -295,7 +337,7 @@ export function OpsEventsSection({ - {events.slice(currentPage * pageSize, (currentPage + 1) * pageSize).map((evt, idx) => { + {filteredEvents.slice(currentPage * pageSize, (currentPage + 1) * pageSize).map((evt, idx) => { const rowStyle = SEVERITY_STYLES[evt.severity]?.row ?? ""; return ( {/* Pagination */} - {events.length > pageSize && ( + {filteredEvents.length > pageSize && (
- {currentPage * pageSize + 1}–{Math.min((currentPage + 1) * pageSize, events.length)} of {events.length} + {currentPage * pageSize + 1}–{Math.min((currentPage + 1) * pageSize, filteredEvents.length)} of {filteredEvents.length}{searchQuery && ` (filtered)`}