From 46f00afb7d09b7e932f2a8e79ac1cb50840daf2b Mon Sep 17 00:00:00 2001 From: Ochenstarik Date: Thu, 16 Jul 2026 19:13:44 +0700 Subject: [PATCH] Add server profile editing and deletion --- docs/roadmap.md | 4 +- .../MainPage.xaml | 10 ++ .../MainPage.xaml.cs | 98 +++++++++++++++++++ 3 files changed, 110 insertions(+), 2 deletions(-) diff --git a/docs/roadmap.md b/docs/roadmap.md index e7e9885..4bc7e04 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -18,8 +18,8 @@ - [x] сохранять профили локально без паролей; - [x] получать CPU/load, RAM, disk, uptime и latency; - [x] собрать и реально запустить x64-приложение; -- [ ] редактирование и удаление серверов; -- [ ] единственный изменяемый Hub; +- [x] редактирование и удаление серверов; +- [x] единственный изменяемый Hub; - [ ] настоящие страницы Servers, Links, Sessions и Settings. ## Этап 2 — установщик Hub/Node diff --git a/src/ServerMonitorManager.Desktop/MainPage.xaml b/src/ServerMonitorManager.Desktop/MainPage.xaml index d37793a..687b736 100644 --- a/src/ServerMonitorManager.Desktop/MainPage.xaml +++ b/src/ServerMonitorManager.Desktop/MainPage.xaml @@ -79,6 +79,16 @@ Click="AddServerButton_Click" Icon="Add" Label="Добавить сервер" /> + + diff --git a/src/ServerMonitorManager.Desktop/MainPage.xaml.cs b/src/ServerMonitorManager.Desktop/MainPage.xaml.cs index a3f1b50..2dff0cf 100644 --- a/src/ServerMonitorManager.Desktop/MainPage.xaml.cs +++ b/src/ServerMonitorManager.Desktop/MainPage.xaml.cs @@ -154,6 +154,11 @@ public sealed partial class MainPage : Page { return; } + if (hubBox.IsChecked == true && Servers.Any(server => server.IsHub)) + { + ShowInfo("Hub уже выбран", "Измените существующий Hub или снимите эту отметку.", InfoBarSeverity.Warning); + return; + } var profile = new ServerProfileData( Guid.NewGuid().ToString("N"), @@ -169,6 +174,99 @@ public sealed partial class MainPage : Page await RefreshServerAsync(server); } + private async void EditServerButton_Click(object sender, RoutedEventArgs e) + { + if (ServerList.SelectedItem is not ServerViewModel selected) + { + ShowInfo("Сервер не выбран", "Выберите сервер в списке для изменения.", InfoBarSeverity.Warning); + return; + } + + var nameBox = new TextBox { Header = "Название", Text = selected.Profile.Name }; + var hostBox = new TextBox { Header = "IP или домен", Text = selected.Profile.Host }; + var portBox = new NumberBox + { + Header = "SSH-порт", + Value = selected.Profile.Port, + Minimum = 1, + Maximum = 65535, + SpinButtonPlacementMode = NumberBoxSpinButtonPlacementMode.Compact + }; + var userBox = new TextBox { Header = "Пользователь", Text = selected.Profile.User }; + var hubBox = new CheckBox { Content = "Это главный Mesh Hub", IsChecked = selected.IsHub }; + AutomationProperties.SetName(hubBox, "Использовать сервер как главный Mesh Hub"); + var dialog = new ContentDialog + { + XamlRoot = XamlRoot, + Title = "Изменить сервер", + Content = new StackPanel + { + Spacing = 12, + MinWidth = 420, + Children = { nameBox, hostBox, portBox, userBox, hubBox } + }, + PrimaryButtonText = "Сохранить", + CloseButtonText = "Отмена", + DefaultButton = ContentDialogButton.Primary + }; + if (await dialog.ShowAsync() != ContentDialogResult.Primary) + { + return; + } + if (string.IsNullOrWhiteSpace(nameBox.Text) + || string.IsNullOrWhiteSpace(hostBox.Text) + || string.IsNullOrWhiteSpace(userBox.Text) + || double.IsNaN(portBox.Value)) + { + ShowInfo("Данные не сохранены", "Название, адрес, порт и пользователь обязательны.", InfoBarSeverity.Warning); + return; + } + if (hubBox.IsChecked == true && Servers.Any(server => server.IsHub && server != selected)) + { + ShowInfo("Hub уже выбран", "В конфигурации может быть только один главный Mesh Hub.", InfoBarSeverity.Warning); + return; + } + + var index = Servers.IndexOf(selected); + var updated = new ServerViewModel(new ServerProfileData( + selected.Profile.Id, + nameBox.Text.Trim(), + hostBox.Text.Trim(), + checked((int)portBox.Value), + userBox.Text.Trim(), + hubBox.IsChecked == true)); + Servers[index] = updated; + await SaveProfilesAsync(); + await RefreshServerAsync(updated); + ShowInfo("Сервер изменён", updated.Name, InfoBarSeverity.Success); + } + + private async void DeleteServerButton_Click(object sender, RoutedEventArgs e) + { + if (ServerList.SelectedItem is not ServerViewModel selected) + { + ShowInfo("Сервер не выбран", "Выберите сервер в списке для удаления.", InfoBarSeverity.Warning); + return; + } + var dialog = new ContentDialog + { + XamlRoot = XamlRoot, + Title = $"Удалить {selected.Name}?", + Content = "Удаляется только локальный профиль. Серверная часть и WireGuard Node останутся установленными.", + PrimaryButtonText = "Удалить профиль", + CloseButtonText = "Отмена", + DefaultButton = ContentDialogButton.Close + }; + if (await dialog.ShowAsync() != ContentDialogResult.Primary) + { + return; + } + Servers.Remove(selected); + await SaveProfilesAsync(); + UpdateEmptyState(); + ShowInfo("Профиль удалён", selected.Name, InfoBarSeverity.Success); + } + private async void RefreshButton_Click(object sender, RoutedEventArgs e) => await RefreshAllAsync();