diff --git a/frontend/src/ASNsNewManager.jsx b/frontend/src/ASNsNewManager.jsx index 93b1ca4..2aaca7b 100644 --- a/frontend/src/ASNsNewManager.jsx +++ b/frontend/src/ASNsNewManager.jsx @@ -31,6 +31,7 @@ import ErrorAlert from './components/ErrorAlert.jsx'; import { notifyMutationSuccess } from './components/NotifyProvider.jsx'; import ImportModal from './components/ImportModal.jsx'; import QuickAddBar from './components/QuickAddBar.jsx'; +import AccordionCard from './components/AccordionCard.jsx'; const API_URL = '/api'; @@ -523,24 +524,34 @@ function ASNsNewManager() { - {/* QuickAdd stays for batch input */} - { const [a, c] = String(line).split(/\s+/); return { asn: (a||'').trim(), community: (c||'').trim() }; }} - validateItem={(obj) => isValidAsn(obj.asn) && isValidCommunity(obj.community)} - onApply={(list) => { - setItems(prev => { - const merged = [...prev, ...list]; - const map = new Map(); - for (const it of merged) { - const key = String(it.asn).trim(); - if (!map.has(key)) map.set(key, { asn: key, community: String(it.community).trim() }); - } - return Array.from(map.values()); - }); - }} - /> + {/* Дополнительные варианты */} + + { const [a, c] = String(line).split(/\s+/); return { asn: (a||'').trim(), community: (c||'').trim() }; }} + validateItem={(obj) => isValidAsn(obj.asn) && isValidCommunity(obj.community)} + onApply={(list) => { + setItems(prev => { + const merged = [...prev, ...list]; + const map = new Map(); + for (const it of merged) { + const key = String(it.asn).trim(); + if (!map.has(key)) map.set(key, { asn: key, community: String(it.community).trim() }); + } + return Array.from(map.values()); + }); + }} + /> +
{ e.preventDefault(); }} + onDrop={onDropImport} + > +
+ Перетащите файл TXT/CSV сюда для импорта (формат: ASN community) +
+
+
{/* Drag & Drop импорт */}
- {/* QuickAdd stays for batch input */} - { const [d, c] = String(line).split(/\s+/); return { domain: (d||'').toLowerCase(), community: (c||'').trim() }; }} - validateItem={(obj) => isValidDomain(obj.domain) && isValidCommunity(obj.community)} - onApply={(list) => { - setItems(prev => { - const merged = [...prev, ...list]; - const map = new Map(); - for (const it of merged) { - const key = String(it.domain).trim().toLowerCase(); - if (!map.has(key)) map.set(key, { domain: key, community: String(it.community).trim() }); - } - return Array.from(map.values()); - }); - }} - /> + {/* Дополнительные варианты */} + + { const [d, c] = String(line).split(/\s+/); return { domain: (d||'').toLowerCase(), community: (c||'').trim() }; }} + validateItem={(obj) => isValidDomain(obj.domain) && isValidCommunity(obj.community)} + onApply={(list) => { + setItems(prev => { + const merged = [...prev, ...list]; + const map = new Map(); + for (const it of merged) { + const key = String(it.domain).trim().toLowerCase(); + if (!map.has(key)) map.set(key, { domain: key, community: String(it.community).trim() }); + } + return Array.from(map.values()); + }); + }} + /> +
{ e.preventDefault(); }} + onDrop={onDropImport} + > +
+ Перетащите файл TXT/CSV сюда для импорта (формат: domain community) +
+
+
{/* Карточка действий больше не нужна — действия перенесены в page-header */} {/* Drag & Drop импорт */} diff --git a/frontend/src/IPRangesManager.jsx b/frontend/src/IPRangesManager.jsx index a350992..51346af 100644 --- a/frontend/src/IPRangesManager.jsx +++ b/frontend/src/IPRangesManager.jsx @@ -31,6 +31,7 @@ import ErrorAlert from './components/ErrorAlert.jsx'; import { notifyMutationSuccess } from './components/NotifyProvider.jsx'; import ImportModal from './components/ImportModal.jsx'; import QuickAddBar from './components/QuickAddBar.jsx'; +import AccordionCard from './components/AccordionCard.jsx'; const API_URL = '/api'; @@ -779,24 +780,34 @@ function IPRangesManager() { - {/* QuickAdd stays for batch input */} - { const [cidr, c] = String(line).split(/\s+/); return { ipRange: (cidr||'').trim(), community: (c||'').trim() }; }} - validateItem={(obj) => isValidCidr(obj.ipRange) && isValidCommunity(obj.community)} - onApply={(list) => { - setItems(prev => { - const merged = [...prev, ...list]; - const map = new Map(); - for (const it of merged) { - const key = String(it.ipRange).trim(); - if (!map.has(key)) map.set(key, { ipRange: key, community: String(it.community).trim() }); - } - return Array.from(map.values()); - }); - }} - /> + {/* Дополнительные варианты */} + + { const [cidr, c] = String(line).split(/\s+/); return { ipRange: (cidr||'').trim(), community: (c||'').trim() }; }} + validateItem={(obj) => isValidCidr(obj.ipRange) && isValidCommunity(obj.community)} + onApply={(list) => { + setItems(prev => { + const merged = [...prev, ...list]; + const map = new Map(); + for (const it of merged) { + const key = String(it.ipRange).trim(); + if (!map.has(key)) map.set(key, { ipRange: key, community: String(it.community).trim() }); + } + return Array.from(map.values()); + }); + }} + /> +
{ e.preventDefault(); }} + onDrop={onDropImport} + > +
+ Перетащите файл TXT/CSV сюда для импорта (формат: CIDR community) +
+
+
{/* Drag & Drop импорт */}
+
setOpen(v => !v)} aria-expanded={open}> +

{title}

+ +
+ {open && ( +
+ {children} +
+ )} +
+ ); +} + +export default AccordionCard; + + diff --git a/frontend/src/components/PageHeader.jsx b/frontend/src/components/PageHeader.jsx index abd2523..8d2b756 100644 --- a/frontend/src/components/PageHeader.jsx +++ b/frontend/src/components/PageHeader.jsx @@ -17,7 +17,7 @@ function PageHeader({ title, pretitle, actions, meta }) { {/* Отдельная строка под заголовком: действия страницы */} {actions && ( -
+
{actions}
)}