diff --git a/frontend/src/ASNsNewManager.jsx b/frontend/src/ASNsNewManager.jsx index a77aaa3..fba44c3 100644 --- a/frontend/src/ASNsNewManager.jsx +++ b/frontend/src/ASNsNewManager.jsx @@ -510,25 +510,27 @@ function ASNsNewManager() { {error && ( setError('')} /> )} - + {success && (
-
- {success} -
+
{success}
- +
)} } - actions={( + actions={ { if (!filterCommunity) { setError('Выберите community в фильтре для очистки'); return; } setClearCommunitiesOpen(true); }} + onClearCommunities={() => { + if (!filterCommunity) { + setError('Выберите community в фильтре для очистки'); + return; + } + setClearCommunitiesOpen(true); + }} disableClearCommunities={items.length === 0 || !filterCommunity} onSave={handleSaveChanges} disableSave={loading} @@ -549,18 +557,23 @@ function ASNsNewManager() { onOnlineUpdate={() => setWsOpen(true)} onBackgroundUpdate={async () => { try { - const res = await fetch('/api/update-bgp/background', { method: 'POST' }); + const res = await fetch('/api/update-bgp/background', { + method: 'POST', + }); const data = await res.json().catch(() => ({})); if (!res.ok || data.ok === false) { throw new Error(data?.message || `HTTP ${res.status}`); } notifyMutationSuccess('Фоновое обновление запущено', data); } catch (e) { - window.notify?.error('Не удалось запустить фоновое обновление', String(e)); + window.notify?.error( + 'Не удалось запустить фоновое обновление', + String(e), + ); } }} /> - )} + } /> -
-
- {/* BulkActionsBar */} - 0 ? () => { - if (confirm(`Удалить ${selectedItems.size} записей?`)) { - handleBulkDelete(); - } - } : null} - onExport={selectedItems.size > 0 ? handleBulkExport : null} - /> - -
-
-
-
-
-
- - Список - {filtered.length} -
-
- Всего записей: {filtered.length} -
-
-
-
-
- { - setSearchTerm(filters.searchTerm || ''); - setFilterCommunity(filters.filterCommunity || ''); - setSortField(filters.sortField || 'asn'); - setSortOrder(filters.sortOrder || 'asc'); - setCurrentPage(1); - }} - /> - {/* Фильтр по community */} -
- - +
+
+
+
+
+
+ + Список + + {filtered.length} -
- {/* Поиск */} -
- - - - { setSearchTerm(e.target.value); setCurrentPage(1); }} - aria-label="Поиск ASN" - style={{ paddingRight: searchTerm ? '2.5rem' : undefined }} - /> - {!!searchTerm && ( - - )} +
+ Всего записей: {filtered.length}
-
-
- {/* Таблица на лёгкой карточной подложке */} - {loading ? ( - - ) : paginatedItems.length === 0 ? ( - - Импорт} - secondaryAction={} - /> - - ) : ( -
- - - - - - - - - - - - {paginatedItems.map((item, idx) => ( - - - - - - - - ))} - -
- 0 && paginatedItems.every(i => selectedItems.has(i.asn))} - onChange={(e) => { - if (e.target.checked) { - selectAll(); - } else { - deselectAll(); - } - }} - title="Выбрать все на странице" - /> - handleSort('asn')}> -
- - Номер AS - {sortField === 'asn' && ( - - {sortOrder === 'asc' ? : } - - )} -
-
- Имя AS - handleSort('community')}> -
- - Community - {sortField === 'community' && ( - - {sortOrder === 'asc' ? : } - - )} -
-
Действия
- toggleSelectItem(item.asn)} - onClick={(e) => e.stopPropagation()} - /> - -
- - {item.asn} - - - -
-
- {asnNameMap[item.asn] ? ( - {asnNameMap[item.asn]} - ) : ( - - )} - {renderCommunityBadge(item.community)} -
- - - - - - -
-
-
- )} -
-
- +
+
+
+ + + + +
+
+ + + + { + setSearchTerm(e.target.value); + setCurrentPage(1); + }} + aria-label="Поиск ASN" + style={{ paddingRight: searchTerm ? '2.5rem' : undefined }} + /> + {!!searchTerm && ( + + )} +
+
+ +
+ {loading ? ( + + ) : paginatedItems.length === 0 ? ( + + + Импорт + + } + secondaryAction={ + + } + /> + + ) : ( +
+ + + + + + + + + + + + {paginatedItems.map((item, idx) => ( + + + + + + + + ))} + +
+ 0 && + paginatedItems.every((i) => selectedItems.has(i.asn)) + } + onChange={(e) => { + if (e.target.checked) { + selectAll(); + } else { + deselectAll(); + } + }} + title="Выбрать все на странице" + /> + handleSort('asn')} + > +
+ + Номер AS + {sortField === 'asn' && ( + + {sortOrder === 'asc' ? ( + + ) : ( + + )} + + )} +
+
Имя AS handleSort('community')} + > +
+ + Community + {sortField === 'community' && ( + + {sortOrder === 'asc' ? ( + + ) : ( + + )} + + )} +
+
Действия
+ toggleSelectItem(item.asn)} + onClick={(e) => e.stopPropagation()} + /> + +
+ + {item.asn} + + + +
+
+ {asnNameMap[item.asn] ? ( + {asnNameMap[item.asn]} + ) : ( + + )} + {renderCommunityBadge(item.community)} +
+ + + + + + +
+
+
+ )} +
+ +
+ +
setShowDeleteModal(false)} /> + setConfirmSaveOpen(false)} /> + setImportOpen(false)} - sampleHeader={['asn','community']} + sampleHeader={['asn', 'community']} placeholder={'12345 65000:100'} /> - {/* Модальное окно редактирования community */} +

- ASN: {itemBeingEdited.asn} + ASN:{' '} + {itemBeingEdited.asn}

@@ -871,7 +932,9 @@ function ASNsNewManager() { onChange={setEditingValue} communities={communities} onKeyDown={handleEditKeyDown} - className={`form-control${isValidCommunity(editingValue) ? '' : ' is-invalid'}`} + className={`form-control${ + isValidCommunity(editingValue) ? '' : ' is-invalid' + }`} useShortValue={true} /> {!isValidCommunity(editingValue) && ( @@ -883,29 +946,34 @@ function ASNsNewManager() { )} + setHistoryOpen(false)} onRolledBack={() => fetchItems()} /> + setWsOpen(false)} /> + { setItems(prev => prev.filter(i => i.community !== filterCommunity)); setClearCommunitiesOpen(false); }} + onConfirm={() => { + setItems((prev) => prev.filter((i) => i.community !== filterCommunity)); + setClearCommunitiesOpen(false); + }} onCancel={() => setClearCommunitiesOpen(false)} /> - {/* datalist больше не нужен, т.к. используем кастомный автокомплит */}
); } -export default ASNsNewManager; \ No newline at end of file +export default ASNsNewManager; \ No newline at end of file