From e0c7ec32d637fd58924e70320ccd638345f64e0f Mon Sep 17 00:00:00 2001 From: shats Date: Tue, 17 Feb 2026 15:56:17 +0700 Subject: [PATCH] feat(SettingsPage, TrafficDashboard): add traffic interface settings and filtering for enhanced analytics functionality --- frontend/src/SettingsPage.jsx | 47 +++++++++++++++++++++++++++++++ frontend/src/TrafficDashboard.jsx | 35 ++++++++++++++++++++--- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/frontend/src/SettingsPage.jsx b/frontend/src/SettingsPage.jsx index ca2538f..217ec91 100644 --- a/frontend/src/SettingsPage.jsx +++ b/frontend/src/SettingsPage.jsx @@ -10,6 +10,7 @@ import { IconChartPie, IconWorld, IconSearch, + IconChartBar, } from '@tabler/icons-react'; import FormField from './components/FormField'; import ErrorAlert from './components/ErrorAlert'; @@ -42,6 +43,12 @@ const SIDEBAR_GROUPS = [ { id: 'ptr-zone', title: 'PTR зона', icon: IconWorld }, ], }, + { + title: 'Аналитика', + items: [ + { id: 'traffic-interfaces', title: 'Настройка Аналитики', icon: IconChartBar }, + ], + }, ]; const SIDEBAR_SECTIONS = SIDEBAR_GROUPS.flatMap((g) => g.items); @@ -65,6 +72,7 @@ export default function SettingsPage() { const [pingServicesServerId, setPingServicesServerId] = useState(''); const [pingServicesGatewayIp, setPingServicesGatewayIp] = useState(''); const [pingServicesCacheSeconds, setPingServicesCacheSeconds] = useState(''); + const [trafficInterfaceNames, setTrafficInterfaceNames] = useState(''); const [serversList, setServersList] = useState([]); const [sidebarSearch, setSidebarSearch] = useState(''); const [activeSection, setActiveSection] = useState(() => { @@ -141,6 +149,14 @@ export default function SettingsPage() { ? String(data.pingServicesCacheSeconds) : '' ); + const rawNames = data?.trafficInterfaceNames; + setTrafficInterfaceNames( + Array.isArray(rawNames) + ? rawNames.filter((n) => n != null).map(String).join(', ') + : typeof rawNames === 'string' + ? rawNames + : '' + ); const e = settingsRes?.headers?.etag || settingsRes?.headers?.ETag || ''; setEtag(e ? String(e) : ''); @@ -213,6 +229,10 @@ export default function SettingsPage() { 0, parseInt(pingServicesCacheSeconds, 10) || 0 ), + trafficInterfaceNames: (trafficInterfaceNames || '') + .split(/[\n,]+/) + .map((s) => s.trim()) + .filter(Boolean), }; const payload = { settings: mergedSettings, etag }; const res = await api.post('/ui-settings', payload); @@ -532,6 +552,33 @@ export default function SettingsPage() { )} + + {activeSection === 'traffic-interfaces' && ( + <> + +

+ Укажите, какие интерфейсы учитывать на странице Расход трафика. + Пустое поле — учитываются все интерфейсы. Имена можно перечислить через запятую или с новой строки. +

+
+
+ +