updated
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
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();
|
||||
@@ -32,13 +36,63 @@ function App() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 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 (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<h1>Docker Service Display</h1>
|
||||
<div className="flex space-x-2 w-fit">
|
||||
<SearchBox searchTerm={searchTerm} onSearchChange={setSearchTerm} />
|
||||
<FilterBox
|
||||
availableLabels={allLabels}
|
||||
selectedLabels={selectedLabels}
|
||||
onLabelToggle={handleLabelToggle}
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<main className="service-grid">
|
||||
{services.map(service => (
|
||||
{filteredServices.map(service => (
|
||||
<ServiceCard key={service.id} service={service} />
|
||||
))}
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user