From d9b0e69f7c084a2499e7ed4545d77d5d0292c8e4 Mon Sep 17 00:00:00 2001 From: Mateusz Skoczek Date: Tue, 30 May 2023 20:44:39 +0200 Subject: [PATCH] Changes in core, HTML export added --- TimetableDesigner.Core/Unit.cs | 48 +++++ TimetableDesigner.Export/Exporter.cs | 57 +++++ TimetableDesigner.Export/ExporterHTML.cs | 165 +++++++++++++++ .../TimetableDesigner.Export.csproj | 4 + TimetableDesigner.Scheduler/Scheduler.cs | 7 - TimetableDesigner/Resources/Images/HTML.png | Bin 0 -> 497 bytes TimetableDesigner/Resources/Images/Import.png | Bin 0 -> 393 bytes .../ViewModels/Views/ExportHTMLViewVM.cs | 196 ++++++++++++++++++ TimetableDesigner/Views/ExportHTMLView.xaml | 76 +++++++ .../Views/ExportHTMLView.xaml.cs | 28 +++ 10 files changed, 574 insertions(+), 7 deletions(-) create mode 100644 TimetableDesigner.Core/Unit.cs create mode 100644 TimetableDesigner.Export/Exporter.cs create mode 100644 TimetableDesigner.Export/ExporterHTML.cs rename TimetableDesigner.Scheduler/TimetableDesigner.Scheduler.csproj => TimetableDesigner.Export/TimetableDesigner.Export.csproj (62%) delete mode 100644 TimetableDesigner.Scheduler/Scheduler.cs create mode 100644 TimetableDesigner/Resources/Images/HTML.png create mode 100644 TimetableDesigner/Resources/Images/Import.png create mode 100644 TimetableDesigner/ViewModels/Views/ExportHTMLViewVM.cs create mode 100644 TimetableDesigner/Views/ExportHTMLView.xaml create mode 100644 TimetableDesigner/Views/ExportHTMLView.xaml.cs diff --git a/TimetableDesigner.Core/Unit.cs b/TimetableDesigner.Core/Unit.cs new file mode 100644 index 0000000..f08a740 --- /dev/null +++ b/TimetableDesigner.Core/Unit.cs @@ -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 + } +} diff --git a/TimetableDesigner.Export/Exporter.cs b/TimetableDesigner.Export/Exporter.cs new file mode 100644 index 0000000..c509648 --- /dev/null +++ b/TimetableDesigner.Export/Exporter.cs @@ -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 _groups; + protected HashSet _subgroups; + protected HashSet _teachers; + protected HashSet _classrooms; + + #endregion + + + + #region PROPERTIES + + public ICollection Groups => _groups; + public ICollection Subgroups => _subgroups; + public ICollection Teachers => _teachers; + public ICollection Classrooms => _classrooms; + + + #endregion + + + + #region CONSTRUCTORS + + protected Exporter(Project project) + { + _project = project; + _groups = new HashSet(); + _subgroups = new HashSet(); + _teachers = new HashSet(); + _classrooms = new HashSet(); + } + + #endregion + + + + #region PUBLIC METHODS + + public abstract void Export(string path); + + #endregion + } +} diff --git a/TimetableDesigner.Export/ExporterHTML.cs b/TimetableDesigner.Export/ExporterHTML.cs new file mode 100644 index 0000000..88930d6 --- /dev/null +++ b/TimetableDesigner.Export/ExporterHTML.cs @@ -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(""); + builder.AppendLine(""); + builder.AppendLine(""); + builder.AppendLine(""); + builder.AppendLine(""); + + if (Groups.Count > 0) + { + builder.AppendLine("

Groups

"); + + foreach (Group group in Groups) + { + builder.AppendLine("

"); + builder.AppendLine(group.Name); + builder.AppendLine("

"); + builder.AppendLine(BuildTable(group)); + } + } + + if (Subgroups.Count > 0) + { + builder.AppendLine("

Subgroups

