From 216e05df9fd5b813b10016158125b9b23af18051 Mon Sep 17 00:00:00 2001 From: shats Date: Thu, 6 Nov 2025 23:44:18 +0700 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=84=D0=B8=D0=BB=D1=8C=D1=82=D1=80?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B8=20=D0=B2=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D0=B4=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B2=20=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD=D1=82=D0=B0=D1=85=20ASNsNewManag?= =?UTF-8?q?er,=20AutoUrlManager,=20DomainsNewManager,=20IPRangesManager=20?= =?UTF-8?q?=D0=B8=20FilterManager.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B0=20null=20=D0=B4=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B5=D0=B4=D0=BE=D1=82=D0=B2=D1=80=D0=B0=D1=89=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA=20?= =?UTF-8?q?=D0=B8=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D1=81=D1=82=D0=B0=D0=B1=D0=B8=D0=BB=D1=8C=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B8=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/ASNsNewManager.jsx | 7 ++-- frontend/src/AutoUrlManager.jsx | 4 +-- frontend/src/DomainsNewManager.jsx | 23 +++++++------ frontend/src/FilterManager.jsx | 51 +++++++++++++++++----------- frontend/src/IPRangesManager.jsx | 14 ++++---- frontend/src/hooks/useDataManager.js | 11 +++--- 6 files changed, 63 insertions(+), 47 deletions(-) diff --git a/frontend/src/ASNsNewManager.jsx b/frontend/src/ASNsNewManager.jsx index e8adada..b16fd05 100644 --- a/frontend/src/ASNsNewManager.jsx +++ b/frontend/src/ASNsNewManager.jsx @@ -365,9 +365,10 @@ function ASNsNewManager() { // Локальная фильтрация и пагинация const filtered = sortedItems.filter(i => { + if (!i) return false; const byCommunity = !filterCommunity || i.community === filterCommunity; const term = String(searchTerm || '').toLowerCase(); - const bySearch = !term || String(i.asn).toLowerCase().includes(term); + const bySearch = !term || String(i.asn || '').toLowerCase().includes(term); return byCommunity && bySearch; }); const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize)); @@ -375,7 +376,7 @@ function ASNsNewManager() { // Подгружаем имена ASN из кэша/внешних API (после вычисления paginatedItems) useEffect(() => { - const visible = paginatedItems.map(i => i.asn); + const visible = paginatedItems.filter(i => i != null).map(i => i.asn).filter(asn => asn != null); visible.forEach(async (asn) => { const cached = getAsnNameSync(asn); if (cached !== null && typeof cached !== 'undefined') { @@ -388,7 +389,7 @@ function ASNsNewManager() { }, [JSON.stringify(paginatedItems)]); // Для фильтра - список всех уникальных community - const allCommunities = Array.from(new Set(items.map(i => String(i.community)))); + const allCommunities = Array.from(new Set(items.filter(i => i != null).map(i => String(i.community || '')).filter(c => c !== ''))); // Сортировка по клику const handleSort = (field) => { diff --git a/frontend/src/AutoUrlManager.jsx b/frontend/src/AutoUrlManager.jsx index 716cb69..717262b 100644 --- a/frontend/src/AutoUrlManager.jsx +++ b/frontend/src/AutoUrlManager.jsx @@ -83,7 +83,7 @@ function AutoUrlManager() { // Validate URLs const validUrls = urls - .filter(u => isValidHttpUrl(u.url) && isValidCommunity(u.community)) + .filter(u => u != null && isValidHttpUrl(u.url) && isValidCommunity(u.community)) .map(u => ({ url: u.url.trim(), community: String(u.community).trim() })); if (validUrls.length === 0) { setMessage('Добавьте хотя бы одну корректную запись (валидный URL и числовой community)'); @@ -302,7 +302,7 @@ function AutoUrlManager() {
)} @@ -1284,7 +1295,7 @@ function FilterManager() { - {filter.gateway} + {filter?.gateway || ''} )} @@ -1296,8 +1307,8 @@ function FilterManager() { onChange={(e) => setEditingDraft({ ...editingDraft, description: e.target.value })} /> ) : ( -
- {filter.description ? ( +
+ {filter?.description ? ( {filter.description} ) : ( Без описания @@ -1712,26 +1723,26 @@ function FilterManager() { ) : simpleFilters.length === 0 ? ( Нет фильтров ) : ( - simpleFilters.map((filter, idx) => ( + simpleFilters.filter(f => f != null).map((filter, idx) => ( handleSimpleEditFilter(idx, 'community', e.target.value)} /> handleSimpleEditFilter(idx, 'gateway', e.target.value)} /> handleSimpleEditFilter(idx, 'description', e.target.value)} /> @@ -2041,7 +2052,7 @@ function EditFilterModal({ show, filter, onChange, onSave, onClose }) { type="text" className="form-control" placeholder="65001:200" - value={filter.community} + value={filter?.community || ''} onChange={(e) => handleChange('community', e.target.value)} required /> @@ -2052,7 +2063,7 @@ function EditFilterModal({ show, filter, onChange, onSave, onClose }) { type="text" className="form-control" placeholder="SWE-HIPHOST" - value={filter.gateway} + value={filter?.gateway || ''} onChange={(e) => handleChange('gateway', e.target.value)} required /> @@ -2063,7 +2074,7 @@ function EditFilterModal({ show, filter, onChange, onSave, onClose }) { type="text" className="form-control" placeholder="Описание фильтра" - value={filter.description} + value={filter?.description || ''} onChange={(e) => handleChange('description', e.target.value)} />
@@ -2099,9 +2110,9 @@ function DeleteFilterModal({ show, filter, onDelete, onClose }) {

Вы уверены, что хотите удалить фильтр?

- Community: {filter.community}
- Gateway: {filter.gateway}
- {filter.description && <>Описание: {filter.description}} + Community: {filter?.community || ''}
+ Gateway: {filter?.gateway || ''}
+ {filter?.description && <>Описание: {filter.description}}
diff --git a/frontend/src/IPRangesManager.jsx b/frontend/src/IPRangesManager.jsx index 14f7026..53800a3 100644 --- a/frontend/src/IPRangesManager.jsx +++ b/frontend/src/IPRangesManager.jsx @@ -225,7 +225,7 @@ function IPRangesManager() { const [analyzeFilters, setAnalyzeFilters] = useState({ community: '', minMask: 0, maxMask: 32, type: 'any', supernet16: false }); const handlePreviewDiff = () => { - const valid = items.filter(i => isValidCidr(i.ipRange) && isValidCommunity(i.community)) + const valid = items.filter(i => i != null && isValidCidr(i.ipRange) && isValidCommunity(i.community)) .map(i => ({ ipRange: i.ipRange.trim(), community: String(i.community).trim() })); const unique = deduplicate(valid); setDiff(computeDiff(originalItems, unique)); @@ -234,7 +234,7 @@ function IPRangesManager() { const handleSaveChanges = async () => { // подготовим diff и спросим подтверждение только при массовых изменениях (>10) - const valid = items.filter(i => isValidCidr(i.ipRange) && isValidCommunity(i.community)) + const valid = items.filter(i => i != null && isValidCidr(i.ipRange) && isValidCommunity(i.community)) .map(i => ({ ipRange: i.ipRange.trim(), community: String(i.community).trim() })); const unique = deduplicate(valid); const diffData = computeDiff(originalItems, unique); @@ -329,7 +329,7 @@ function IPRangesManager() { const parsed = lines.map(l => { const [cidr, c] = l.split(/\s+/); return { ipRange: (cidr || '').trim(), community: (c || '').trim() }; - }).filter(i => isValidCidr(i.ipRange) && isValidCommunity(i.community)); + }).filter(i => i != null && isValidCidr(i.ipRange) && isValidCommunity(i.community)); setItems(prev => { const merged = [...prev, ...parsed]; const map = new Map(); @@ -342,7 +342,7 @@ function IPRangesManager() { }; const clearInvalid = () => { - setItems(prev => prev.filter(i => i.ipRange || i.community) + setItems(prev => prev.filter(i => i != null && (i.ipRange || i.community)) .filter(i => isValidCidr(i.ipRange) && isValidCommunity(i.community)) ); }; @@ -603,7 +603,7 @@ function IPRangesManager() { const community = String(analyzeFilters.community || '').trim(); if (!community) { window.notify?.error?.('Выберите community'); return; } // исходные для community - const allForCommunity = items.filter(i => i.community === community && isValidCidr(i.ipRange)); + const allForCommunity = items.filter(i => i != null && i.community === community && isValidCidr(i.ipRange)); const totalBefore = allForCommunity.length; const filtered = allForCommunity.filter(i => { @@ -641,7 +641,7 @@ function IPRangesManager() { const applyAnalysisToItems = () => { if (!analysisPreview) return; const { community, afterCidrs, unchangedCidrs } = analysisPreview; - const keptOthers = items.filter(i => i.community !== community); + const keptOthers = items.filter(i => i != null && i.community !== community); const newCommunityItems = [ ...unchangedCidrs.map(ipRange => ({ ipRange, community })), ...afterCidrs.map(ipRange => ({ ipRange, community })) @@ -1054,7 +1054,7 @@ function IPRangesManager() { message={`Будут удалены все IP-диапазоны с community "${filterCommunity}". Действие НЕ сохраняет изменения автоматически.`} confirmText={'Удалить'} cancelText={'Отмена'} - onConfirm={() => { setItems(prev => prev.filter(i => i.community !== filterCommunity)); setClearCommunitiesOpen(false); }} + onConfirm={() => { setItems(prev => prev.filter(i => i != null && i.community !== filterCommunity)); setClearCommunitiesOpen(false); }} onCancel={() => setClearCommunitiesOpen(false)} /> {/* Analyze Settings Modal */} diff --git a/frontend/src/hooks/useDataManager.js b/frontend/src/hooks/useDataManager.js index b15a627..a69867c 100644 --- a/frontend/src/hooks/useDataManager.js +++ b/frontend/src/hooks/useDataManager.js @@ -129,7 +129,7 @@ export function useDataManager(config) { continue; } const prev = mapBefore.get(k); - if (String(prev.community) !== String(v.community)) { + if (prev && v && String(prev.community || '') !== String(v.community || '')) { changed.push({ from: prev, to: v }); } } @@ -147,6 +147,7 @@ export function useDataManager(config) { try { // Валидируем и дедуплицируем const valid = items.filter(item => { + if (!item) return false; const itemValid = validateItem ? validateItem(item[itemKey]) : true; const communityValid = validateCommunity ? validateCommunity(item.community) : true; return itemValid && communityValid; @@ -198,7 +199,8 @@ export function useDataManager(config) { }; // Сортировка - const sortedItems = [...items].sort((a, b) => { + const sortedItems = [...items].filter(item => item != null).sort((a, b) => { + if (!a || !b) return 0; let valA = a[sortField] || ''; let valB = b[sortField] || ''; if (typeof valA === 'string') valA = valA.toLowerCase(); @@ -210,9 +212,10 @@ export function useDataManager(config) { // Фильтрация const filtered = sortedItems.filter(item => { + if (!item) return false; const byCommunity = !filterCommunity || item.community === filterCommunity; const term = String(searchTerm || '').toLowerCase(); - const bySearch = !term || String(item[itemKey]).toLowerCase().includes(term); + const bySearch = !term || String(item[itemKey] || '').toLowerCase().includes(term); return byCommunity && bySearch; }); @@ -221,7 +224,7 @@ export function useDataManager(config) { 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.filter(i => i != null).map(i => i.community).filter(c => c != null))); // Управление сортировкой const handleSort = (field) => {