feat(NetworkConfigManager, GatewayAutocompleteInput): add serverId handling for gateway filtering, enhancing configuration accuracy and user experience
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m2s

This commit is contained in:
2026-01-25 21:06:15 +07:00
parent d583757882
commit c7ebe0943b
2 changed files with 38 additions and 8 deletions
+10 -4
View File
@@ -583,6 +583,7 @@ function NetworkConfigManager() {
ip: ip,
description: gw.description || '',
country: gw.country || '',
serverId: templateServerId, // Сохраняем serverId для фильтрации
parentGateways: gw.parentGateways ? [...gw.parentGateways] : [],
};
});
@@ -595,11 +596,14 @@ function NetworkConfigManager() {
const updatedGateways = templateGateways.map((gw, index) => {
const originalTemplate = selectedTemplate.gateways[index];
// Обновляем serverId для всех gateways при изменении сервера
const updatedGateway = { ...gw, serverId: templateServerId };
// Для прямых gateways используем IP сервера
if (gw.type === 'direct' && templateServerId) {
const server = getServerInfo(templateServerId);
if (server && server.ip) {
return { ...gw, ip: server.ip };
return { ...updatedGateway, ip: server.ip };
}
}
// Для рекурсивных gateways генерируем из базового IP
@@ -614,14 +618,14 @@ function NetworkConfigManager() {
// Если IP пустой или последний октет совпадает с шаблоном, обновляем
if (!gw.ip || (currentIpParts.length === 4 && templateIpParts.length === 4 &&
currentIpParts[3] === templateIpParts[3])) {
return { ...gw, ip: templateIp };
return { ...updatedGateway, ip: templateIp };
}
}
}
return gw;
return updatedGateway;
});
// Обновляем только если есть изменения
const hasChanges = updatedGateways.some((gw, i) => gw.ip !== templateGateways[i]?.ip);
const hasChanges = updatedGateways.some((gw, i) => gw.ip !== templateGateways[i]?.ip || gw.serverId !== templateGateways[i]?.serverId);
if (hasChanges) {
setTemplateGateways(updatedGateways);
}
@@ -3886,6 +3890,7 @@ function NetworkConfigManager() {
}}
gateways={config.gateways}
interfaces={config.tunnelInterfaces}
serverId={editingGateway.serverId}
excludeGatewayId={editingGateway.id}
placeholder="Выберите родительский gateway или интерфейс..."
/>
@@ -5318,6 +5323,7 @@ function NetworkConfigManager() {
gateways={config.gateways}
interfaces={config.tunnelInterfaces}
templateGateways={templateGateways}
serverId={templateServerId}
excludeGatewayId={gw.id}
placeholder="Выберите родительский gateway или интерфейс..."
/>
@@ -11,6 +11,7 @@ function GatewayAutocompleteInput({
gateways = [],
interfaces = [],
templateGateways = [], // Gateways из шаблона, которые еще не созданы
serverId = null, // ID сервера для фильтрации интерфейсов и gateways
excludeGatewayId = null, // ID gateway, который нужно исключить (текущий редактируемый)
placeholder = '',
className = 'form-control',
@@ -27,8 +28,15 @@ function GatewayAutocompleteInput({
const items = [];
// Добавляем прямые gateway из шаблона (которые еще не созданы)
// Фильтруем по serverId, если указан
templateGateways
.filter(g => g.id !== excludeGatewayId && g.type === 'direct' && g.ip)
.filter(g => {
if (g.id === excludeGatewayId) return false;
if (g.type !== 'direct' || !g.ip) return false;
// Если указан serverId, фильтруем по нему
if (serverId && g.serverId !== serverId) return false;
return true;
})
.forEach(g => {
items.push({
type: 'gateway',
@@ -43,8 +51,15 @@ function GatewayAutocompleteInput({
});
// Добавляем прямые gateway (уже созданные)
// Фильтруем по serverId, если указан
gateways
.filter(g => g.id !== excludeGatewayId && g.type === 'direct' && g.ip)
.filter(g => {
if (g.id === excludeGatewayId) return false;
if (g.type !== 'direct' || !g.ip) return false;
// Если указан serverId, фильтруем по нему
if (serverId && g.serverId !== serverId) return false;
return true;
})
.forEach(g => {
items.push({
type: 'gateway',
@@ -59,8 +74,17 @@ function GatewayAutocompleteInput({
});
// Добавляем интерфейсы
// Фильтруем по serverId, если указан (интерфейс должен принадлежать серверу)
interfaces
.filter(i => i.remoteIp)
.filter(i => {
if (!i.remoteIp) return false;
// Если указан serverId, фильтруем интерфейсы, которые принадлежат этому серверу
if (serverId) {
// Интерфейс принадлежит серверу, если serverId === i.serverId или serverId === i.serverId2
return i.serverId === serverId || i.serverId2 === serverId;
}
return true;
})
.forEach(i => {
items.push({
type: 'interface',
@@ -75,7 +99,7 @@ function GatewayAutocompleteInput({
});
return items;
}, [gateways, interfaces, templateGateways, excludeGatewayId]);
}, [gateways, interfaces, templateGateways, excludeGatewayId, serverId]);
const suggestions = useMemo(() => {
const q = String(value || '').toLowerCase();