From 1b47e08129fdea7ead439e79840c7e8803ee21e8 Mon Sep 17 00:00:00 2001 From: marco370 <48531002-marco370@users.noreply.replit.com> Date: Fri, 2 Jan 2026 15:37:32 +0000 Subject: [PATCH] Add search functionality to the whitelist page and improve IP status indication Add a search bar to the whitelist page and filter results by IP, reason, and notes. Modify the detections page to visually indicate when an IP is already whitelisted by changing the button color to green and using a different icon. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 4231475f-0a12-42cd-bf3f-3401022fd4e5 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/8i4FqXF --- client/src/pages/Detections.tsx | 47 ++++++++++++++++++++++++--------- client/src/pages/Whitelist.tsx | 32 +++++++++++++++++++--- 2 files changed, 62 insertions(+), 17 deletions(-) diff --git a/client/src/pages/Detections.tsx b/client/src/pages/Detections.tsx index 0df1c32..a6ab5a4 100644 --- a/client/src/pages/Detections.tsx +++ b/client/src/pages/Detections.tsx @@ -5,10 +5,10 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Slider } from "@/components/ui/slider"; -import { AlertTriangle, Search, Shield, Globe, MapPin, Building2, ShieldPlus } from "lucide-react"; +import { AlertTriangle, Search, Shield, Globe, MapPin, Building2, ShieldPlus, ShieldCheck } from "lucide-react"; import { format } from "date-fns"; import { useState } from "react"; -import type { Detection } from "@shared/schema"; +import type { Detection, Whitelist } from "@shared/schema"; import { getFlag } from "@/lib/country-flags"; import { apiRequest, queryClient } from "@/lib/queryClient"; import { useToast } from "@/hooks/use-toast"; @@ -39,6 +39,14 @@ export default function Detections() { refetchInterval: 5000, }); + // Fetch whitelist to check if IP is already whitelisted + const { data: whitelistData } = useQuery({ + queryKey: ["/api/whitelist"], + }); + + // Create a Set of whitelisted IPs for fast lookup + const whitelistedIps = new Set(whitelistData?.map(w => w.ipAddress) || []); + const filteredDetections = detections?.filter((d) => d.sourceIp.toLowerCase().includes(searchQuery.toLowerCase()) || d.anomalyType.toLowerCase().includes(searchQuery.toLowerCase()) @@ -278,17 +286,30 @@ export default function Detections() { )} - + {whitelistedIps.has(detection.sourceIp) ? ( + + ) : ( + + )} diff --git a/client/src/pages/Whitelist.tsx b/client/src/pages/Whitelist.tsx index b28f1a9..e889a57 100644 --- a/client/src/pages/Whitelist.tsx +++ b/client/src/pages/Whitelist.tsx @@ -2,7 +2,7 @@ import { useQuery, useMutation } from "@tanstack/react-query"; import { queryClient, apiRequest } from "@/lib/queryClient"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; -import { Shield, Plus, Trash2, CheckCircle2, XCircle } from "lucide-react"; +import { Shield, Plus, Trash2, CheckCircle2, XCircle, Search } from "lucide-react"; import { format } from "date-fns"; import { useState } from "react"; import { useForm } from "react-hook-form"; @@ -44,6 +44,7 @@ const whitelistFormSchema = insertWhitelistSchema.extend({ export default function WhitelistPage() { const { toast } = useToast(); const [isAddDialogOpen, setIsAddDialogOpen] = useState(false); + const [searchQuery, setSearchQuery] = useState(""); const form = useForm>({ resolver: zodResolver(whitelistFormSchema), @@ -59,6 +60,13 @@ export default function WhitelistPage() { queryKey: ["/api/whitelist"], }); + // Filter whitelist based on search query + const filteredWhitelist = whitelist?.filter((item) => + item.ipAddress.toLowerCase().includes(searchQuery.toLowerCase()) || + item.reason?.toLowerCase().includes(searchQuery.toLowerCase()) || + item.comment?.toLowerCase().includes(searchQuery.toLowerCase()) + ); + const addMutation = useMutation({ mutationFn: async (data: z.infer) => { return await apiRequest("POST", "/api/whitelist", data); @@ -189,11 +197,27 @@ export default function WhitelistPage() { + {/* Search Bar */} + + +
+ + setSearchQuery(e.target.value)} + className="pl-9" + data-testid="input-search-whitelist" + /> +
+
+
+ - IP Protetti ({whitelist?.length || 0}) + IP Protetti ({filteredWhitelist?.length || 0}{searchQuery && whitelist ? ` di ${whitelist.length}` : ''}) @@ -201,9 +225,9 @@ export default function WhitelistPage() {
Caricamento...
- ) : whitelist && whitelist.length > 0 ? ( + ) : filteredWhitelist && filteredWhitelist.length > 0 ? (
- {whitelist.map((item) => ( + {filteredWhitelist.map((item) => (