feat: добавлена возможность сортировки трафика по частоте и времени
Some checks failed
Build and Deploy Gateway / build-and-deploy (push) Failing after 0s
Some checks failed
Build and Deploy Gateway / build-and-deploy (push) Failing after 0s
Refs: None
This commit is contained in:
@@ -33,7 +33,7 @@ const CATEGORY_BADGE = {
|
|||||||
other: { cls: '', label: 'other' },
|
other: { cls: '', label: 'other' },
|
||||||
};
|
};
|
||||||
|
|
||||||
function groupTraffic(list) {
|
function groupTraffic(list, sortBy = 'time') {
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
for (const e of list) {
|
for (const e of list) {
|
||||||
const key = `${e.category}|${e.host}|${e.port}|${e.matchedRule || ''}`;
|
const key = `${e.category}|${e.host}|${e.port}|${e.matchedRule || ''}`;
|
||||||
@@ -47,7 +47,9 @@ function groupTraffic(list) {
|
|||||||
map.set(key, { ...e, _key: key, _lastTs: ts, count: 1, lastTs: e.ts });
|
map.set(key, { ...e, _key: key, _lastTs: ts, count: 1, lastTs: e.ts });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Array.from(map.values()).sort((a, b) => b._lastTs - a._lastTs);
|
const arr = Array.from(map.values());
|
||||||
|
if (sortBy === 'count') return arr.sort((a, b) => b.count - a.count || b._lastTs - a._lastTs);
|
||||||
|
return arr.sort((a, b) => b._lastTs - a._lastTs);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TrafficTab() {
|
function TrafficTab() {
|
||||||
@@ -56,6 +58,7 @@ function TrafficTab() {
|
|||||||
const [filter, setFilter] = useState('all'); // all | direct | vpn | block
|
const [filter, setFilter] = useState('all'); // all | direct | vpn | block
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
const [grouped, setGrouped] = useState(true);
|
const [grouped, setGrouped] = useState(true);
|
||||||
|
const [sortBy, setSortBy] = useState('count'); // time | count
|
||||||
const [autoscroll, setAutoscroll] = useState(true);
|
const [autoscroll, setAutoscroll] = useState(true);
|
||||||
const containerRef = useRef(null);
|
const containerRef = useRef(null);
|
||||||
const pausedRef = useRef(false);
|
const pausedRef = useRef(false);
|
||||||
@@ -90,8 +93,8 @@ function TrafficTab() {
|
|||||||
e.matchedRule?.toLowerCase().includes(s),
|
e.matchedRule?.toLowerCase().includes(s),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return grouped ? groupTraffic(list) : list;
|
return grouped ? groupTraffic(list, sortBy) : list;
|
||||||
}, [traffic, filter, search, grouped]);
|
}, [traffic, filter, search, grouped, sortBy]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!autoscroll || !containerRef.current) return;
|
if (!autoscroll || !containerRef.current) return;
|
||||||
@@ -124,6 +127,12 @@ function TrafficTab() {
|
|||||||
<input type="checkbox" checked={grouped} onChange={(e) => setGrouped(e.target.checked)} />
|
<input type="checkbox" checked={grouped} onChange={(e) => setGrouped(e.target.checked)} />
|
||||||
Группировать
|
Группировать
|
||||||
</label>
|
</label>
|
||||||
|
{grouped && (
|
||||||
|
<select className="select" value={sortBy} onChange={(e) => setSortBy(e.target.value)} style={{ width: 'auto' }}>
|
||||||
|
<option value="count">По частоте</option>
|
||||||
|
<option value="time">По времени</option>
|
||||||
|
</select>
|
||||||
|
)}
|
||||||
<label className="checkbox">
|
<label className="checkbox">
|
||||||
<input type="checkbox" checked={autoscroll} onChange={(e) => setAutoscroll(e.target.checked)} />
|
<input type="checkbox" checked={autoscroll} onChange={(e) => setAutoscroll(e.target.checked)} />
|
||||||
Автоскролл
|
Автоскролл
|
||||||
|
|||||||
Reference in New Issue
Block a user