main group window

This commit is contained in:
Zagrebin 2024-12-12 10:20:21 +03:00
parent 311783b23d
commit 2b38373d9f
13 changed files with 358 additions and 27 deletions

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using domain.Request;
using Presence.Desktop.Models;
namespace Presence.Desktop.Helpers
{
public static class CsvHelper
{
public static IEnumerable<AddStudentRequest> ReadCsvStudents(string path)
{
List<AddStudentRequest> students = new List<AddStudentRequest>();
var csvLines = File.ReadAllLines(path, Encoding.GetEncoding("utf-8"));
using (var reader = new StreamReader(path))
{
string line;
while ((line = reader.ReadLine()) != null)
{
var values = line.Split(';');
if (values.Length != 3)
continue;
students.Add(new AddStudentRequest
{
LastName = values[0],
FirstName = values[1],
Patronymic = values[2]
});
}
}
return students;
}
}
}

View File

@ -10,6 +10,6 @@ namespace Presence.Desktop.Models
{ {
public int Id { get; set; } public int Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public IEnumerable<StudentPresenter>? students = null; public List<StudentPresenter>? students = null;
} }
} }

View File

@ -10,10 +10,6 @@
<ItemGroup> <ItemGroup>
<AvaloniaResource Include="Assets\**" /> <AvaloniaResource Include="Assets\**" />
<AvaloniaXaml Remove="Новая папка\**" />
<Compile Remove="Новая папка\**" />
<EmbeddedResource Remove="Новая папка\**" />
<None Remove="Новая папка\**" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -0,0 +1,6 @@
namespace Presence.Desktop.ViewModels;
public class EditWindowViewModel : ViewModelBase
{
}

View File

