From ae88a3a46a489d3143a1a61f4745e3098686ea60 Mon Sep 17 00:00:00 2001 From: shats Date: Tue, 11 Nov 2025 21:08:45 +0700 Subject: [PATCH] =?UTF-8?q?feat:=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=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D0=B0=20AutoUrlManager=20=D1=81=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=D0=BC=20?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D1=8B=D1=85=20=D1=84=D1=83=D0=BD=D0=BA=D1=86?= =?UTF-8?q?=D0=B8=D0=B9,=20=D1=82=D0=B0=D0=BA=D0=B8=D1=85=20=D0=BA=D0=B0?= =?UTF-8?q?=D0=BA=20=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=20URL=20=D0=B8=20?= =?UTF-8?q?=D0=BE=D1=87=D0=B8=D1=81=D1=82=D0=BA=D0=B0=20=D0=BF=D1=83=D1=81?= =?UTF-8?q?=D1=82=D1=8B=D1=85=20=D1=81=D1=82=D1=80=D0=BE=D0=BA.=20=D0=92?= =?UTF-8?q?=D0=BD=D0=B5=D0=B4=D1=80=D0=B5=D0=BD=D1=8B=20=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D1=8B=D0=B5=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D1=83=D0=BB=D1=83=D1=87?= =?UTF-8?q?=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D1=81=D0=BA=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9?= =?UTF-8?q?=D1=81=D0=B0=20=D0=B8=20=D0=B2=D0=B7=D0=B0=D0=B8=D0=BC=D0=BE?= =?UTF-8?q?=D0=B4=D0=B5=D0=B9=D1=81=D1=82=D0=B2=D0=B8=D1=8F,=20=D0=B0=20?= =?UTF-8?q?=D1=82=D0=B0=D0=BA=D0=B6=D0=B5=20=D1=83=D0=BB=D1=83=D1=87=D1=88?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=B0=D0=BB=D0=B8=D0=B4=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B8=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/AutoUrlManager.jsx | 238 ++++++++++++++++++-------------- 1 file changed, 134 insertions(+), 104 deletions(-) diff --git a/frontend/src/AutoUrlManager.jsx b/frontend/src/AutoUrlManager.jsx index 717262b..d79e437 100644 --- a/frontend/src/AutoUrlManager.jsx +++ b/frontend/src/AutoUrlManager.jsx @@ -13,6 +13,11 @@ import { IconCircleCheck, IconCopy } from '@tabler/icons-react'; +import PageHeader from './components/PageHeader.jsx'; +import PageHeaderActions from './components/PageHeaderActions.jsx'; +import TableSkeleton, { TableEmpty } from './components/TableSkeleton.jsx'; +import EmptyState from './components/EmptyState.jsx'; +import ImportModal from './components/ImportModal.jsx'; function AutoUrlManager() { const [urls, setUrls] = useState([]); @@ -22,6 +27,7 @@ function AutoUrlManager() { const [message, setMessage] = useState(''); const [messageType, setMessageType] = useState(''); const [touched, setTouched] = useState({}); + const [importOpen, setImportOpen] = useState(false); useEffect(() => { fetchUrls(); @@ -45,6 +51,10 @@ function AutoUrlManager() { setUrls([...urls, { url: '', community: '' }]); }; + const clearEmptyRows = () => { + setUrls(urls.filter(u => u != null && (u.url || u.community))); + }; + const removeUrl = (index) => { setUrls(urls.filter((_, i) => i !== index)); }; @@ -144,24 +154,83 @@ function AutoUrlManager() { } }; - if (loading) { - return ( -
-
-
- ); - } - return (
-
-
-
-

Автоматические URL

-
Управление автоматическими URL-адресами для загрузки списков IP и доменов
+ +
+ + +
+
+ + + +
-
-
+ )} + /> {message && (
@@ -174,53 +243,36 @@ function AutoUrlManager() { )}
-
-

URL-адреса для автоматической загрузки

-
-
- - -
-
-
- {urls.length === 0 ? ( -
- -

Нет добавленных URL-адресов

- -
+ {loading ? ( + + ) : urls.length === 0 ? ( + + + Добавить первый URL + + )} + secondaryAction={( + + )} + /> ) : (
@@ -299,49 +351,8 @@ function AutoUrlManager() { Всего URL-адресов: {urls.length} )} -
- - - +
+ Введите http/https URL и числовой community. Не валидные поля подсвечиваются.
@@ -405,6 +416,25 @@ function AutoUrlManager() { + + {/* Модальное окно импорта */} + { + const [u, c] = String(line).split(/\s+/); + return { url: u || '', community: c || '' }; + }} + validateItem={(obj) => Boolean(obj?.url) && Boolean(obj?.community)} + onConfirm={(items) => { + setUrls(prev => [...prev, ...items]); + setImportOpen(false); + }} + onClose={() => setImportOpen(false)} + /> ); }