"); + + foreach (Subgroup subgroup in Subgroups) + { + builder.AppendLine("

"); + builder.AppendLine(subgroup.Name); + builder.AppendLine("

"); + builder.AppendLine(BuildTable(subgroup)); + } + } + + if (Teachers.Count > 0) + { + builder.AppendLine("

Teachers

"); + + foreach (Teacher teacher in Teachers) + { + builder.AppendLine("

"); + builder.AppendLine(teacher.Name); + builder.AppendLine("

"); + builder.AppendLine(BuildTable(teacher)); + } + } + + if (Classrooms.Count > 0) + { + builder.AppendLine("

Classrooms

"); + + foreach (Classroom classroom in Classrooms) + { + builder.AppendLine("

"); + builder.AppendLine(classroom.Name); + builder.AppendLine("

"); + builder.AppendLine(BuildTable(classroom)); + } + } + + builder.AppendLine(""); + builder.AppendLine(""); + + return builder.ToString(); + } + + private string BuildTable(Unit unit) + { + IEnumerable 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 days = _project.TimetableTemplate.Days; + IEnumerable slots = _project.TimetableTemplate.Slots; + + StringBuilder builder = new StringBuilder(); + + builder.AppendLine(""); + builder.AppendLine(""); + builder.AppendLine(""); + foreach (TimetableDay day in days) + { + builder.AppendLine($""); + } + builder.AppendLine(""); + foreach (TimetableSpan slot in slots) + { + builder.AppendLine(""); + builder.AppendLine($""); + foreach (TimetableDay day in days) + { + IEnumerable slotClasses = classes.Where(x => x.Day == day && x.Slot == slot); + + builder.AppendLine(""); + } + builder.AppendLine(""); + } + builder.AppendLine("
{day.Name}
{slot}"); + 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($"

"); + builder.AppendLine(slotClass.Name); + builder.AppendLine("

