feat(FirewallPage): enhance apply summary functionality with confirmation for individual and bulk actions
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m8s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m8s
This commit is contained in:
@@ -231,6 +231,8 @@ export default function FirewallPage() {
|
||||
const [applying, setApplying] = useState(false);
|
||||
const [ipInfoMap, setIpInfoMap] = useState({});
|
||||
const [ipInfoLoading, setIpInfoLoading] = useState(false);
|
||||
const [applyConfirmRow, setApplyConfirmRow] = useState(null);
|
||||
const [applyingRow, setApplyingRow] = useState(null);
|
||||
|
||||
const routerServers = useMemo(
|
||||
() =>
|
||||
@@ -327,26 +329,46 @@ export default function FirewallPage() {
|
||||
return () => { cancelled = true; };
|
||||
}, [analysisResult?.suggestions]);
|
||||
|
||||
const applyPayload = applyConfirmRow
|
||||
? { removeIds: applyConfirmRow.ids, addEntries: [applyConfirmRow.addEntry] }
|
||||
: analysisResult?.suggestions?.length
|
||||
? {
|
||||
removeIds: analysisResult.suggestions.flatMap((s) => s.ids),
|
||||
addEntries: analysisResult.suggestions.map((s) => s.addEntry),
|
||||
}
|
||||
: null;
|
||||
|
||||
const handleApplySummary = async () => {
|
||||
if (!serverId || !analysisResult?.suggestions?.length) return;
|
||||
setApplying(true);
|
||||
if (!serverId || !applyPayload) return;
|
||||
const isRow = !!applyConfirmRow;
|
||||
if (isRow) setApplyingRow(applyConfirmRow.subnet);
|
||||
else setApplying(true);
|
||||
try {
|
||||
const removeIds = analysisResult.suggestions.flatMap((s) => s.ids);
|
||||
const addEntries = analysisResult.suggestions.map((s) => s.addEntry);
|
||||
await api.post('/mikrotik/address-lists/apply-summary', {
|
||||
serverId,
|
||||
removeIds,
|
||||
addEntries,
|
||||
removeIds: applyPayload.removeIds,
|
||||
addEntries: applyPayload.addEntries,
|
||||
});
|
||||
window.notify?.success?.(`Удалено ${removeIds.length} записей, добавлено ${addEntries.length} подсетей.`);
|
||||
const removed = applyPayload.removeIds.length;
|
||||
const added = applyPayload.addEntries.length;
|
||||
window.notify?.success?.(`Удалено ${removed} записей, добавлено ${added} подсетей.`);
|
||||
setApplyConfirmOpen(false);
|
||||
setAnalysisOpen(false);
|
||||
setAnalysisResult(null);
|
||||
setApplyConfirmRow(null);
|
||||
if (isRow && analysisResult?.suggestions) {
|
||||
setAnalysisResult((prev) => ({
|
||||
...prev,
|
||||
suggestions: prev.suggestions.filter((s) => s.subnet !== applyConfirmRow.subnet),
|
||||
}));
|
||||
} else {
|
||||
setAnalysisOpen(false);
|
||||
setAnalysisResult(null);
|
||||
}
|
||||
await fetchAddressLists();
|
||||
} catch (e) {
|
||||
window.notify?.error?.(e?.response?.data?.message || e?.message || 'Ошибка применения');
|
||||
} finally {
|
||||
setApplying(false);
|
||||
setApplyingRow(null);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -457,10 +479,11 @@ export default function FirewallPage() {
|
||||
setAnalysisOpen(false);
|
||||
setAnalysisResult(null);
|
||||
setApplyConfirmOpen(false);
|
||||
setApplyConfirmRow(null);
|
||||
setIpInfoMap({});
|
||||
}}
|
||||
title="Анализ списка ban"
|
||||
size="lg"
|
||||
size="xl"
|
||||
>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">Суммаризировать подсети /24, в которых одиночных IP больше чем</label>
|
||||
@@ -504,12 +527,14 @@ export default function FirewallPage() {
|
||||
<th>AS / Хостер</th>
|
||||
<th>Ссылка</th>
|
||||
<th>Действие</th>
|
||||
<th className="text-end" style={{ width: '120px' }}>Применить</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{analysisResult.suggestions.map((s) => {
|
||||
const firstIp = s.subnet.split('/')[0];
|
||||
const info = ipInfoMap[s.subnet];
|
||||
const rowApplying = applyingRow === s.subnet;
|
||||
return (
|
||||
<tr key={s.subnet}>
|
||||
<td className="font-monospace">{s.subnet}</td>
|
||||
@@ -532,6 +557,22 @@ export default function FirewallPage() {
|
||||
</a>
|
||||
</td>
|
||||
<td className="text-muted small">Удалить {s.count} записей → добавить 1</td>
|
||||
<td className="text-end">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-sm btn-warning"
|
||||
disabled={rowApplying || applying}
|
||||
onClick={() => {
|
||||
setApplyConfirmRow(s);
|
||||
setApplyConfirmOpen(true);
|
||||
}}
|
||||
>
|
||||
{rowApplying ? (
|
||||
<span className="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true" />
|
||||
) : null}
|
||||
Применить
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
@@ -542,9 +583,12 @@ export default function FirewallPage() {
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-warning"
|
||||
onClick={() => setApplyConfirmOpen(true)}
|
||||
onClick={() => {
|
||||
setApplyConfirmRow(null);
|
||||
setApplyConfirmOpen(true);
|
||||
}}
|
||||
>
|
||||
Применить на роутере
|
||||
Применить всё на роутере
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
@@ -555,19 +599,24 @@ export default function FirewallPage() {
|
||||
|
||||
<ConfirmDialog
|
||||
open={applyConfirmOpen}
|
||||
title="Применить суммаризацию на роутере?"
|
||||
title={applyConfirmRow ? `Применить для ${applyConfirmRow.subnet}?` : 'Применить суммаризацию на роутере?'}
|
||||
message={
|
||||
analysisResult?.suggestions?.length
|
||||
? `Будет удалено ${analysisResult.suggestions.reduce((acc, s) => acc + s.ids.length, 0)} записей и добавлено ${analysisResult.suggestions.length} записей (подсети /24). Продолжить?`
|
||||
: ''
|
||||
applyConfirmRow
|
||||
? `Удалить ${applyConfirmRow.count} записей и добавить 1 запись (подсеть ${applyConfirmRow.subnet}). Продолжить?`
|
||||
: applyPayload
|
||||
? `Будет удалено ${applyPayload.removeIds.length} записей и добавлено ${applyPayload.addEntries.length} записей (подсети /24). Продолжить?`
|
||||
: ''
|
||||
}
|
||||
confirmText="Применить"
|
||||
cancelText="Отмена"
|
||||
destructive
|
||||
size="md"
|
||||
loading={applying}
|
||||
loading={applying || !!applyingRow}
|
||||
onConfirm={handleApplySummary}
|
||||
onCancel={() => setApplyConfirmOpen(false)}
|
||||
onCancel={() => {
|
||||
setApplyConfirmOpen(false);
|
||||
setApplyConfirmRow(null);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user