+ {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) => {