diff --git a/frontend/src/FilterManager.jsx b/frontend/src/FilterManager.jsx index 38a1f6b..66296bf 100644 --- a/frontend/src/FilterManager.jsx +++ b/frontend/src/FilterManager.jsx @@ -65,18 +65,14 @@ function FilterManager() { const [editingServer, setEditingServer] = useState(null); const [editServerError, setEditServerError] = useState(''); - // Новое состояние для режима - const [mode, setMode] = useState('advanced'); // 'simple' | 'advanced' - const [simpleFilters, setSimpleFilters] = useState([]); - const [simpleAddFilter, setSimpleAddFilter] = useState({ community: '', gateway: '', description: '' }); - const [simpleError, setSimpleError] = useState(''); - const [simpleSuccess, setSimpleSuccess] = useState(''); - const [simpleLoading, setSimpleLoading] = useState(false); - - // Состояние поиска/сортировки в расширенном режиме + // Состояние поиска/сортировки const [filterSearch, setFilterSearch] = useState(''); const [sortBy, setSortBy] = useState('community'); // community | gateway | description const [sortDir, setSortDir] = useState('asc'); // asc | desc + + // Состояние sidebar + const [sidebarCollapsed, setSidebarCollapsed] = useState(false); + const [serverSearch, setServerSearch] = useState(''); // Состояние для инлайн-редактирования и массовых действий const [editingKey, setEditingKey] = useState(null); @@ -104,7 +100,6 @@ function FilterManager() { useEffect(() => { fetchServers(); - fetchSimpleFilters(); }, []); // Загружаем фильтры при выборе сервера @@ -142,18 +137,6 @@ function FilterManager() { } }; - const fetchSimpleFilters = async () => { - setSimpleLoading(true); - try { - const response = await api.get(`/simple-filters`); - setSimpleFilters(response.data); - } catch (error) { - console.error('Error fetching simple filters:', error); - setSimpleFilters([]); - } finally { - setSimpleLoading(false); - } - }; const handleAddServer = async () => { if (!newServer.name.trim()) { @@ -606,19 +589,15 @@ function FilterManager() { } }; - // Состояние для поиска - const [searchTerm, setSearchTerm] = useState(''); - // Фильтрация серверов по поиску const filteredServers = servers.filter(server => - server.name.toLowerCase().includes(searchTerm.toLowerCase()) || - (server.description && server.description.toLowerCase().includes(searchTerm.toLowerCase())) + server.name.toLowerCase().includes(serverSearch.toLowerCase()) || + (server.description && server.description.toLowerCase().includes(serverSearch.toLowerCase())) ); - - // Статистика - const totalServers = servers.length; - const enabledServers = servers.filter(s => s.enabled).length; - const serversWithFilters = servers.filter(s => s.id === selectedServer?.id ? serverFilters.length > 0 : false).length; + + // Разделение серверов на активные и неактивные + const activeServers = filteredServers.filter(s => s.enabled); + const inactiveServers = filteredServers.filter(s => !s.enabled); // Преобразованные фильтры для таблицы (поиск + сортировка) const processedFilters = (() => { @@ -737,466 +716,248 @@ function FilterManager() { } }; - // Функция для применения фильтров из упрощённого режима на все сервера - const handleDeploySimpleFiltersToAll = async () => { - if (servers.length === 0) { - setSimpleError('Нет серверов для применения фильтров.'); - return; - } - if (simpleFilters.length === 0) { - setSimpleError('Нет фильтров для применения.'); - return; - } - setSimpleLoading(true); - try { - // Копируем фильтры и генерируем конфиг для каждого сервера - for (const server of servers) { - await api.post(`/server-filters/${server.id}`, { filters: simpleFilters }); - // Генерируем конфиг - const response = await api.post(`/server-filters/generate-config`, { filters: simpleFilters }); - if (response.data && response.data.config) { - await api.post(`/server-configs/${server.id}`, { config: response.data.config }); - } - } - setSimpleSuccess('Фильтры и конфигурация успешно применены ко всем серверам!'); - setTimeout(() => setSimpleSuccess(''), 4000); - } catch (error) { - setSimpleError('Ошибка при применении фильтров: ' + (error.response?.data || error.message)); - } finally { - setSimpleLoading(false); - } - }; - - // Функции для работы с фильтрами в упрощённом режиме - const handleSimpleAddFilter = async () => { - if (!simpleAddFilter.community.trim() || !simpleAddFilter.gateway.trim()) { - setSimpleError('Поля Community и Gateway должны быть заполнены.'); - return; - } - const updatedFilters = [...simpleFilters, { ...simpleAddFilter }]; - setSimpleFilters(updatedFilters); - setSimpleAddFilter({ community: '', gateway: '', description: '' }); - setSimpleError(''); - - // Сохраняем фильтры - try { - await api.post(`/simple-filters`, { filters: updatedFilters }); - setSimpleSuccess('Фильтр успешно добавлен!'); - setTimeout(() => setSimpleSuccess(''), 3000); - } catch (error) { - console.error('Error saving simple filters:', error); - setSimpleError('Не удалось сохранить фильтр.'); - } - }; - - const handleSimpleDeleteFilter = async (filter) => { - const updatedFilters = simpleFilters.filter(f => f !== filter); - setSimpleFilters(updatedFilters); - - // Сохраняем фильтры - try { - await api.post(`/simple-filters`, { filters: updatedFilters }); - setSimpleSuccess('Фильтр успешно удален!'); - setTimeout(() => setSimpleSuccess(''), 3000); - } catch (error) { - console.error('Error saving simple filters:', error); - setSimpleError('Не удалось удалить фильтр.'); - } - }; - - const handleSimpleEditFilter = async (index, field, value) => { - const updated = [...simpleFilters]; - updated[index][field] = value; - setSimpleFilters(updated); - - // Сохраняем фильтры - try { - await api.post(`/simple-filters`, { filters: updated }); - } catch (error) { - console.error('Error saving simple filters:', error); - setSimpleError('Не удалось сохранить изменения.'); - } - }; return ( -
-
-
-
-

Управление фильтрами frouting

-
Главная / Фильтры
+
+ {/* Боковая панель для выбора сервера */} + {!sidebarCollapsed && ( + + )} + + {/* Кнопка для разворачивания боковой панели */} + {sidebarCollapsed && ( +
+ +
+ )} + + {/* Основной контент */} +
+
+
+
+
+

+ Управление фильтрами frouting +

+
+ +
+
{selectedServer && ( - <> - - - - +
+
+ + + +
+
)}
-
- {/* Уведомления */} - {error && ( -
- - {error} - -
- )} - {success && ( -
- - {success} - -
- )} +
+
+ {/* Уведомления */} + {error && ( +
+ + {error} + +
+ )} + {success && ( +
+ + {success} + +
+ )} - {/* Панель статистики */} - {mode === 'advanced' && ( -
-
-
-
-
-
- - - -
-
-
{totalServers}
-
Всего серверов
-
+ {/* Пустое состояние - выбор сервера */} + {!selectedServer ? ( +
+
+
-
-
-
-
-
-
-
-
- - - -
-
-
{enabledServers}
-
Активных серверов
-
-
-
-
-
-
-
-
-
-
- - - -
-
-
{selectedServer ? serverFilters.length : '-'}
-
- {selectedServer ? 'Фильтров в выбранном сервере' : 'Выберите сервер'} -
-
-
-
-
-
-
-
-
-
-
- - - -
-
-
- {!selectedServer ? 'Не выбран' : serverFilters.length > 0 ? 'Готов' : 'Не готов'} -
-
Статус конфигурации
-
-
-
-
-
-
- )} - - {/* Секция управления серверами */} - {mode === 'advanced' && ( -
-
-
-
-

- - Готовые конфигурации серверов -

-
-
- - - - setSearchTerm(e.target.value)} - /> +

Выберите сервер

+

+ Выберите сервер из списка слева для управления его фильтрами +

+ {servers.length === 0 && ( +
-
-
-
-
- {servers.length === 0 ? ( -
- -

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

-
- ) : filteredServers.length === 0 ? ( -
- -

Серверы не найдены по запросу "{searchTerm}"

- -
- ) : ( -
- {filteredServers.map(server => ( -
-
-
-
-
-

- {server.name} - {selectedServer?.id === server.id && ( - Выбран - )} -

-
- - {server.enabled ? 'Активен' : 'Неактивен'} - - {server.id === selectedServer?.id && ( - - {serverFilters.length} фильтров - - )} -
-
-
- { - const updatedServers = servers.map(s => - s.id === server.id ? { ...s, enabled: !s.enabled } : s - ); - try { - await api.post(`/server-configs`, { servers: updatedServers }); - setServers(updatedServers); - } catch (error) { - setError('Не удалось обновить статус сервера'); - } - }} - /> -
-
- - {server.description && ( -

{server.description}

- )} - -
- - - - -
-
-
-
- ))} -
)}
-
-
-
- )} + ) : null} - {/* Секция фильтров выбранного сервера */} - {selectedServer && ( -
-
-
-
-
-
-

- - Фильтры сервера: {selectedServer.name} - - {serverFilters.length} фильтров - -

-
- Управление фильтрами community/gateway для генерации конфигурации MikroTik -
-
-
-
- - - + {/* Секция фильтров выбранного сервера */} + {selectedServer && ( +
+
+

+ + Фильтры сервера: {selectedServer.name} + + {serverFilters.length} + +

+
+
setFilterSearch(e.target.value)} /> - {filterSearch && ( - - )} -
-
-
-
- - - - - {serverFilters.length > 0 && ( - - )} + + +
+
-
{loading ? (
@@ -1368,13 +1129,14 @@ function FilterManager() {
)} - - )} + + )} +
-
+ )}
- )} +
{/* Модальные окна */} - {/* Модальное окно упрощённого режима */} -
- {mode === 'simple' ? ( - - ) : ( - - )} -
- {mode === 'simple' ? ( -
-
-
-
-

- Фильтры (упрощённый режим) -

-
- Управление фильтрами community/gateway для всех серверов -
-
-
-
- {simpleFilters.length} фильтров -
-
-
-
-
- {simpleError && ( -
{simpleError}
- )} - {simpleSuccess && ( -
{simpleSuccess}
- )} -
- - - - - - - - - - - {simpleLoading ? ( - - - - ) : simpleFilters.length === 0 ? ( - - ) : ( - simpleFilters.filter(f => f != null).map((filter, idx) => ( - - - - - - - )) - )} - -
COMMUNITYGATEWAYОПИСАНИЕДЕЙСТВИЯ
-
- Загрузка... -
- Загрузка фильтров... -
Нет фильтров
- handleSimpleEditFilter(idx, 'community', e.target.value)} - /> - - handleSimpleEditFilter(idx, 'gateway', e.target.value)} - /> - - handleSimpleEditFilter(idx, 'description', e.target.value)} - /> - - -
-
-
-
- setSimpleAddFilter({ ...simpleAddFilter, community: e.target.value })} - /> -
-
- setSimpleAddFilter({ ...simpleAddFilter, gateway: e.target.value })} - /> -
-
- setSimpleAddFilter({ ...simpleAddFilter, description: e.target.value })} - /> -
-
- -
-
-
- - - - - {simpleFilters.length > 0 && ( - - )} -
-
-
- ) : ( - // ... существующий расширенный режим ... - <> - {/* Панель статистики */} - {/* Секция управления серверами */} - {/* ... всё как было ... */} - - )}