From 96a65b24bdb220efa2da9db69e63b8ba38c73608 Mon Sep 17 00:00:00 2001 From: luxick Date: Sat, 29 Feb 2020 20:14:54 +0100 Subject: [PATCH] Notebook layout and episodes page --- EstusShots.Gtk/MainWindow.cs | 144 +++++++-- EstusShots.Gtk/MainWindow.glade | 302 ++++++++++++++---- EstusShots.Server/Models/Episode.cs | 2 +- EstusShots.Server/Services/EpisodesService.cs | 5 +- EstusShots.Shared/Dto/Episode.cs | 5 +- 5 files changed, 381 insertions(+), 77 deletions(-) diff --git a/EstusShots.Gtk/MainWindow.cs b/EstusShots.Gtk/MainWindow.cs index d875758..e7fe20f 100644 --- a/EstusShots.Gtk/MainWindow.cs +++ b/EstusShots.Gtk/MainWindow.cs @@ -14,12 +14,22 @@ namespace EstusShots.Gtk internal class MainWindow : Window { private const string ApiUrl = "http://localhost:5000/api/"; + [UI] private readonly Label _infoLabel = null; [UI] public readonly Button LoadButton = null; [UI] public readonly Box LoadingSpinner = null; [UI] public readonly Button NewSeasonButton = null; + [UI] public readonly Button AddEpisodeButton = null; [UI] public readonly Overlay SeasonsOverlay = null; + [UI] public readonly Overlay EpisodesOverlay = null; [UI] public readonly TreeView SeasonsView = null; + [UI] public readonly TreeView EpisodesTreeView = null; + [UI] public readonly Notebook Navigation = null; + [UI] public readonly Box EpisodesPage = null; + + private EstusShotsClient Client { get; } + private BindableListControl SeasonsControl { get; set; } + private BindableListControl EpisodesControl { get; set; } public MainWindow() : this(new Builder("MainWindow.glade")) { @@ -28,40 +38,82 @@ namespace EstusShots.Gtk private MainWindow(Builder builder) : base(builder.GetObject("MainWindow").Handle) { builder.Autoconnect(this); - Client = new EstusShotsClient("http://localhost:5000/api/"); + Client = new EstusShotsClient(ApiUrl); DeleteEvent += Window_DeleteEvent; LoadButton.Clicked += LoadButtonClicked; NewSeasonButton.Clicked += NewSeasonButtonOnClicked; + AddEpisodeButton.Clicked += AddEpisodeButtonOnClicked; - var seasonsColumns = new List - { - new DataColumn(nameof(Season.DisplayName)) {Title = "Name"}, - new DataColumn(nameof(Season.Description)) {Title = "Description"}, - new DataColumn(nameof(Season.Start)) - { - Title = "Start", - Format = date => (date as DateTime?)?.ToString("dd.MM.yyyy hh:mm") - } - }; - SeasonsControl = new BindableListControl(seasonsColumns, nameof(Season.SeasonId), SeasonsView); - SeasonsControl.OnSelectionChanged += SeasonsViewOnOnSelectionChanged; + InitSeasonsControl(); + InitEpisodesControl(); + + // The episodes page is not shown, as long as no season is selected + EpisodesPage.Hide(); + Info("Application Started"); // No need to wait for the loading to finnish var _ = ReloadSeasons(); } - private EstusShotsClient Client { get; } - private BindableListControl SeasonsControl { get; } + private void InitSeasonsControl() + { + var columns = new List + { + new DataColumn(nameof(Season.DisplayName)) {Title = "Name"}, + new DataColumn(nameof(Season.Description)) {Title = "Description"}, + new DataColumn(nameof(Season.Start)) + { + Title = "Start", + Format = date => (date as DateTime?)?.ToString("dd.MM.yyyy") + }, + new DataColumn(nameof(Season.End)) + { + Title = "End", + Format = date => (date as DateTime?)?.ToString("dd.MM.yyyy") ?? "Ongoing" + } + }; + SeasonsControl = new BindableListControl(columns, nameof(Season.SeasonId), SeasonsView); + SeasonsControl.OnSelectionChanged += SeasonsViewOnOnSelectionChanged; + } + + private void InitEpisodesControl() + { + var columns = new List + { + new DataColumn(nameof(Episode.DisplayName)) {Title = "Name"}, + new DataColumn(nameof(Episode.Title)) {Title = "Title"}, + new DataColumn(nameof(Episode.Date)) + { + Title = "Date", + Format = d => (d as DateTime?)?.ToString("dd.MM.yyyy") + }, + new DataColumn(nameof(Episode.Start)) + { + Title = "Start", + Format = d => (d as DateTime?)?.ToString("HH:mm") + + }, + new DataColumn(nameof(Episode.End)) + { + Title = "End", + Format = d => (d as DateTime?)?.ToString("HH:mm") ?? "Ongoing" + } + }; + EpisodesControl = new BindableListControl(columns, nameof(Episode.EpisodeId), EpisodesTreeView); + } private async void SeasonsViewOnOnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (!(e.Selection is Season season)) return; + using var _ = new LoadingMode(this); - // TODO this is test code + EpisodesPage.Show(); var parameter = new GetEpisodesParameter(season.SeasonId); var res = await Client.Episodes.GetEpisodes(parameter); + EpisodesControl.Items = res.Data.Episodes; + EpisodesControl.DataBind(); Info($"{season.DisplayName}: {res.Data.Episodes.Count} episodes"); } @@ -86,6 +138,47 @@ namespace EstusShots.Gtk await ReloadSeasons(); Info("Created new Season"); } + + private async void AddEpisodeButtonOnClicked(object sender, EventArgs e) + { + if (SeasonsControl.SelectedItem == null) return; + using var _ = new LoadingMode(this); + + var season = SeasonsControl.SelectedItem; + + // Some random test data + var rand = new Random(); + var start = new DateTime( + DateTime.Today.Year, + DateTime.Today.Month, + DateTime.Today.Day, + DateTime.Today.Hour + rand.Next(0, 12), + DateTime.Today.Minute + rand.Next(0, 59), + DateTime.Today.Second + ); + var end = start.AddHours(rand.Next(2, 4)); + + var ep = new Episode + { + SeasonId = season.SeasonId, + Number = EpisodesControl.Items.Any() ? EpisodesControl.Items.Max(x => x.Number) + 1 : 1, + Title = $"An Episode in season '{season.Game}'", + Date = DateTime.Today, + Start = start, + End = end + }; + + var parameter = new SaveEpisodeParameter(ep); + var res = await Client.Episodes.SaveEpisode(parameter); + + if (!res.OperationResult.Success) + { + Info($"Cannot add episode: {res.OperationResult.ShortMessage}"); + return; + } + + await ReloadEpisodes(); + } private async void LoadButtonClicked(object sender, EventArgs a) { @@ -106,7 +199,23 @@ namespace EstusShots.Gtk SeasonsControl.Items = res.Data.Seasons; SeasonsControl.DataBind(); - Info("List Refreshed"); + Info("Seasons Refreshed"); + } + + private async Task ReloadEpisodes() + { + var seasonId = SeasonsControl.SelectedItem.SeasonId; + var res = await Task.Factory.StartNew( + () => Client.Episodes.GetEpisodes(new GetEpisodesParameter(seasonId)).Result); + if (!res.OperationResult.Success) + { + _infoLabel.Text = $"Refresh Failed: {res.OperationResult.ShortMessage}"; + return; + } + + EpisodesControl.Items = res.Data.Episodes; + EpisodesControl.DataBind(); + Info("Episodes Refreshed"); } private void Window_DeleteEvent(object sender, DeleteEventArgs a) @@ -118,6 +227,5 @@ namespace EstusShots.Gtk { _infoLabel.Text = message; } - } } \ No newline at end of file diff --git a/EstusShots.Gtk/MainWindow.glade b/EstusShots.Gtk/MainWindow.glade index 1f67c95..bb5ebee 100644 --- a/EstusShots.Gtk/MainWindow.glade +++ b/EstusShots.Gtk/MainWindow.glade @@ -32,8 +32,11 @@ 1 + - + False Estus Shots 800 @@ -51,27 +54,258 @@ 2 vertical - + True - False + True - + True - True - in + False + vertical - + True - True - horizontal - - + False + + + True + True + in + + + True + True + horizontal + + + + + + + + -1 + + + True + True + 0 + + + + + True + False + end + + + Reload + True + True + True + + + False + True + 0 + + + + + New Season + True + True + True + + + True + True + 1 + + + + + + + + False + True + 2 + 2 + + + + + + + True + False + Seasons + + + False + + + + + True + False + vertical + + + True + False + + + True + True + in + + + True + True + horizontal + + + + + + + + -1 + + + + + True + True + 0 + + + + + True + False + end + + + Add Episode + True + True + True + + + True + True + 0 + + + + + + + + + + + False + True + 1 + - -1 + 1 + + + + + True + False + Episodes + + + 1 + False + + + + + True + False + vertical + + + + + + True + False + Enemies go here + + + False + True + 1 + + + + + + + + 2 + + + + + True + False + Enemies + + + 2 + False + + + + + True + False + vertical + + + + + + True + False + Players go here + + + False + True + 1 + + + + + + + + 3 + + + + + True + False + Players + + + 3 + False @@ -81,48 +315,6 @@ 0 - - - True - False - end - - - Reload - True - True - True - - - False - True - 0 - - - - - New Season - True - True - True - - - True - True - 1 - - - - - - - - False - True - 2 - 1 - - True @@ -157,7 +349,7 @@ False True - 2 + 3 diff --git a/EstusShots.Server/Models/Episode.cs b/EstusShots.Server/Models/Episode.cs index 21d7413..ccfd4d1 100644 --- a/EstusShots.Server/Models/Episode.cs +++ b/EstusShots.Server/Models/Episode.cs @@ -11,7 +11,7 @@ namespace EstusShots.Server.Models [MaxLength(50)] public string Title { get; set; } = default!; - public DateTime DateTime { get; set; } + public DateTime Date { get; set; } public DateTime Start { get; set; } diff --git a/EstusShots.Server/Services/EpisodesService.cs b/EstusShots.Server/Services/EpisodesService.cs index 8e2dcc2..ce11b46 100644 --- a/EstusShots.Server/Services/EpisodesService.cs +++ b/EstusShots.Server/Services/EpisodesService.cs @@ -30,6 +30,7 @@ namespace EstusShots.Server.Services { var episodes = await _context.Episodes .Where(x => x.SeasonId == parameter.SeasonId) + .Include(x => x.Season) .ToListAsync(); var dtos = _mapper.Map>(episodes); _logger.LogInformation($"{dtos.Count} episodes loaded for season '{parameter.SeasonId}'"); @@ -38,7 +39,9 @@ namespace EstusShots.Server.Services public async Task> GetEpisode(GetEpisodeParameter parameter) { - var episode = await _context.Seasons.FindAsync(parameter.EpisodeId); + var episode = await _context.Episodes + .Include(x => x.Season) + .FirstOrDefaultAsync(x => x.EpisodeId == parameter.EpisodeId); if (episode == null) { _logger.LogWarning($"Episode with ID {parameter.EpisodeId} was not found in database"); diff --git a/EstusShots.Shared/Dto/Episode.cs b/EstusShots.Shared/Dto/Episode.cs index 9709088..fd1f9a8 100644 --- a/EstusShots.Shared/Dto/Episode.cs +++ b/EstusShots.Shared/Dto/Episode.cs @@ -1,4 +1,5 @@ using System; +using System.Text.Json.Serialization; namespace EstusShots.Shared.Dto { @@ -10,7 +11,7 @@ namespace EstusShots.Shared.Dto public string Title { get; set; } - public DateTime DateTime { get; set; } + public DateTime Date { get; set; } public DateTime Start { get; set; } @@ -20,6 +21,6 @@ namespace EstusShots.Shared.Dto public Season Season { get; set; } - public string Displayname => $"S{Season.Number:D2}E{Number:D2}"; + public string DisplayName => $"S{Season?.Number ?? 0:D2}E{Number:D2}"; } } \ No newline at end of file