mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-07 13:24:21 +00:00
feat(frontend): add text search to the inbound list
The v2.x panel could filter inbounds but the list page only had the node dropdown. Add a search box next to it matching on remark, port, and protocol, composed with the node filter; the dataset is already client-side, so no API change. Closes #5267
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
Card,
|
||||
Checkbox,
|
||||
Dropdown,
|
||||
Input,
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
@@ -22,6 +23,7 @@ import {
|
||||
ReloadOutlined,
|
||||
InfoCircleOutlined,
|
||||
DeleteOutlined,
|
||||
SearchOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
import { HttpUtil } from '@/utils';
|
||||
@@ -56,6 +58,7 @@ export default function InboundList({
|
||||
// Node filter (#4997): 'all' shows everything, 0 is the local-panel
|
||||
// sentinel (inbounds without a nodeId), otherwise a node id. Session-only.
|
||||
const [nodeFilter, setNodeFilter] = useState<number | 'all'>('all');
|
||||
const [searchKey, setSearchKey] = useState('');
|
||||
|
||||
const showNodeFilter = useMemo(
|
||||
() => nodesById.size > 0 || dbInbounds.some((ib) => ib.nodeId != null),
|
||||
@@ -72,10 +75,17 @@ export default function InboundList({
|
||||
);
|
||||
|
||||
const visibleInbounds = useMemo(() => {
|
||||
if (nodeFilter === 'all') return dbInbounds;
|
||||
if (nodeFilter === 0) return dbInbounds.filter((ib) => ib.nodeId == null);
|
||||
return dbInbounds.filter((ib) => ib.nodeId === nodeFilter);
|
||||
}, [dbInbounds, nodeFilter]);
|
||||
let list = dbInbounds;
|
||||
if (nodeFilter === 0) list = list.filter((ib) => ib.nodeId == null);
|
||||
else if (nodeFilter !== 'all') list = list.filter((ib) => ib.nodeId === nodeFilter);
|
||||
const q = searchKey.trim().toLowerCase();
|
||||
if (!q) return list;
|
||||
return list.filter((ib) => (
|
||||
(ib.remark || '').toLowerCase().includes(q)
|
||||
|| String(ib.port).includes(q)
|
||||
|| (ib.protocol || '').toLowerCase().includes(q)
|
||||
));
|
||||
}, [dbInbounds, nodeFilter, searchKey]);
|
||||
|
||||
const onSwitchEnable = useCallback(async (dbInbound: DBInboundRecord, next: boolean) => {
|
||||
const previous = dbInbound.enable;
|
||||
@@ -180,6 +190,15 @@ export default function InboundList({
|
||||
aria-label={t('pages.clients.filters.nodes')}
|
||||
/>
|
||||
)}
|
||||
<Input
|
||||
value={searchKey}
|
||||
onChange={(e) => setSearchKey(e.target.value)}
|
||||
placeholder={t('search')}
|
||||
allowClear
|
||||
prefix={<SearchOutlined />}
|
||||
style={{ maxWidth: isMobile ? 110 : 200 }}
|
||||
aria-label={t('search')}
|
||||
/>
|
||||
{selectedRowKeys.length > 0 && (
|
||||
<>
|
||||
<Tag color="blue" closable onClose={() => setSelectedRowKeys([])} style={{ marginInlineEnd: 0 }}>
|
||||
|
||||
Reference in New Issue
Block a user