diff --git a/src/HikvisionAttendanceManager.App/DbToDeviceView.xaml.cs b/src/HikvisionAttendanceManager.App/DbToDeviceView.xaml.cs deleted file mode 100644 index f69474c..0000000 --- a/src/HikvisionAttendanceManager.App/DbToDeviceView.xaml.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System.Collections.ObjectModel; -using System.Windows; -using System.Windows.Controls; -using HikvisionAttendanceManager.App.Models; -using HikvisionAttendanceManager.App.Services; - -namespace HikvisionAttendanceManager.App; - -public partial class DbToDeviceView : UserControl -{ - private readonly DeviceService _devices = new(); - private readonly AttendanceMachineUserRepository _machineUsers = new(); - private readonly AttendanceMachineFaceTemplateRepository _faceTemplates = new(); - private readonly TemplateSyncService _service; - private readonly ObservableCollection _rows = []; - private bool _initialized; - - public DbToDeviceView() - { - InitializeComponent(); - _service = new TemplateSyncService(new HikvisionIsapiClient(), _machineUsers, _faceTemplates, new OperationHistoryService()); - UsersGrid.ItemsSource = _rows; - UpdateUsersEmptyState(); - } - - public async Task InitializeAsync() - { - if (_initialized) return; - _initialized = true; - await RefreshAsync(); - } - - public async Task RefreshAsync() - { - var originalContent = RefreshButton.Content; - try - { - RefreshButton.IsEnabled = false; - RefreshButton.Content = "Refreshing..."; - SourceCombo.SelectedItem = null; - TargetCombo.SelectedItem = null; - _rows.Clear(); - UpdateUsersEmptyState(); - ProgressCard.Visibility = Visibility.Collapsed; - ProgressBar.Value = 0; - ProgressText.Text = ""; - CounterText.Text = ""; - UsersGrid.Items.Refresh(); - var devices = await _devices.LoadUnifiedAsync(); - SourceCombo.ItemsSource = devices; - TargetCombo.ItemsSource = devices; - } - finally - { - RefreshButton.IsEnabled = true; - RefreshButton.Content = originalContent; - } - } - - private async void Refresh_Click(object sender, RoutedEventArgs e) => await RefreshAsync(); - - private void SourceChanged(object sender, SelectionChangedEventArgs e) - { - _rows.Clear(); - UpdateUsersEmptyState(); - } - - private async void LoadUsers_Click(object sender, RoutedEventArgs e) - { - if (SourceCombo.SelectedItem is not Device source) { MessageBox.Show("Select a source machine."); return; } - _rows.Clear(); - var users = await _machineUsers.GetActiveByMachineAsync(source.MachineId, CancellationToken.None); - foreach (var user in users) - { - var template = await _faceTemplates.TryGetActiveAsync(user.SerialNumber, CancellationToken.None); - var hasFace = template?.Template is { Length: > 0 } && HikvisionIsapiClient.IsUploadableFaceTemplate(template.Template); - _rows.Add(new SelectableMachineUser(user.SerialNumber, user.EmployeeName, hasFace)); - } - - UpdateUsersEmptyState(); - } - - private void SelectAll_Click(object sender, RoutedEventArgs e) - { - foreach (var row in _rows) row.IsSelected = true; - UsersGrid.Items.Refresh(); - } - - private void ClearSelection_Click(object sender, RoutedEventArgs e) - { - foreach (var row in _rows) row.IsSelected = false; - UsersGrid.Items.Refresh(); - } - - private void UpdateUsersEmptyState() - { - UsersEmptyState.Visibility = _rows.Count == 0 ? Visibility.Visible : Visibility.Collapsed; - } - - private async void Transfer_Click(object sender, RoutedEventArgs e) - { - if (SourceCombo.SelectedItem is not Device source || TargetCombo.SelectedItem is not Device target) - { - MessageBox.Show("Select source and target machines."); - return; - } - if (string.Equals(source.MachineId, target.MachineId, StringComparison.OrdinalIgnoreCase) && - string.Equals(source.IpAddress, target.IpAddress, StringComparison.OrdinalIgnoreCase)) - { - MessageBox.Show("Source and target must be different devices."); - return; - } - - var selected = _rows.Where(r => r.IsSelected).Select(r => r.SerialNumber).ToList(); - if (selected.Count == 0) { MessageBox.Show("Select at least one user."); return; } - - ProgressCard.Visibility = Visibility.Visible; - var progress = new Progress(p => - { - ProgressBar.Maximum = Math.Max(1, p.Total); - ProgressBar.Value = p.Completed; - ProgressText.Text = $"{p.Completed}/{p.Total} · {p.CurrentEmployee} · {p.CurrentOperation}"; - CounterText.Text = $"Users: {p.Created} · Faces: {p.FacesUploaded} · Skipped: {p.Skipped} · Failed: {p.Failed}"; - }); - try - { - var entry = await _service.DbToDeviceAsync(source, target, selected, progress, CancellationToken.None); - ProgressText.Text = $"Completed — {entry.Status}"; - CounterText.Text = entry.Context; - } - catch (Exception ex) - { - MessageBox.Show(ex.Message, "DB → Device", MessageBoxButton.OK, MessageBoxImage.Error); - } - } -} diff --git a/src/HikvisionAttendanceManager.App/DbToDeviceView.xaml b/src/HikvisionAttendanceManager.App/DeviceToDeviceView.xaml similarity index 65% rename from src/HikvisionAttendanceManager.App/DbToDeviceView.xaml rename to src/HikvisionAttendanceManager.App/DeviceToDeviceView.xaml index 2b8d6ca..33d8496 100644 --- a/src/HikvisionAttendanceManager.App/DbToDeviceView.xaml +++ b/src/HikvisionAttendanceManager.App/DeviceToDeviceView.xaml @@ -1,4 +1,4 @@ - @@ -171,8 +171,8 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -