feat: Implement server filter updates in EasySwitchManager with success and error notifications, enhancing user feedback and improving error handling during filter application.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m4s

This commit is contained in:
2025-12-07 13:09:02 +07:00
parent 4a3426e04f
commit cb32b1bd71
+105 -8
View File
@@ -26,6 +26,7 @@ const countryToFlag = (code) => {
function EasySwitchManager() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [success, setSuccess] = useState('');
// Серверы и фильтры
const [servers, setServers] = useState([]);
@@ -175,10 +176,93 @@ function EasySwitchManager() {
};
const handleApplyChanges = async () => {
// TODO: Реализовать сохранение изменений на сервер
console.log('Applying changes:', activeGateways);
setHasChanges(false);
// Здесь можно добавить логику обновления фильтров на серверах
setLoading(true);
setError('');
try {
// Группируем изменения по serverId
const changesByServer = new Map();
Object.entries(activeGateways).forEach(([key, gateway]) => {
const [serverId, community] = key.split(':');
if (!changesByServer.has(serverId)) {
changesByServer.set(serverId, new Map());
}
changesByServer.get(serverId).set(community, gateway);
});
// Обновляем фильтры для каждого сервера
const updatePromises = Array.from(changesByServer.entries()).map(async ([serverId, communitiesMap]) => {
try {
// Получаем текущие фильтры сервера
const response = await api.get(`/server-filters/${serverId}`);
const currentFilters = Array.isArray(response.data) ? response.data : [];
// Создаем Set существующих communities в фильтрах
const existingCommunitiesSet = new Set(currentFilters.map(f => f.community));
// Обновляем существующие фильтры и добавляем новые
const updatedFilters = [];
const processedCommunities = new Set();
// Обновляем существующие
currentFilters.forEach(filter => {
const newGateway = communitiesMap.get(filter.community);
if (newGateway) {
updatedFilters.push({
...filter,
gateway: newGateway
});
processedCommunities.add(filter.community);
} else {
updatedFilters.push(filter);
}
});
// Добавляем новые фильтры для communities, которых не было
communitiesMap.forEach((gateway, community) => {
if (!processedCommunities.has(community)) {
// Находим описание из справочника
const commInfo = communitiesDirectory.find(c => c.value === community);
updatedFilters.push({
community: community,
gateway: gateway,
description: commInfo?.name || commInfo?.description || ''
});
}
});
// Сохраняем обновленные фильтры
await api.post(`/server-filters/${serverId}`, { filters: updatedFilters });
return { serverId, success: true };
} catch (error) {
console.error(`Error updating filters for ${serverId}:`, error);
return { serverId, success: false, error };
}
});
const results = await Promise.all(updatePromises);
const successCount = results.filter(r => r.success).length;
const errorCount = results.filter(r => !r.success).length;
if (errorCount === 0) {
setHasChanges(false);
setSuccess(`✅ Изменения успешно применены для ${successCount} ${successCount === 1 ? 'сервера' : 'серверов'}`);
setTimeout(() => setSuccess(''), 3000);
// Перезагружаем данные чтобы обновить бейджи "настроен"
await handleRefresh();
} else {
setError(`Не удалось обновить ${errorCount} ${errorCount === 1 ? 'сервер' : 'серверов'}. Успешно: ${successCount}.`);
setTimeout(() => setError(''), 5000);
}
} catch (err) {
console.error('Error applying changes:', err);
setError('Ошибка при применении изменений. Проверьте подключение к серверу.');
} finally {
setLoading(false);
}
};
const handleRefresh = async () => {
@@ -322,11 +406,24 @@ function EasySwitchManager() {
</ul>
</div>
{/* Ошибки */}
{/* Уведомления */}
{error && (
<div className="alert alert-danger d-flex align-items-center" role="alert">
<IconAlertCircle className="me-2" />
<div>{error}</div>
<div className="alert alert-danger alert-dismissible" role="alert">
<div className="d-flex">
<IconAlertCircle className="me-2" />
<div>{error}</div>
</div>
<button type="button" className="btn-close" onClick={() => setError('')}></button>
</div>
)}
{success && (
<div className="alert alert-success alert-dismissible" role="alert">
<div className="d-flex">
<IconCheck className="me-2" />
<div>{success}</div>
</div>
<button type="button" className="btn-close" onClick={() => setSuccess('')}></button>
</div>
)}