feat: improve k8s resource filtering UI

- Change namespace filter from text input to dropdown select
- Add name filtering input for all resource types
- Fix UI overlap issue with namespace dropdown label
- Add automatic namespace list loading
- Implement server-side name filtering for all resources
- Support combined namespace + name filtering

🤖 Generated with [Qoder][https://qoder.com]
This commit is contained in:
loveuer
2025-11-12 23:26:52 +08:00
parent 54ed79cea3
commit 7d2e2ab842
2 changed files with 134 additions and 10 deletions

View File

@@ -26,6 +26,8 @@ import {
DialogContent,
DialogActions,
Snackbar,
MenuItem,
Select,
} from '@mui/material'
import SettingsIcon from '@mui/icons-material/Settings'
import CloseIcon from '@mui/icons-material/Close'
@@ -56,6 +58,8 @@ export default function K8sResourceList() {
const [kubeconfig, setKubeconfig] = useState('')
const [kubeconfigError, setKubeconfigError] = useState(false)
const [namespace, setNamespace] = useState('')
const [namespaces, setNamespaces] = useState<string[]>([])
const [nameFilter, setNameFilter] = useState('')
const [createDialogOpen, setCreateDialogOpen] = useState(false)
const [yamlContent, setYamlContent] = useState('')
const [applyLoading, setApplyLoading] = useState(false)
@@ -80,8 +84,11 @@ export default function K8sResourceList() {
useEffect(() => {
if (kubeconfig) {
fetchResources()
if (selectedKind.key !== 'namespace' && selectedKind.key !== 'pv') {
fetchNamespaces()
}
}
}, [selectedKind, namespace])
}, [selectedKind, namespace, nameFilter])
const fetchKubeconfig = async () => {
try {
@@ -222,6 +229,9 @@ export default function K8sResourceList() {
if (namespace && selectedKind.key !== 'namespace' && selectedKind.key !== 'pv') {
url.searchParams.set('namespace', namespace)
}
if (nameFilter) {
url.searchParams.set('name', nameFilter)
}
const res = await fetch(url.toString())
if (!res.ok) throw new Error(`HTTP ${res.status}`)
@@ -234,6 +244,18 @@ export default function K8sResourceList() {
}
}
const fetchNamespaces = async () => {
try {
const res = await fetch('/api/v1/k8s/namespace/list')
if (!res.ok) throw new Error(`HTTP ${res.status}`)
const result = await res.json()
const namespaceList = result.data?.items?.map((ns: any) => ns.metadata.name) || []
setNamespaces(namespaceList)
} catch (e: any) {
console.error('Failed to fetch namespaces:', e)
}
}
const getResourceColumns = () => {
switch (selectedKind.key) {
case 'namespace':
@@ -412,13 +434,35 @@ export default function K8sResourceList() {
</Box>
{selectedKind.key !== 'namespace' && selectedKind.key !== 'pv' && (
<Box sx={{ mb: 2 }}>
<Box sx={{ mb: 2, display: 'flex', gap: 2 }}>
<TextField
placeholder="Namespace (空则查询所有)"
select
label="Namespace"
value={namespace}
onChange={(e) => setNamespace(e.target.value)}
size="small"
sx={{ width: 300 }}
sx={{ width: 200 }}
SelectProps={{
displayEmpty: true,
}}
InputLabelProps={{ shrink: true }}
>
<MenuItem value="">
<em></em>
</MenuItem>
{namespaces.map((ns) => (
<MenuItem key={ns} value={ns}>
{ns}
</MenuItem>
))}
</TextField>
<TextField
label="名称过滤"
placeholder="按名称过滤"
value={nameFilter}
onChange={(e) => setNameFilter(e.target.value)}
size="small"
sx={{ width: 200 }}
/>
</Box>
)}