@ -1,5 +1,6 @@
using domain.UseCase; using domain.UseCase;
using Presence.Desktop.Models; using Presence.Desktop.Models;
using Presence.Desktop.Helpers;
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Reactive; using System.Reactive;
@ -7,8 +8,13 @@ using System.Linq;
using ReactiveUI; using ReactiveUI;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Windows.Input; using System.Windows.Input;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls.Selection;
using domain.Request;
using System.Text;
namespace Presence.Desktop.ViewModels namespace Presence.Desktop.ViewModels
{ {
@ -45,8 +51,32 @@ namespace Presence.Desktop.ViewModels
set => this.RaiseAndSetIfChanged(ref _selectedFile, value); set => this.RaiseAndSetIfChanged(ref _selectedFile, value);
} }
private bool _MultipleSelected = false;
public bool MultipleSelected { get => _MultipleSelected; set => this.RaiseAndSetIfChanged(ref _MultipleSelected, value); }
public SelectionModel<StudentPresenter> Selection { get; }
private string _selectedSort = "Релевантность";
public string SelectedSort
{
get => _selectedSort;
set => this.RaiseAndSetIfChanged(ref _selectedSort, value);
}
public List<string> Sorting { get; set; } =
[
"Релевантность",
"А-Я",
"Я-А"
];
public ICommand OpenFileDialog { get; } public ICommand OpenFileDialog { get; }
public ICommand EditCommand { get; }
public ICommand DeleteCommand { get; }
public ICommand DeleteSelectedCommand { get; }
public ICommand DeleteAllCommand { get; }
public MainWindowViewModel() public MainWindowViewModel()
{ {
_groupService = null; _groupService = null;
@ -63,12 +93,25 @@ namespace Presence.Desktop.ViewModels
_students = new(); _students = new();
this.WhenAnyValue(vm => vm.SelectedGroupItem) this.WhenAnyValue(vm => vm.SelectedGroupItem,
x => x.SelectedSort)
.Subscribe(_ => .Subscribe(_ =>
{ {
RefreshGroups(); RefreshGroups();
SetStudents(); SetStudents(SelectedSort);
}); });
Selection = new SelectionModel<StudentPresenter>();
Selection.SingleSelect = false;
Selection.SelectionChanged += (sender, args) =>
{
MultipleSelected = Selection.SelectedItems.Count > 1;
};
DeleteCommand = ReactiveCommand.Create(DeleteStudent);
DeleteSelectedCommand = ReactiveCommand.Create(DeleteStudent);
DeleteAllCommand = ReactiveCommand.Create(DeleteAllStudents);
} }
private void RefreshGroups() private void RefreshGroups()
@ -91,7 +134,7 @@ namespace Presence.Desktop.ViewModels
Id = item.Id, Id = item.Id,
Name = item.Name Name = item.Name
} }
}) }).ToList()
}; };
groupPresenters.Add(groupPresenter); groupPresenters.Add(groupPresenter);
} }
@ -99,25 +142,117 @@ namespace Presence.Desktop.ViewModels
_groups = new(groupPresenters); _groups = new(groupPresenters);
} }
private void SetStudents() private void SetStudents(string selectedSort)
{ {
if (SelectedGroupItem == null) return; if (SelectedGroupItem == null) return;
if (SelectedGroupItem.students == null) return; if (SelectedGroupItem.students == null) return;
Students.Clear(); Students.Clear();
foreach (var student in SelectedGroupItem.students) List<StudentPresenter> students = new(_groupService.GetGroupsWithStudents()
.Single(g => g.Id == SelectedGroupItem.Id)
.Users
.Select(u => new StudentPresenter
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
Patronymic = u.Patronymic,
Group = new GroupPresenter()
{
Id = SelectedGroupItem.Id,
Name = SelectedGroupItem.Name
}
})
);
students = selectedSort switch
{
"Релевантность" => students.OrderBy(s => s.Id).ToList(),
"А-Я" => students.OrderBy(s => s.LastName).ToList(),
"Я-А" => students.OrderByDescending(s => s.LastName).ToList(),
_ => students
};
foreach (var student in students)
Students.Add(student); Students.Add(student);
} }
private async Task SelectFile() private async Task SelectFile()
{ {
SelectedFile = await ShowOpenFileDialog.Handle(Unit.Default); try
if (SelectedFile is object)
{ {
SelectedFile = await ShowOpenFileDialog.Handle(Unit.Default);
} }
catch (Exception)
{
return;
}
if (SelectedGroupItem == null) return;
try
{
var studentsToAdd = CsvHelper.ReadCsvStudents(SelectedFile);
if (studentsToAdd.Any())
{
_groupService.AddStudentsToGroup(SelectedGroupItem.Id, studentsToAdd);
foreach (var studentRequest in studentsToAdd)
{
var studentPresenter = new StudentPresenter
{
LastName = studentRequest.LastName,
FirstName = studentRequest.FirstName,
Patronymic = studentRequest.Patronymic,
Group = SelectedGroupItem
};
SelectedGroupItem.students.Add(studentPresenter);
Students.Add(studentPresenter);
}
RefreshGroups();
SetStudents(SelectedSort);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
private void DeleteStudent()
{
if (Selection.SelectedItems == null || Selection.SelectedItems.Count == 0) return;
var studentIds = Selection.SelectedItems.Select(s => s.Id).ToList();
_groupService.RemoveStudentsFromGroupByIds(SelectedGroupItem.Id, studentIds);
foreach (var student in Selection.SelectedItems.ToList())
{
SelectedGroupItem.students.Remove(student);
Students.Remove(student);
}
SetStudents(SelectedSort);
RefreshGroups();
}
private void DeleteAllStudents()
{
if (Students.Count == 0 && SelectedGroupItem == null) return;
_groupService.RemoveStudentsFromGroup(SelectedGroupItem.Id);
SelectedGroupItem.students.Clear();
Students.Clear();
RefreshGroups();
SetStudents(SelectedSort);
} }
} }

View File

@ -0,0 +1,17 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:Presence.Desktop.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Presence.Desktop.EditWindow"
x:DataType="vm:EditWindowViewModel"
Title="Edit">
<Design.DataContext>
<vm:EditWindowViewModel/>
</Design.DataContext>
</Window>

View File

@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Presence.Desktop;
public partial class EditWindow : Window
{
public EditWindow()
{
InitializeComponent();
}
}

View File

@ -13,28 +13,44 @@
<vm:MainWindowViewModel/> <vm:MainWindowViewModel/>
</Design.DataContext> </Design.DataContext>
<DockPanel Background="Azure"> <DockPanel>
<StackPanel <StackPanel
Spacing="10" Spacing="10"
HorizontalAlignment="Center" HorizontalAlignment="Center"
DockPanel.Dock="Top" DockPanel.Dock="Top"
Orientation="Horizontal"> Orientation="Horizontal">
<ComboBox ItemsSource="{Binding Groups}" SelectedValue="{Binding SelectedGroupItem}"> <ComboBox ItemsSource="{Binding Groups}"
<ComboBox.ItemTemplate> SelectedValue="{Binding SelectedGroupItem}"
<DataTemplate> DisplayMemberBinding="{Binding Name}"
<TextBlock Text="{Binding Name}"/> SelectedValueBinding="{Binding}"
</DataTemplate> />
</ComboBox.ItemTemplate>
</ComboBox>
<Button Width="140" HorizontalContentAlignment="Center" Content="Внести студентов" Command="{Binding OpenFileDialog}"/> <Button Width="140" HorizontalContentAlignment="Center" Content="Внести студентов" Command="{Binding OpenFileDialog}"/>
<ComboBox/> <ComboBox ItemsSource="{Binding Sorting}" SelectedItem="{Binding SelectedSort}"/>
<Button HorizontalAlignment="Right" Content="Удалить всех студентов" Command="{Binding DeleteAllCommand}"/>
</StackPanel> </StackPanel>
<Border> <Border>
<ListBox ItemsSource="{Binding Students}"> <ListBox Name="StudentListBox" SelectionMode="Multiple" Selection="{Binding Selection}" ItemsSource="{Binding Students}">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock> <StackPanel.ContextMenu>
<ContextMenu>
<MenuItem IsVisible="{Binding !#StudentListBox.((vm:MainWindowViewModel)DataContext).MultipleSelected}"
Command="{Binding #StudentListBox.((vm:MainWindowViewModel)DataContext).EditCommand}"
Header="Изменить"/>
<MenuItem IsVisible="{Binding !#StudentListBox.((vm:MainWindowViewModel)DataContext).MultipleSelected}"
Command="{Binding #StudentListBox.((vm:MainWindowViewModel)DataContext).DeleteCommand}"
Header="Удалить"/>
<MenuItem IsVisible="{Binding #StudentListBox.((vm:MainWindowViewModel)DataContext).MultipleSelected}"
Command="{Binding #StudentListBox.((vm:MainWindowViewModel)DataContext).DeleteSelectedCommand}"
Header="Удалить выделенные"/>
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock>
<TextBlock.Text> <TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1} {2}"> <MultiBinding StringFormat="{}{0} {1} {2}">
<Binding Path="LastName"/> <Binding Path="LastName"/>
@ -48,6 +64,7 @@
</ListBox.ItemTemplate> </ListBox.ItemTemplate>
</ListBox> </ListBox>
</Border> </Border>
</DockPanel> </DockPanel>
</Window> </Window>

View File

@ -15,6 +15,9 @@ namespace Presence.Desktop.Views
{ {
public MainWindow() public MainWindow()
{ {
if (Design.IsDesignMode)
ViewModel = new MainWindowViewModel();
InitializeComponent(); InitializeComponent();
this.WhenActivated(action => this.WhenActivated(action =>
@ -41,7 +44,7 @@ namespace Presence.Desktop.Views
}; };
var storageFile = await topLevel.StorageProvider.OpenFilePickerAsync(fpOptions); var storageFile = await topLevel.StorageProvider.OpenFilePickerAsync(fpOptions);
interaction.SetOutput(storageFile.First().Path.ToString()); interaction.SetOutput(storageFile.First().Path.LocalPath);
} }
} }

View File

@ -27,6 +27,14 @@ namespace data.Repository
/// <param name="students">список студентов</param> /// <param name="students">список студентов</param>
public bool AddGroupWithStudents(Group group, IEnumerable<Student> students); public bool AddGroupWithStudents(Group group, IEnumerable<Student> students);
/// <summary>
/// TODO
/// </summary>
/// <param name="id"></param>
/// <param name="students"></param>
/// <returns></returns>
public bool AddStudentsToGroup(int id, IEnumerable<Student> students);
/// <summary> /// <summary>
/// Удаление группы по индетефикатору /// Удаление группы по индетефикатору
/// </summary> /// </summary>
@ -39,5 +47,21 @@ namespace data.Repository
/// <param name="id">индетефикатор</param> /// <param name="id">индетефикатор</param>
/// <param name="name">наименованвие</param> /// <param name="name">наименованвие</param>
public bool UpdateGroup(int id, string name); public bool UpdateGroup(int id, string name);
/// <summary>
/// Удаление всех студентов из группы
/// </summary>
/// <param name="id">индетефикатор</param>
/// <returns></returns>
public bool RemoveStudentsFromGroup(int id);
/// <summary>
/// Удаление студентов из группы по их индетефикатору
/// </summary>
/// <param name="id">индетефикатор группы</param>
/// <param name="studentIds">список индетефикаторов студентов</param>
/// <returns></returns>
public bool RemoveStudentsFromGroupByIds(int id, IEnumerable<int> studentIds);
} }
} }

View File

