feat: Добавить кэширование имен ASN и улучшить обработку данных в менеджере ASNs, включая обновление фильтрации и отображения метаданных
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m51s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m51s
This commit is contained in:
@@ -32,6 +32,7 @@ import { notifyMutationSuccess } from './components/NotifyProvider.jsx';
|
||||
import ImportModal from './components/ImportModal.jsx';
|
||||
import QuickAddBar from './components/QuickAddBar.jsx';
|
||||
import AccordionCard from './components/AccordionCard.jsx';
|
||||
import { getAsnName, getAsnNameSync } from './lib/asn.js';
|
||||
|
||||
const API_URL = '/api';
|
||||
|
||||
@@ -60,6 +61,7 @@ function ASNsNewManager() {
|
||||
const [filterCommunity, setFilterCommunity] = useState('');
|
||||
const editInputRef = useRef(null);
|
||||
const pageSize = 10;
|
||||
const [asnNameMap, setAsnNameMap] = useState({});
|
||||
|
||||
// Справочник community для подсказок
|
||||
const [communities, setCommunities] = useState([]);
|
||||
@@ -74,6 +76,20 @@ function ASNsNewManager() {
|
||||
})();
|
||||
}, []);
|
||||
|
||||
// Подгружаем имена ASN из кэша/внешних API
|
||||
useEffect(() => {
|
||||
const visible = paginatedItems.map(i => i.asn);
|
||||
visible.forEach(async (asn) => {
|
||||
const cached = getAsnNameSync(asn);
|
||||
if (cached !== null && typeof cached !== 'undefined') {
|
||||
setAsnNameMap(prev => ({ ...prev, [asn]: cached }));
|
||||
return;
|
||||
}
|
||||
const name = await getAsnName(asn);
|
||||
if (name !== null) setAsnNameMap(prev => ({ ...prev, [asn]: name }));
|
||||
});
|
||||
}, [JSON.stringify(paginatedItems)]);
|
||||
|
||||
const renderCommunityBadge = (value) => {
|
||||
const v = String(value ?? '').trim();
|
||||
if (!v) return <span className="badge bg-blue-lt text-blue">—</span>;
|
||||
@@ -105,7 +121,7 @@ function ASNsNewManager() {
|
||||
try {
|
||||
const response = await api.get(`/asns`, { params: { offset: 0, limit: 0, format: 'std' } });
|
||||
const payload = Array.isArray(response.data?.items) ? response.data.items : [];
|
||||
const mapped = payload.map(item => ({ asn: item.domain, community: item.type }));
|
||||
const mapped = payload.map(item => ({ asn: String(item.domain), community: String(item.type) }));
|
||||
const total = mapped.length;
|
||||
setItems(mapped);
|
||||
setOriginalItems(mapped);
|
||||
@@ -367,7 +383,7 @@ function ASNsNewManager() {
|
||||
const paginatedItems = filtered.slice((currentPage - 1) * pageSize, (currentPage) * pageSize);
|
||||
|
||||
// Для фильтра - список всех уникальных community
|
||||
const allCommunities = Array.from(new Set(items.map(i => i.community)));
|
||||
const allCommunities = Array.from(new Set(items.map(i => String(i.community))));
|
||||
|
||||
// Сортировка по клику
|
||||
const handleSort = (field) => {
|
||||
@@ -577,7 +593,7 @@ function ASNsNewManager() {
|
||||
value={filterCommunity}
|
||||
onChange={e => { setFilterCommunity(e.target.value); setCurrentPage(1); }}
|
||||
title={(() => {
|
||||
const meta = communities.find(c => c.value === filterCommunity);
|
||||
const meta = communities.find(c => String(c.value) === String(filterCommunity));
|
||||
if (!meta) return 'Все community';
|
||||
const name = meta.name ? meta.name + ' — ' : '';
|
||||
const desc = meta.description || '';
|
||||
@@ -587,11 +603,11 @@ function ASNsNewManager() {
|
||||
>
|
||||
<option value="">Все community</option>
|
||||
{allCommunities.map(community => {
|
||||
const meta = communities.find(c => c.value === community);
|
||||
const meta = communities.find(c => String(c.value) === String(community));
|
||||
const label = meta && meta.name ? `${community} — ${meta.name}` : community;
|
||||
const title = meta ? `${meta.name ? meta.name + ' — ' : ''}${meta.description || ''}${meta.tags && meta.tags.length ? ' (' + meta.tags.join(', ') + ')' : ''}` : community;
|
||||
return (
|
||||
<option key={community} value={community} title={title}>{label}</option>
|
||||
<option key={community} value={String(community)} title={title}>{label}</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
@@ -632,6 +648,9 @@ function ASNsNewManager() {
|
||||
</span>
|
||||
)}
|
||||
</th>
|
||||
<th>
|
||||
Имя AS
|
||||
</th>
|
||||
<th className="cursor-pointer" onClick={() => handleSort('community')}>
|
||||
Community
|
||||
{sortField === 'community' && (
|
||||
@@ -647,6 +666,13 @@ function ASNsNewManager() {
|
||||
{paginatedItems.map((item) => (
|
||||
<tr key={item.asn} className={editingAsn === item.asn ? 'table-info' : ''}>
|
||||
<td className="font-monospace" title="ASN">{item.asn}</td>
|
||||
<td title={asnNameMap[item.asn] || ''}>
|
||||
{asnNameMap[item.asn] ? (
|
||||
<span>{asnNameMap[item.asn]}</span>
|
||||
) : (
|
||||
<span className="text-muted">—</span>
|
||||
)}
|
||||
</td>
|
||||
<td>{renderCommunityBadge(item.community)}</td>
|
||||
<td className="text-end">
|
||||
{editingAsn === item.asn ? (
|
||||
|
||||
Reference in New Issue
Block a user