Changes in core, HTML export added

This commit is contained in:
2023-05-30 20:44:39 +02:00
Unverified
parent 93cc11bd01
commit d9b0e69f7c
10 changed files with 574 additions and 7 deletions

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
namespace TimetableDesigner.Core
{
[Serializable]
public abstract class Unit
{
#region FIELDS
private ulong _id;
private Guid _guid;
private string _name;
#endregion
#region PROPERTIES
public ulong Id => _id;
public Guid Guid => _guid;
public string Name
{
get => _name;
set => _name = value;
}
#endregion
#region CONSTRUCTORS
public Unit(ulong id)
{
_id = id;
_guid = Guid.NewGuid();
_name = string.Empty;
}
#endregion
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
namespace TimetableDesigner.Export
{
public abstract class Exporter
{
#region FIELDS
protected Project _project;
protected HashSet<Group> _groups;
protected HashSet<Subgroup> _subgroups;
protected HashSet<Teacher> _teachers;
protected HashSet<Classroom> _classrooms;
#endregion
#region PROPERTIES
public ICollection<Group> Groups => _groups;
public ICollection<Subgroup> Subgroups => _subgroups;
public ICollection<Teacher> Teachers => _teachers;
public ICollection<Classroom> Classrooms => _classrooms;
#endregion
#region CONSTRUCTORS
protected Exporter(Project project)
{
_project = project;
_groups = new HashSet<Group>();
_subgroups = new HashSet<Subgroup>();
_teachers = new HashSet<Teacher>();
_classrooms = new HashSet<Classroom>();
}
#endregion
#region PUBLIC METHODS
public abstract void Export(string path);
#endregion
}
}

View File

@@ -0,0 +1,165 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
namespace TimetableDesigner.Export
{
public class ExporterHTML : Exporter
{
#region CONSTRUCTORS
public ExporterHTML(Project project) : base(project) { }
#endregion
#region PUBLIC METHODS
public override void Export(string path) => Export(path, null);
public void Export(string path, string? css)
{
string content = BuildDocument(css);
using (StreamWriter writer = new StreamWriter(path))
{
writer.WriteLine(content);
}
}
#endregion
#region PRIVATE METHODS
private string BuildDocument(string? css)
{
if (css == null)
{
StringBuilder cssBuilder = new StringBuilder();
cssBuilder.AppendLine("h1 {text-align: center;}");
cssBuilder.AppendLine("table, td, th { border: 1px solid black; border-collapse: collapse; }");
cssBuilder.AppendLine("td, th { padding: 10px; }");
css = cssBuilder.ToString();
}
StringBuilder builder = new StringBuilder();
builder.AppendLine("<html>");
builder.AppendLine("<head>");
builder.AppendLine("<style>");
builder.AppendLine(css);
builder.AppendLine("</style>");
builder.AppendLine("</head>");
builder.AppendLine("<body>");
if (Groups.Count > 0)
{
builder.AppendLine("<h1>Groups</h1>");
foreach (Group group in Groups)
{
builder.AppendLine("<h2>");
builder.AppendLine(group.Name);
builder.AppendLine("</h2>");
builder.AppendLine(BuildTable(group));
}
}
if (Subgroups.Count > 0)
{
builder.AppendLine("<h1>Subgroups</h1>");
foreach (Subgroup subgroup in Subgroups)
{
builder.AppendLine("<h2>");
builder.AppendLine(subgroup.Name);
builder.AppendLine("</h2>");
builder.AppendLine(BuildTable(subgroup));
}
}
if (Teachers.Count > 0)
{
builder.AppendLine("<h1>Teachers</h1>");
foreach (Teacher teacher in Teachers)
{
builder.AppendLine("<h2>");
builder.AppendLine(teacher.Name);
builder.AppendLine("</h2>");
builder.AppendLine(BuildTable(teacher));
}
}
if (Classrooms.Count > 0)
{
builder.AppendLine("<h1>Classrooms</h1>");
foreach (Classroom classroom in Classrooms)
{
builder.AppendLine("<h2>");
builder.AppendLine(classroom.Name);
builder.AppendLine("</h2>");
builder.AppendLine(BuildTable(classroom));
}
}
builder.AppendLine("</body>");
builder.AppendLine("</html>");
return builder.ToString();
}
private string BuildTable(Unit unit)
{
IEnumerable<Class> classes = _project.Classes.Where(c => c.Classroom == unit || c.Teacher == unit || c.Group == unit || (unit is Group g && c.Group is Subgroup s && g.AssignedSubgroups.Contains(s)))
.Where(c => c.Slot is not null && c.Day is not null);
IEnumerable<TimetableDay> days = _project.TimetableTemplate.Days;
IEnumerable<TimetableSpan> slots = _project.TimetableTemplate.Slots;
StringBuilder builder = new StringBuilder();
builder.AppendLine("<table>");
builder.AppendLine("<tr>");
builder.AppendLine("<th></th>");
foreach (TimetableDay day in days)
{
builder.AppendLine($"<th>{day.Name}</th>");
}
builder.AppendLine("<tr>");
foreach (TimetableSpan slot in slots)
{
builder.AppendLine("<tr>");
builder.AppendLine($"<th>{slot}</th>");
foreach (TimetableDay day in days)
{
IEnumerable<Class> slotClasses = classes.Where(x => x.Day == day && x.Slot == slot);
builder.AppendLine("<td>");
foreach (Class slotClass in slotClasses)
{
string group = slotClass.Group is null ? "none" : slotClass.Group.Name;
string teacher = slotClass.Teacher is null ? "none" : slotClass.Teacher.Name;
string classroom = slotClass.Classroom is null ? "none" : slotClass.Classroom.Name;
builder.AppendLine($"<p title=\"Group: {group}\nTeacher: {teacher}\nClassroom: {classroom}\">");
builder.AppendLine(slotClass.Name);
builder.AppendLine("</p>");
}
builder.AppendLine("</td>");
}
builder.AppendLine("</tr>");
}
builder.AppendLine("</table>");
return builder.ToString();
}
#endregion
}
}

View File

@@ -6,4 +6,8 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\TimetableDesigner.Core\TimetableDesigner.Core.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,7 +0,0 @@
namespace TimetableDesigner.Scheduler
{
public class Class1
{
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

View File

@@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Xml.Serialization;
using TimetableDesigner.Commands;
using TimetableDesigner.Core;
using TimetableDesigner.Customs;
using TimetableDesigner.Export;
using TimetableDesigner.Services.FileDialog;
using TimetableDesigner.Services.MessageBox;
using TimetableDesigner.Services.Project;
using TimetableDesigner.ViewModels.Models;
namespace TimetableDesigner.ViewModels.Views
{
public class ExportHTMLViewVM : ObservableObject, IViewVM
{
#region FIELDS
private readonly IProjectService _projectService;
private readonly IFileDialogService _fileDialogService;
private readonly IMessageBoxService _messageBoxSercvice;
#endregion
#region PROPERTIES
public ObservableDictionary<GroupVM, bool> Groups { get; set; }
public ObservableDictionary<SubgroupVM, bool> Subgroups { get; set; }
public ObservableDictionary<TeacherVM, bool> Teachers { get; set; }
public ObservableDictionary<ClassroomVM, bool> Classrooms { get; set; }
public ICommand ExportCommand { get; set; }
#endregion
#region CONSTRUCTORS
public ExportHTMLViewVM()
{
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
_fileDialogService = ServiceProvider.Instance.GetService<IFileDialogService>();
_messageBoxSercvice = ServiceProvider.Instance.GetService<IMessageBoxService>();
ObservableCollection<GroupVM> groups = _projectService.ProjectViewModel.Groups;
groups.CollectionChanged += Groups_CollectionChanged;
Groups = new ObservableDictionary<GroupVM, bool>(groups.ToDictionary(x => x, x => true));
ObservableCollection<SubgroupVM> subgroups = _projectService.ProjectViewModel.Subgroups;
subgroups.CollectionChanged += Subgroups_CollectionChanged;
Subgroups = new ObservableDictionary<SubgroupVM, bool>(subgroups.ToDictionary(x => x, x => true));
ObservableCollection<TeacherVM> teachers = _projectService.ProjectViewModel.Teachers;
teachers.CollectionChanged += Teachers_CollectionChanged;
Teachers = new ObservableDictionary<TeacherVM, bool>(teachers.ToDictionary(x => x, x => true));
ObservableCollection<ClassroomVM> classrooms = _projectService.ProjectViewModel.Classrooms;
classrooms.CollectionChanged += Classrooms_CollectionChanged;
Classrooms = new ObservableDictionary<ClassroomVM, bool>(classrooms.ToDictionary(x => x, x => true));
ExportCommand = new RelayCommand<object>(a => Export());
}
#endregion
#region PRIVATE METHODS
private void Export()
{
Dictionary<string, IEnumerable<string>> types = new Dictionary<string, IEnumerable<string>>()
{
{ "HTML", new List<string> { "html" } }
};
string? path = _fileDialogService.SaveFile(types);
if (path is null)
{
return;
}
Project project = _projectService.Project;
IEnumerable<Group> groups = Groups.Cast<ObservableKeyValuePair<GroupVM, bool>>().Where(x => x.Value).Select(x => x.Key.Group);
IEnumerable<Subgroup> subgroups = Subgroups.Cast<ObservableKeyValuePair<SubgroupVM, bool>>().Where(x => x.Value).Select(x => x.Key.Subgroup);
IEnumerable<Teacher> teachers = Teachers.Cast<ObservableKeyValuePair<TeacherVM, bool>>().Where(x => x.Value).Select(x => x.Key.Teacher);
IEnumerable<Classroom> classrooms = Classrooms.Cast<ObservableKeyValuePair<ClassroomVM, bool>>().Where(x => x.Value).Select(x => x.Key.Classroom);
Exporter exporter = new ExporterHTML(project);
foreach (Group group in groups)
{
exporter.Groups.Add(group);
}
foreach (Subgroup subgroup in subgroups)
{
exporter.Subgroups.Add(subgroup);
}
foreach (Teacher teacher in teachers)
{
exporter.Teachers.Add(teacher);
}
foreach (Classroom classroom in classrooms)
{
exporter.Classrooms.Add(classroom);
}
exporter.Export(path);
_messageBoxSercvice.ShowInformation("Data was exported successfully");
}
private void Groups_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.OldItems is not null)
{
foreach (GroupVM vm in e.OldItems)
{
Groups.Remove(vm);
}
}
if (e.NewItems is not null)
{
foreach (GroupVM vm in e.NewItems)
{
Groups.Add(vm, true);
}
}
}
private void Subgroups_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.OldItems is not null)
{
foreach (SubgroupVM vm in e.OldItems)
{
Subgroups.Remove(vm);
}
}
if (e.NewItems is not null)
{
foreach (SubgroupVM vm in e.NewItems)
{
Subgroups.Add(vm, true);
}
}
}
private void Teachers_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.OldItems is not null)
{
foreach (TeacherVM vm in e.OldItems)
{
Teachers.Remove(vm);
}
}
if (e.NewItems is not null)
{
foreach (TeacherVM vm in e.NewItems)
{
Teachers.Add(vm, true);
}
}
}
private void Classrooms_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.OldItems is not null)
{
foreach (ClassroomVM vm in e.OldItems)
{
Classrooms.Remove(vm);
}
}
if (e.NewItems is not null)
{
foreach (ClassroomVM vm in e.NewItems)
{
Classrooms.Add(vm, true);
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,76 @@
<UserControl x:Class="TimetableDesigner.Views.ExportHTMLView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TimetableDesigner.Views"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<vm:ExportHTMLViewVM/>
</UserControl.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" Margin="5" Header="Timetables to export">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Groups" Margin="2"/>
<ScrollViewer Grid.Row="1" Grid.Column="0" Margin="2">
<ListBox ItemsSource="{Binding Groups}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Key.Name}" IsChecked="{Binding Value}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
<TextBlock Grid.Row="0" Grid.Column="1" Text="Subgroups" Margin="2"/>
<ScrollViewer Grid.Row="1" Grid.Column="1" Margin="2">
<ListBox ItemsSource="{Binding Subgroups}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Key.Name}" IsChecked="{Binding Value}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Teachers" Margin="2"/>
<ScrollViewer Grid.Row="3" Grid.Column="0" Margin="2">
<ListBox ItemsSource="{Binding Teachers}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Key.Name}" IsChecked="{Binding Value}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
<TextBlock Grid.Row="2" Grid.Column="1" Text="Classrooms" Margin="2"/>
<ScrollViewer Grid.Row="3" Grid.Column="1" Margin="2">
<ListBox ItemsSource="{Binding Classrooms}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Key.Name}" IsChecked="{Binding Value}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
</Grid>
</GroupBox>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="Export" Margin="5" Padding="3" Command="{Binding ExportCommand}"/>
</StackPanel>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TimetableDesigner.Views
{
/// <summary>
/// Interaction logic for ExportHTMLView.xaml
/// </summary>
public partial class ExportHTMLView : UserControl
{
public ExportHTMLView()
{
InitializeComponent();
}
}
}