diff --git a/EstusShots.Gtk/Controls/BindableListControl.cs b/EstusShots.Gtk/Controls/BindableListControl.cs
index 19e26a8..3c7004b 100644
--- a/EstusShots.Gtk/Controls/BindableListControl.cs
+++ b/EstusShots.Gtk/Controls/BindableListControl.cs
@@ -100,7 +100,7 @@ namespace EstusShots.Gtk.Controls
}
}
- private void TreeViewOnRowActivated(object o, RowActivatedArgs args)
+ private void TreeViewOnRowActivated(object o, RowActivatedArgs args)
{
if (!(o is TreeView tree)) return;
var selection = tree.Selection;
@@ -128,19 +128,35 @@ namespace EstusShots.Gtk.Controls
foreach (var dataColumn in Columns)
{
// Offset by one, because the first column in the data store is fixed to the key value of the row
- var index = Columns.IndexOf(dataColumn) + 1;
- var column = new TreeViewColumn(
- dataColumn.Title,
- new CellRendererText(),
- "text", index)
- {
- Resizable = true,
- Reorderable = true
- };
- TreeView.AppendColumn(column);
+ var valueIndex = Columns.IndexOf(dataColumn) + 1;
+ var cell = GetRenderer(dataColumn);
+ var attr = GetAttribute(dataColumn);
+ dataColumn.PackStart(cell, true);
+ dataColumn.AddAttribute(cell, attr, valueIndex);
+ TreeView.AppendColumn(dataColumn);
}
}
+ private CellRenderer GetRenderer(DataColumn column)
+ {
+ var property = typeof(T).GetProperty(column.PropertyName);
+ return property?.PropertyType.Name switch
+ {
+ nameof(Boolean) => new CellRendererToggle(),
+ _ => new CellRendererText()
+ };
+ }
+
+ private string GetAttribute(DataColumn column)
+ {
+ var property = typeof(T).GetProperty(column.PropertyName);
+ return property?.PropertyType.Name switch
+ {
+ nameof(Boolean) => "active",
+ _ => "text"
+ };
+ }
+
private void InitListStore()
{
var types = Columns
diff --git a/EstusShots.Gtk/Controls/DataColumn.cs b/EstusShots.Gtk/Controls/DataColumn.cs
index df2f6a7..135a8cf 100644
--- a/EstusShots.Gtk/Controls/DataColumn.cs
+++ b/EstusShots.Gtk/Controls/DataColumn.cs
@@ -1,16 +1,20 @@
using System;
+using Gtk;
namespace EstusShots.Gtk.Controls
{
- public class DataColumn
+ public class DataColumn : TreeViewColumn
{
public DataColumn()
{
+ Resizable = true;
+ Reorderable = true;
}
public DataColumn(string propertyName)
{
PropertyName = propertyName;
+ Title = propertyName;
}
///
@@ -18,11 +22,6 @@ namespace EstusShots.Gtk.Controls
///
public string PropertyName { get; }
- ///
- /// The column header.
- ///
- public string Title { get; set; }
-
///
/// Applies the given transformation on each item in the column.
/// This changes only the display of the value.
diff --git a/EstusShots.Gtk/Dialogs/PlayerEditor.cs b/EstusShots.Gtk/Dialogs/PlayerEditor.cs
index f85c3a1..de69939 100644
--- a/EstusShots.Gtk/Dialogs/PlayerEditor.cs
+++ b/EstusShots.Gtk/Dialogs/PlayerEditor.cs
@@ -42,6 +42,11 @@ namespace EstusShots.Gtk.Dialogs
_builder.Autoconnect(this);
SavePlayerButton.Clicked += SavePlayerButtonOnClicked;
+ CancelPlayerEditorButton.Clicked += (sender, args) =>
+ {
+ OnDialogClosed?.Invoke(this, new DialogClosedEventArgs(false, null));
+ PlayerEditorDialog.Dispose();
+ };
PlayerEditorDialog.TransientFor = parent;
PlayerEditorDialog.Show();
diff --git a/EstusShots.Gtk/Pages/PlayersPage.cs b/EstusShots.Gtk/Pages/PlayersPage.cs
index eff3b3a..2b2128d 100644
--- a/EstusShots.Gtk/Pages/PlayersPage.cs
+++ b/EstusShots.Gtk/Pages/PlayersPage.cs
@@ -1,5 +1,7 @@
using System;
+using System.Collections.Generic;
using System.Threading.Tasks;
+using EstusShots.Gtk.Controls;
using EstusShots.Gtk.Dialogs;
using EstusShots.Shared.Dto;
using EstusShots.Shared.Models.Parameters;
@@ -15,14 +17,34 @@ namespace EstusShots.Gtk
[UI] public readonly TreeView PlayersTreeView = null;
[UI] public readonly Button NewPlayerButton = null;
[UI] public readonly Box PlayerEditorContainer = null;
-
+
+ private BindableListControl PlayersControl;
private void InitPlayersPage()
{
NewPlayerButton.Clicked += NewPlayerButtonOnClicked;
+
+ var columns = new List
+ {
+ new DataColumn(nameof(Player.Name)),
+ new DataColumn(nameof(Player.Alias)),
+ new DataColumn(nameof(Player.HexId)) {Title = "Hex ID"},
+ new DataColumn(nameof(Player.Anonymous)) {Title = "Is Anonymous?", FixedWidth = 30}
+ };
+ PlayersControl = new BindableListControl(columns, nameof(Player.PlayerId), PlayersTreeView);
+ PlayersControl.OnSelectionChanged += PlayersControlOnOnSelectionChanged;
+
+ Task.Factory.StartNew(ReloadPlayers);
}
// Events
+
+ private void PlayersControlOnOnSelectionChanged(object o, SelectionChangedEventArgs args)
+ {
+ if (!(args.Selection is Player player)) return;
+ var dialog = new PlayerEditor(this, player);
+ dialog.OnDialogClosed += PlayerEditorClosed;
+ }
private void NewPlayerButtonOnClicked(object sender, EventArgs e)
{
@@ -33,7 +55,7 @@ namespace EstusShots.Gtk
private async void PlayerEditorClosed(object o, DialogClosedEventArgs args)
{
if (!args.Ok || !(args.Model is Player player)) return;
- var res = await Task.Factory.StartNew(()
+ var res = await Task.Factory.StartNew(()
=> Client.Players.SavePlayer(new SavePlayerParameter(player)).Result);
if (!res.OperationResult.Success)
{
@@ -42,12 +64,12 @@ namespace EstusShots.Gtk
return;
}
- // ReloadPlayers();
+ await ReloadPlayers();
}
-
+
// Private Methods
- private async void ReloadPlayers()
+ private async Task ReloadPlayers()
{
var res = await Task.Factory.StartNew(()
=> Client.Players.GetPlayers(new GetPlayersParameter()).Result);
@@ -58,10 +80,9 @@ namespace EstusShots.Gtk
return;
}
- // TODO
- // SeasonsControl.Items = res.Data.Seasons;
- // SeasonsControl.DataBind();
- // Info("Player list refreshed");
+ PlayersControl.Items = res.Data.Players;
+ PlayersControl.DataBind();
+ Info("Player list refreshed");
}
}
}
\ No newline at end of file
diff --git a/EstusShots.Server/Mapping/Profiles.cs b/EstusShots.Server/Mapping/Profiles.cs
index 0b9efc2..a9bf2bc 100644
--- a/EstusShots.Server/Mapping/Profiles.cs
+++ b/EstusShots.Server/Mapping/Profiles.cs
@@ -12,6 +12,9 @@ namespace EstusShots.Server.Mapping
CreateMap();
CreateMap();
+
+ CreateMap();
+ CreateMap();
}
}
}
\ No newline at end of file
diff --git a/EstusShots.Server/Services/PlayersService.cs b/EstusShots.Server/Services/PlayersService.cs
index 2fbf684..aeed627 100644
--- a/EstusShots.Server/Services/PlayersService.cs
+++ b/EstusShots.Server/Services/PlayersService.cs
@@ -1,10 +1,13 @@
+using System.Collections.Generic;
using System.Threading.Tasks;
using AutoMapper;
using EstusShots.Server.Models;
using EstusShots.Shared.Interfaces;
using EstusShots.Shared.Models;
using EstusShots.Shared.Models.Parameters;
+using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
+using Dto = EstusShots.Shared.Dto;
namespace EstusShots.Server.Services
{
@@ -23,26 +26,42 @@ namespace EstusShots.Server.Services
public async Task> GetPlayers(GetPlayersParameter parameter)
{
- throw new System.NotImplementedException();
+ var players = await _context.Players.ToListAsync();
+ var dtos = _mapper.Map>(players);
+ return new ApiResponse(new GetPlayersResponse(dtos));
}
public async Task> GetPlayerDetails(GetPlayerDetailsParameter parameter)
{
- throw new System.NotImplementedException();
+ var player = await _context.Players.FindAsync(parameter.PlayerId);
+ if (player == null)
+ {
+ _logger.LogWarning($"Player '{parameter.PlayerId}' not found in database");
+ return new ApiResponse(new OperationResult(false, "Player not found"));
+ }
+
+ var dto = _mapper.Map(player);
+ return new ApiResponse(new GetPlayerDetailsResponse(dto));
}
public async Task> SavePlayer(SavePlayerParameter parameter)
{
- var player = _mapper.Map(parameter.Player);
- if (player.PlayerId.IsEmpty())
+ if (parameter.Player.PlayerId.IsEmpty())
{
- _context.Players.Add(player);
+ _context.Players.Add(_mapper.Map(parameter.Player));
var count = await _context.SaveChangesAsync();
_logger.LogInformation($"Created {count} rows");
+ return new ApiResponse(new SavePlayerResponse(parameter.Player.PlayerId));
+ }
+ else
+ {
+ var player = await _context.Players.FindAsync(parameter.Player.PlayerId);
+ _context.Players.Update(player);
+ _mapper.Map(parameter.Player, player);
+ var count = await _context.SaveChangesAsync();
+ _logger.LogInformation($"Updated player '{player.PlayerId}'");
return new ApiResponse(new SavePlayerResponse(player.PlayerId));
}
- // TODO Update Player
- return new ApiResponse(new OperationResult(false, "NotImplemented"));
}
public async Task> DeletePlayers(DeletePlayerParameter parameter)