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:
@@ -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>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user