import React, { useState, useEffect, useMemo } from 'react'; import './App.css'; import { getServices } from './api'; import ServiceCard from './components/ServiceCard'; import SearchBox from './components/SearchBox'; // Import SearchBox import FilterBox from './components/FilterBox'; // Import FilterBox function App() { const [services, setServices] = useState([]); const [searchTerm, setSearchTerm] = useState(''); // Add state for search term const [selectedLabels, setSelectedLabels] = useState([]); async function fetchServices() { const fetchedServices = await getServices(); setServices(fetchedServices); } useEffect(() => { fetchServices(); const ws = new WebSocket('ws://localhost:3001/api/events'); ws.onmessage = (event) => { const message = JSON.parse(event.data); if (message.type === 'container' && (message.action === 'start' || message.action === 'stop')) { fetchServices(); } }; ws.onclose = () => { // Optional: handle reconnection logic here }; return () => { ws.close(); }; }, []); // Extract unique labels const allLabels = useMemo(() => { const labels = new Set(); services.forEach(service => { for (const key in service.labels) { labels.add(`${key}:${service.labels[key]}`); } }); return Array.from(labels).sort(); }, [services]); // Handler for toggling labels const handleLabelToggle = (labelToToggle) => { setSelectedLabels(prevSelectedLabels => { if (prevSelectedLabels.includes(labelToToggle)) { return prevSelectedLabels.filter(label => label !== labelToToggle); } else { return [...prevSelectedLabels, labelToToggle]; } }); }; // Filtering logic const filteredServices = services.filter(service => { const matchesSearchTerm = service.name.toLowerCase().includes(searchTerm.toLowerCase()); let matchesFilterTerm = true; // Update filtering logic to use selectedLabels if (selectedLabels.length > 0) { matchesFilterTerm = selectedLabels.every(selectedLabel => { const [key, value] = selectedLabel.split(':'); if (value) { // key:value format return service.labels[key] === value; } else { // key only format (e.g., "has:env" was replaced by just "env") return Object.keys(service.labels).includes(key); } }); } return matchesSearchTerm && matchesFilterTerm; }); return (

Docker Service Display

{filteredServices.map(service => ( ))}
); } export default App;