@ -38,7 +38,33 @@ namespace data.Repository
Debug.WriteLine("Во время добавления группы со студентами произошла ошибка: ", ex.Message); Debug.WriteLine("Во время добавления группы со студентами произошла ошибка: ", ex.Message);
transaction.Rollback(); transaction.Rollback();
} }
return false; return false;
}
public bool AddStudentsToGroup(int id, IEnumerable<Student> students)
{
using var transaction = _dbContext.Database.BeginTransaction();
try
{
Group group = _dbContext.Groups.Find(id);
foreach (var student in students)
{
student.Group = group;
student.GroupId = id;
_dbContext.Students.Add(student);
}
_dbContext.SaveChanges();
transaction.Commit();
return true;
}
catch (Exception ex)
{
Console.WriteLine("Во время добавления студентов в группу произошла ошибка: ", ex.Message);
transaction.Rollback();
}
return false;
} }
public bool CreateGroup(Group group) public bool CreateGroup(Group group)
@ -67,5 +93,27 @@ namespace data.Repository
group.Name = name; group.Name = name;
return _dbContext.SaveChanges() > 0; return _dbContext.SaveChanges() > 0;
} }
public bool RemoveStudentsFromGroup(int id)
{
var students = _dbContext.Students.Where(s => s.GroupId == id).ToList();
_dbContext.Students.RemoveRange(students);
return _dbContext.SaveChanges() > 0;
}
public bool RemoveStudentsFromGroupByIds(int id, IEnumerable<int> studentIds)
{
var studentsToRemove = _dbContext.Students
.Where(s => s.GroupId == id && studentIds.Contains(s.Id))
.ToList();
if (studentsToRemove.Any())
{
_dbContext.Students.RemoveRange(studentsToRemove);
return _dbContext.SaveChanges() > 0;
}
return false;
}
} }
} }

View File

@ -34,6 +34,15 @@ namespace domain.Service
_groupRepository.AddGroupWithStudents(group, students); _groupRepository.AddGroupWithStudents(group, students);
} }
public void AddStudentsToGroup(int id, IEnumerable<AddStudentRequest> students)
{
List<Student> studentList = students
.Select(it => new Student { FirstName = it.FirstName, LastName = it.LastName, Patronymic = it.Patronymic })
.ToList();
_groupRepository.AddStudentsToGroup(id, studentList);
}
public void EditGroup(EditGroupRequest editGroupRequest) public void EditGroup(EditGroupRequest editGroupRequest)
=> _groupRepository.UpdateGroup(editGroupRequest.GroupId, editGroupRequest.GroupName); => _groupRepository.UpdateGroup(editGroupRequest.GroupId, editGroupRequest.GroupName);
@ -78,5 +87,21 @@ namespace domain.Service
}) })
}).Single(g => g.Id == id); }).Single(g => g.Id == id);
} }
public void RemoveStudentsFromGroup(int groupId)
{
_groupRepository.RemoveStudentsFromGroup(groupId);
}
public void RemoveStudentsFromGroupByIds(int groupId, IEnumerable<int> studentIds)
{
var group = _groupRepository.GetAllGroups().FirstOrDefault(g => g.Id == groupId);
if (group == null)
{
throw new KeyNotFoundException($"Группа с ID {groupId} не найдена.");
}
_groupRepository.RemoveStudentsFromGroupByIds(groupId, studentIds);
}
} }
} }

View File

@ -14,6 +14,8 @@ namespace domain.UseCase
public void AddGroupWithStudents(AddGroupWithStudentRequest addGroupWithStudentRequest); public void AddGroupWithStudents(AddGroupWithStudentRequest addGroupWithStudentRequest);
public void AddStudentsToGroup(int id, IEnumerable<AddStudentRequest> students);
public bool RemoveGroup(RemoveGroupRequest removeGroupRequest); public bool RemoveGroup(RemoveGroupRequest removeGroupRequest);
public void EditGroup(EditGroupRequest editGroupRequest); public void EditGroup(EditGroupRequest editGroupRequest);
@ -21,5 +23,9 @@ namespace domain.UseCase
public IEnumerable<GroupEntity> GetGroupsWithStudents(); public IEnumerable<GroupEntity> GetGroupsWithStudents();
public GroupSubjectEntity GetGroupSubject(int id); public GroupSubjectEntity GetGroupSubject(int id);
public void RemoveStudentsFromGroup(int groupId);
public void RemoveStudentsFromGroupByIds(int groupId, IEnumerable<int> studentIds);
} }
} }