feat(SettingsModal): enhance server selection for ping services with autocomplete input and load server list from API
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m58s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m58s
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import FormField from './FormField';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useState, useMemo } from 'react';
|
||||
import api from '../lib/api.js';
|
||||
import { IconSettings, IconDeviceFloppy } from '@tabler/icons-react';
|
||||
import ErrorAlert from './ErrorAlert';
|
||||
import ServerAutocompleteInput from './ServerAutocompleteInput.jsx';
|
||||
|
||||
/**
|
||||
* SettingsModal - модальное окно настроек интерфейса
|
||||
@@ -25,17 +26,27 @@ export default function SettingsModal({ open, onClose }) {
|
||||
const [pingServicesSource, setPingServicesSource] = useState('web');
|
||||
const [pingServicesServerId, setPingServicesServerId] = useState('');
|
||||
const [pingServicesGatewayIp, setPingServicesGatewayIp] = useState('');
|
||||
const [serversList, setServersList] = useState([]);
|
||||
|
||||
const routerServersForPing = useMemo(() => {
|
||||
return (serversList || []).filter(
|
||||
(s) => s && (String(s.type || '').toLowerCase() === 'jumphost' || String(s.type || '').toLowerCase() === 'home')
|
||||
);
|
||||
}, [serversList]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
setError('');
|
||||
setSuccess('');
|
||||
setLoading(true);
|
||||
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const res = await api.get('/ui-settings');
|
||||
const data = res?.data || {};
|
||||
const [settingsRes, serversRes] = await Promise.all([
|
||||
api.get('/ui-settings'),
|
||||
api.get('/servers').catch(() => ({ data: [] })),
|
||||
]);
|
||||
const data = settingsRes?.data || {};
|
||||
setRawSettings(data);
|
||||
setDohServer(String(data?.dohServer || ''));
|
||||
setWsUrl(String(data?.wsUpdateUrl || ''));
|
||||
@@ -47,8 +58,9 @@ export default function SettingsModal({ open, onClose }) {
|
||||
setPingServicesSource(String(data?.pingServicesSource || 'web').toLowerCase() === 'router' ? 'router' : 'web');
|
||||
setPingServicesServerId(String(data?.pingServicesServerId || '').trim());
|
||||
setPingServicesGatewayIp(String(data?.pingServicesGatewayIp || '').trim());
|
||||
const e = res?.headers?.etag || res?.headers?.ETag || '';
|
||||
const e = settingsRes?.headers?.etag || settingsRes?.headers?.ETag || '';
|
||||
setEtag(e ? String(e) : '');
|
||||
setServersList(Array.isArray(serversRes?.data) ? serversRes.data : []);
|
||||
} catch (e) {
|
||||
setError('Не удалось загрузить настройки');
|
||||
} finally {
|
||||
@@ -256,26 +268,30 @@ export default function SettingsModal({ open, onClose }) {
|
||||
{pingServicesSource === 'router' && (
|
||||
<div className="row g-2">
|
||||
<div className="col-md-6">
|
||||
<FormField
|
||||
label="Роутер (jumphost)"
|
||||
name="pingServicesServerId"
|
||||
type="text"
|
||||
value={pingServicesServerId}
|
||||
onChange={setPingServicesServerId}
|
||||
placeholder="ID, DNS или IP jumphost"
|
||||
helpText="Оставьте пустым — будет использован первый jumphost из списка серверов."
|
||||
disabled={loading || saving}
|
||||
/>
|
||||
<label className="form-label small">Домашний роутер</label>
|
||||
<div className={loading || saving ? 'opacity-75 pe-none' : ''}>
|
||||
<ServerAutocompleteInput
|
||||
value={pingServicesServerId}
|
||||
onChange={(v) => setPingServicesServerId(String(v || '').trim())}
|
||||
servers={routerServersForPing}
|
||||
placeholder="Выберите роутер (jumphost или входной)"
|
||||
className="form-control form-control-sm"
|
||||
maxSuggestions={10}
|
||||
/>
|
||||
</div>
|
||||
<div className="form-text small">
|
||||
Выбор роутера с MikroTik API для пинга с главной. Пусто — первый jumphost из списка.
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<FormField
|
||||
label="IP шлюза (опционально)"
|
||||
label="IP шлюза (не обязательно)"
|
||||
name="pingServicesGatewayIp"
|
||||
type="text"
|
||||
value={pingServicesGatewayIp}
|
||||
onChange={setPingServicesGatewayIp}
|
||||
placeholder="IP шлюза"
|
||||
helpText="Оставьте пустым — берётся первый шлюз роутера."
|
||||
helpText="Не обязательно. Пусто — используется первый шлюз выбранного роутера."
|
||||
disabled={loading || saving}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user