feat(FilterManager): синхронизация с jumphost'ами из раздела Серверы
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m46s

This commit is contained in:
2026-01-20 14:56:42 +07:00
parent 660513aee6
commit 549c695117
+47 -27
View File
@@ -1,4 +1,5 @@
import { useState, useEffect, useRef } from 'react';
import { Link } from 'react-router-dom';
import api from './lib/api.js';
import ConfirmDialog from './components/ConfirmDialog.jsx';
import FormModal from './components/FormModal.jsx';
@@ -716,14 +717,32 @@ function FilterManager() {
};
// Функции для управления серверами
// Загружаем jumphost'ы из раздела "Серверы" (/api/servers)
const fetchServers = async () => {
try {
const response = await api.get(`/server-configs`);
const payload = Array.isArray(response.data) ? response.data : [];
setServers(payload.map(s => ({ ...s, gateways: normalizeGateways(s.gateways, s.name) })));
const response = await api.get(`/servers`);
const allServers = Array.isArray(response.data) ? response.data : [];
// Фильтруем только jumphost'ы (не exit-ноды)
const jumphosts = allServers
.filter(s => s.type !== 'exit')
.map(s => ({
id: s.id || s.ip, // Используем id или ip как идентификатор
name: s.dns?.split('.')[0] || s.ip, // Короткое имя из DNS или IP
fullName: s.dns || s.ip,
description: `${s.provider || ''} ${s.country || ''}`.trim(),
enabled: true,
ip: s.ip,
dns: s.dns,
country: s.country,
provider: s.provider,
tunnel: s.tunnel,
gateways: normalizeGateways(s.gateways, s.dns?.split('.')[0] || s.ip)
}));
setServers(jumphosts);
} catch (error) {
console.error('Error fetching servers:', error);
// Если файл не существует, создаем пустой массив
setServers([]);
}
};
@@ -1435,13 +1454,13 @@ function FilterManager() {
)}
</h3>
<div className="card-actions">
<button
<Link
to="/servers"
className="btn btn-outline-primary btn-sm"
onClick={() => setServerConfigModalOpen(true)}
>
<IconPlus className="icon" />
Добавить сервер
</button>
<IconSettings className="icon" />
Управление серверами
</Link>
</div>
</div>
<div className="card-body">
@@ -1450,18 +1469,18 @@ function FilterManager() {
<div className="empty-icon">
<IconServer size={48} className="text-muted" />
</div>
<p className="empty-title">Нет серверов</p>
<p className="empty-title">Нет jumphost серверов</p>
<p className="empty-subtitle text-muted">
Создайте первый сервер для работы с фильтрами
Добавьте серверы типа JUMP в разделе "Серверы"
</p>
<div className="empty-action">
<button
<Link
to="/servers"
className="btn btn-primary"
onClick={() => setServerConfigModalOpen(true)}
>
<IconPlus className="icon" />
Добавить первый сервер
</button>
<IconServer className="icon" />
Перейти к серверам
</Link>
</div>
</div>
) : (
@@ -2121,17 +2140,18 @@ function FilterManager() {
title="Управление серверами"
size="xl"
>
<div className="mb-3">
<button
<div className="mb-3 d-flex justify-content-between align-items-center">
<p className="text-muted mb-0">
Серверы автоматически синхронизируются из раздела "Серверы" (только JUMP)
</p>
<Link
to="/servers"
className="btn btn-primary"
onClick={() => {
setServerListModalOpen(false);
setServerConfigModalOpen(true);
}}
onClick={() => setServerListModalOpen(false)}
>
<IconPlus className="icon" />
Добавить сервер
</button>
<IconSettings className="icon" />
Управление серверами
</Link>
</div>
{servers.length === 0 ? (
@@ -2139,9 +2159,9 @@ function FilterManager() {
<div className="empty-icon">
<IconServer size={48} />
</div>
<p className="empty-title">Нет серверов</p>
<p className="empty-title">Нет jumphost серверов</p>
<p className="empty-subtitle text-muted">
Создайте первый сервер для работы с фильтрами
Добавьте серверы типа JUMP в разделе "Серверы"
</p>
</div>
) : (