feat: Удалить логику блокировок и обновить логику загрузки данных в менеджерах ASNs, Domains и IPRanges, улучшив фильтрацию и пагинацию для локального отображения
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m55s

This commit is contained in:
2025-08-27 17:39:04 +07:00
parent 0f3ad56f87
commit cd3f7a84e3
4 changed files with 37 additions and 177 deletions
+12 -31
View File
@@ -91,33 +91,19 @@ function ASNsNewManager() {
const [wsUrl, setWsUrl] = useState('');
useEffect(() => {
// Acquire soft lock
const owner = localStorage.getItem('uiOwner') || `ui-${Math.random().toString(36).slice(2,8)}`;
localStorage.setItem('uiOwner', owner);
const resource = 'asns';
const acquire = async () => {
try { await api.post(`/locks/${resource}`, { owner, ttlSeconds: 180 }); } catch {}
};
acquire();
const interval = setInterval(acquire, 60_000);
// Load WS URL once
(async () => {
try { const r = await api.get('/ws/url'); setWsUrl(String(r.data?.url || '')); } catch {}
})();
return () => {
clearInterval(interval);
api.delete(`/locks/${resource}`).catch(() => {});
};
}, []);
const fetchItems = async () => {
setLoading(true);
try {
const effectiveQ = searchTerm ? searchTerm : (filterCommunity ? filterCommunity : '');
const response = await api.get(`/asns`, { params: { q: effectiveQ, offset: Math.max(0, (currentPage - 1) * pageSize), limit: pageSize, format: 'std' } });
const response = await api.get(`/asns`, { params: { offset: 0, limit: 0, format: 'std' } });
const payload = Array.isArray(response.data?.items) ? response.data.items : [];
const total = Number(response.data?.total ?? (Array.isArray(response.data) ? response.data.length : 0));
const mapped = payload.map(item => ({ asn: item.domain, community: item.type }));
const total = mapped.length;
setItems(mapped);
setOriginalItems(mapped);
setTotalItems(Number.isFinite(total) ? total : 0);
@@ -134,13 +120,7 @@ function ASNsNewManager() {
}
};
useEffect(() => {
if (!didInit.current) { didInit.current = true; fetchItems(); return; }
if (searchTimer.current) clearTimeout(searchTimer.current);
searchTimer.current = setTimeout(() => { fetchItems(); }, 350);
return () => { if (searchTimer.current) clearTimeout(searchTimer.current); };
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentPage, searchTerm, filterCommunity]);
useEffect(() => { if (!didInit.current) { didInit.current = true; fetchItems(); } }, []);
const handleAddItem = () => {
const asnOk = isValidAsn(newItem.asn);
@@ -368,14 +348,15 @@ function ASNsNewManager() {
return 0;
});
// Фильтрация по community
const filteredByCommunity = filterCommunity
? sortedItems.filter(i => i.community === filterCommunity)
: sortedItems;
// Пагинация теперь серверная
const paginatedItems = filteredByCommunity;
const totalPages = Math.max(1, Math.ceil((totalItems || paginatedItems.length) / pageSize));
// Локальная фильтрация и пагинация
const filtered = sortedItems.filter(i => {
const byCommunity = !filterCommunity || i.community === filterCommunity;
const term = String(searchTerm || '').toLowerCase();
const bySearch = !term || String(i.asn).toLowerCase().includes(term);
return byCommunity && bySearch;
});
const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
const paginatedItems = filtered.slice((currentPage - 1) * pageSize, (currentPage) * pageSize);
// Для фильтра - список всех уникальных community
const allCommunities = Array.from(new Set(items.map(i => i.community)));