|
@@ -32,10 +32,21 @@ import { activateOnKey } from '@/utils/a11y';
|
|
|
|
|
|
|
|
import { buildRowActionsMenu } from './RowActions';
|
|
import { buildRowActionsMenu } from './RowActions';
|
|
|
import { useInboundColumns } from './useInboundColumns';
|
|
import { useInboundColumns } from './useInboundColumns';
|
|
|
|
|
+import { buildHostRemarksByInboundId, formatHostRemarksLabel } from './helpers';
|
|
|
import InboundStatsModal from './InboundStatsModal';
|
|
import InboundStatsModal from './InboundStatsModal';
|
|
|
import type { DBInboundRecord, GeneralAction, InboundListProps, RowAction } from './types';
|
|
import type { DBInboundRecord, GeneralAction, InboundListProps, RowAction } from './types';
|
|
|
import './InboundList.css';
|
|
import './InboundList.css';
|
|
|
|
|
|
|
|
|
|
+function HostRemarksSuffix({ remarks }: { remarks: string[] }) {
|
|
|
|
|
+ if (remarks.length === 0) return null;
|
|
|
|
|
+ const { display, full } = formatHostRemarksLabel(remarks);
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Tooltip title={full}>
|
|
|
|
|
+ <span className="inbound-host-remarks"> ({display})</span>
|
|
|
|
|
+ </Tooltip>
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
export default function InboundList({
|
|
export default function InboundList({
|
|
|
dbInbounds,
|
|
dbInbounds,
|
|
|
clientCount,
|
|
clientCount,
|
|
@@ -48,6 +59,7 @@ export default function InboundList({
|
|
|
subEnable,
|
|
subEnable,
|
|
|
nodesById,
|
|
nodesById,
|
|
|
hasActiveNode,
|
|
hasActiveNode,
|
|
|
|
|
+ hosts,
|
|
|
onAddInbound,
|
|
onAddInbound,
|
|
|
onGeneralAction,
|
|
onGeneralAction,
|
|
|
onRowAction,
|
|
onRowAction,
|
|
@@ -86,19 +98,22 @@ export default function InboundList({
|
|
|
[nodesById, t],
|
|
[nodesById, t],
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
|
|
+ const hostRemarksByInboundId = useMemo(() => buildHostRemarksByInboundId(hosts), [hosts]);
|
|
|
|
|
+
|
|
|
const visibleInbounds = useMemo(() => {
|
|
const visibleInbounds = useMemo(() => {
|
|
|
let list = dbInbounds;
|
|
let list = dbInbounds;
|
|
|
if (nodeFilter === 0) list = list.filter((ib) => ib.nodeId == null);
|
|
if (nodeFilter === 0) list = list.filter((ib) => ib.nodeId == null);
|
|
|
else if (nodeFilter !== 'all') list = list.filter((ib) => ib.nodeId === nodeFilter);
|
|
else if (nodeFilter !== 'all') list = list.filter((ib) => ib.nodeId === nodeFilter);
|
|
|
const q = searchKey.trim().toLowerCase();
|
|
const q = searchKey.trim().toLowerCase();
|
|
|
if (!q) return list;
|
|
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]);
|
|
|
|
|
|
|
+ return list.filter((ib) => {
|
|
|
|
|
+ if ((ib.remark || '').toLowerCase().includes(q)) return true;
|
|
|
|
|
+ if (String(ib.port).includes(q)) return true;
|
|
|
|
|
+ if ((ib.protocol || '').toLowerCase().includes(q)) return true;
|
|
|
|
|
+ const hostRemarks = hostRemarksByInboundId.get(ib.id) ?? [];
|
|
|
|
|
+ return hostRemarks.some((remark) => remark.toLowerCase().includes(q));
|
|
|
|
|
+ });
|
|
|
|
|
+ }, [dbInbounds, nodeFilter, searchKey, hostRemarksByInboundId]);
|
|
|
|
|
|
|
|
const onSwitchEnable = useCallback(async (dbInbound: DBInboundRecord, next: boolean) => {
|
|
const onSwitchEnable = useCallback(async (dbInbound: DBInboundRecord, next: boolean) => {
|
|
|
const previous = dbInbound.enable;
|
|
const previous = dbInbound.enable;
|
|
@@ -114,8 +129,10 @@ export default function InboundList({
|
|
|
}, []);
|
|
}, []);
|
|
|
|
|
|
|
|
const hasAnyRemark = useMemo(
|
|
const hasAnyRemark = useMemo(
|
|
|
- () => dbInbounds.some((i) => typeof i.remark === 'string' && i.remark.trim() !== ''),
|
|
|
|
|
- [dbInbounds],
|
|
|
|
|
|
|
+ () =>
|
|
|
|
|
+ dbInbounds.some((i) => typeof i.remark === 'string' && i.remark.trim() !== '') ||
|
|
|
|
|
+ dbInbounds.some((i) => (hostRemarksByInboundId.get(i.id)?.length ?? 0) > 0),
|
|
|
|
|
+ [dbInbounds, hostRemarksByInboundId],
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
const hasAnySubSortIndex = useMemo(
|
|
const hasAnySubSortIndex = useMemo(
|
|
@@ -154,6 +171,7 @@ export default function InboundList({
|
|
|
hasAnySubSortIndex,
|
|
hasAnySubSortIndex,
|
|
|
hasActiveNode,
|
|
hasActiveNode,
|
|
|
nodesById,
|
|
nodesById,
|
|
|
|
|
+ hostRemarksByInboundId,
|
|
|
clientCount,
|
|
clientCount,
|
|
|
inboundSpeed,
|
|
inboundSpeed,
|
|
|
subEnable,
|
|
subEnable,
|
|
@@ -293,7 +311,10 @@ export default function InboundList({
|
|
|
onChange={(e) => toggleSelect(record.id, e.target.checked)}
|
|
onChange={(e) => toggleSelect(record.id, e.target.checked)}
|
|
|
/>
|
|
/>
|
|
|
<span className="card-id">#{record.id}</span>
|
|
<span className="card-id">#{record.id}</span>
|
|
|
- <span className="tag-name">{record.remark}</span>
|
|
|
|
|
|
|
+ <span className="tag-name">
|
|
|
|
|
+ <span className="inbound-remark">{record.remark}</span>
|
|
|
|
|
+ <HostRemarksSuffix remarks={hostRemarksByInboundId.get(record.id) ?? []} />
|
|
|
|
|
+ </span>
|
|
|
<div className="card-actions">
|
|
<div className="card-actions">
|
|
|
<Tooltip title={t('pages.inbounds.inboundInfo')}>
|
|
<Tooltip title={t('pages.inbounds.inboundInfo')}>
|
|
|
<InfoCircleOutlined
|
|
<InfoCircleOutlined
|