"); + } + builder.AppendLine("
"); + + return builder.ToString(); + + } + + #endregion + } +} diff --git a/TimetableDesigner.Scheduler/TimetableDesigner.Scheduler.csproj b/TimetableDesigner.Export/TimetableDesigner.Export.csproj similarity index 62% rename from TimetableDesigner.Scheduler/TimetableDesigner.Scheduler.csproj rename to TimetableDesigner.Export/TimetableDesigner.Export.csproj index cfadb03..a9f5fbe 100644 --- a/TimetableDesigner.Scheduler/TimetableDesigner.Scheduler.csproj +++ b/TimetableDesigner.Export/TimetableDesigner.Export.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/TimetableDesigner.Scheduler/Scheduler.cs b/TimetableDesigner.Scheduler/Scheduler.cs deleted file mode 100644 index b632a26..0000000 --- a/TimetableDesigner.Scheduler/Scheduler.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace TimetableDesigner.Scheduler -{ - public class Class1 - { - - } -} \ No newline at end of file diff --git a/TimetableDesigner/Resources/Images/HTML.png b/TimetableDesigner/Resources/Images/HTML.png new file mode 100644 index 0000000000000000000000000000000000000000..be3bf78c42481131951dfcd36df6df9f8b5f0cab GIT binary patch literal 497 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?3oVGw3ym^DX&fq`+c zr;B4q#hl~>3D(68+YXf9p7npr0lVnyB|MS*N8aCcviJXS=>YTd`2Bz8@5tA#wQ=O; zxB2m9V%@wCODD3wc*YqoRrP?;*2XcL-)6y9^%oBt*|&UQ*=zHmA#C1)lkVEPonz$kRnH#8+z{%R1Ij;jn5aPfuc!f!!u{iOos>t8=3G#6I8K^vd2l z@6dyf40eVy*d1<^{7cy|OZ*yQ_ppN zY{-eeT7Peo&xRQRzW?fHUi11@%`k1-#LLzjj z)#gClgg^65^#zY6D%cq&Ex5$4mbNp)YDTV6xlvnHn1-}u@L6W&PMl$qAtVKilEyX$ Z2GeYla2@H|9AF$Wc)I$ztaD0e0suZF)^7j+ literal 0 HcmV?d00001 diff --git a/TimetableDesigner/Resources/Images/Import.png b/TimetableDesigner/Resources/Images/Import.png new file mode 100644 index 0000000000000000000000000000000000000000..9e08cac6be16e7aba01a1b3331501e0e171f5d20 GIT binary patch literal 393 zcmV;40e1e0P)2^+Q|E*K7Q+9LNp_bwXBb8!` z)BcIPAD_#WALtRFs{Hf8sT7mE%v6g2)s$BwKtGgMAwa*BU*yv7mJ+MPr55-qe^_7s zubH3a4@m_2C|^|RUEmIbJdTfgDPJTL*i$UP4KJ?>0qRL&KFRNs2&^J;;deIoGs@er zka2^A8Ufb6nd6%6^qaQrG}jzxZnPa}_?t*r>w33o0_(<^K!rU4v=M5DjS$)h{r8`I nkY!0FAkGLzu`>a~*kV2a`xncDe^84+00000NkvXXu0mjf-w>tp literal 0 HcmV?d00001 diff --git a/TimetableDesigner/ViewModels/Views/ExportHTMLViewVM.cs b/TimetableDesigner/ViewModels/Views/ExportHTMLViewVM.cs new file mode 100644 index 0000000..9dbd9cd --- /dev/null +++ b/TimetableDesigner/ViewModels/Views/ExportHTMLViewVM.cs @@ -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 Groups { get; set; } + public ObservableDictionary Subgroups { get; set; } + public ObservableDictionary Teachers { get; set; } + public ObservableDictionary Classrooms { get; set; } + + public ICommand ExportCommand { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + public ExportHTMLViewVM() + { + _projectService = ServiceProvider.Instance.GetService(); + _fileDialogService = ServiceProvider.Instance.GetService(); + _messageBoxSercvice = ServiceProvider.Instance.GetService(); + + ObservableCollection groups = _projectService.ProjectViewModel.Groups; + groups.CollectionChanged += Groups_CollectionChanged; + Groups = new ObservableDictionary(groups.ToDictionary(x => x, x => true)); + + ObservableCollection subgroups = _projectService.ProjectViewModel.Subgroups; + subgroups.CollectionChanged += Subgroups_CollectionChanged; + Subgroups = new ObservableDictionary(subgroups.ToDictionary(x => x, x => true)); + + ObservableCollection teachers = _projectService.ProjectViewModel.Teachers; + teachers.CollectionChanged += Teachers_CollectionChanged; + Teachers = new ObservableDictionary(teachers.ToDictionary(x => x, x => true)); + + ObservableCollection classrooms = _projectService.ProjectViewModel.Classrooms; + classrooms.CollectionChanged += Classrooms_CollectionChanged; + Classrooms = new ObservableDictionary(classrooms.ToDictionary(x => x, x => true)); + + ExportCommand = new RelayCommand(a => Export()); + } + + #endregion + + + + #region PRIVATE METHODS + + private void Export() + { + Dictionary> types = new Dictionary>() + { + { "HTML", new List { "html" } } + }; + string? path = _fileDialogService.SaveFile(types); + if (path is null) + { + return; + } + + Project project = _projectService.Project; + IEnumerable groups = Groups.Cast>().Where(x => x.Value).Select(x => x.Key.Group); + IEnumerable subgroups = Subgroups.Cast>().Where(x => x.Value).Select(x => x.Key.Subgroup); + IEnumerable teachers = Teachers.Cast>().Where(x => x.Value).Select(x => x.Key.Teacher); + IEnumerable classrooms = Classrooms.Cast>().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 + } +} diff --git a/TimetableDesigner/Views/ExportHTMLView.xaml b/TimetableDesigner/Views/ExportHTMLView.xaml new file mode 100644 index 0000000..a18f2db --- /dev/null +++ b/TimetableDesigner/Views/ExportHTMLView.xaml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +