From 797484525bd33946cf686ff3266f8ddbe73179f1 Mon Sep 17 00:00:00 2001 From: Maxime Adler Date: Thu, 10 Apr 2025 15:18:44 +0200 Subject: [PATCH] Add Create and Update --- .../Games/{GamesBase.razor => GameBase.razor} | 4 +- .../{GamesBase.razor.cs => GameBase.razor.cs} | 2 +- ...GamesBase.razor.css => GameBase.razor.css} | 0 .../{GamesHeader.razor => GameHeader.razor} | 0 ...mesHeader.razor.cs => GameHeader.razor.cs} | 2 +- ...sHeader.razor.css => GameHeader.razor.css} | 0 .../GameIdeas.Shared/Dto/GameFilterDto.cs | 2 - .../GameIdeas.Shared/Dto/PaggingDto.cs | 7 ++ .../Exceptions/NotFoundException.cs | 7 ++ .../Controllers/GameController.cs | 2 +- .../GameIdeas.WebAPI/Services/GameService.cs | 95 +++++++++++++------ 11 files changed, 84 insertions(+), 37 deletions(-) rename src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/{GamesBase.razor => GameBase.razor} (94%) rename src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/{GamesBase.razor.cs => GameBase.razor.cs} (87%) rename src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/{GamesBase.razor.css => GameBase.razor.css} (100%) rename src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/{GamesHeader.razor => GameHeader.razor} (100%) rename src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/{GamesHeader.razor.cs => GameHeader.razor.cs} (95%) rename src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/{GamesHeader.razor.css => GameHeader.razor.css} (100%) create mode 100644 src/GameIdeas/GameIdeas.Shared/Dto/PaggingDto.cs create mode 100644 src/GameIdeas/GameIdeas.Shared/Exceptions/NotFoundException.cs diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GamesBase.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor similarity index 94% rename from src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GamesBase.razor rename to src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor index 3da8b3f..dd434a7 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GamesBase.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor @@ -9,10 +9,10 @@ @ResourcesKey.GamesIdeas - + - +
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GamesBase.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor.cs similarity index 87% rename from src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GamesBase.razor.cs rename to src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor.cs index 0fcb9fa..60ab45d 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GamesBase.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor.cs @@ -3,7 +3,7 @@ using GameIdeas.BlazorApp.Shared.Models; namespace GameIdeas.BlazorApp.Pages.Games; -public partial class GamesBase () +public partial class GameBase () { private DisplayType DisplayType = DisplayType.List; private GameFilterParams GameFilterParams = new(); diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GamesBase.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor.css similarity index 100% rename from src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GamesBase.razor.css rename to src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor.css diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GamesHeader.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor similarity index 100% rename from src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GamesHeader.razor rename to src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GamesHeader.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor.cs similarity index 95% rename from src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GamesHeader.razor.cs rename to src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor.cs index ee0a45e..a854eaf 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GamesHeader.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor.cs @@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Components; namespace GameIdeas.BlazorApp.Pages.Games.Header; -public partial class GamesHeader : ComponentBase +public partial class GameHeader : ComponentBase { [Parameter] public EventCallback AddTypeChanged { get; set; } [Parameter] public RenderFragment? ChildContent { get; set; } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GamesHeader.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor.css similarity index 100% rename from src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GamesHeader.razor.css rename to src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor.css diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs index eae8c05..25ba67c 100644 --- a/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs +++ b/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs @@ -13,6 +13,4 @@ public class GameFilterDto public IEnumerable? DeveloperIds { get; set; } public IEnumerable? CreationUserIds { get; set; } public IEnumerable? ModificationUserIds { get; set; } - public int CurrentPage { get; set; } - public int NumberPerPage { get; set; } } diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/PaggingDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/PaggingDto.cs new file mode 100644 index 0000000..c006966 --- /dev/null +++ b/src/GameIdeas/GameIdeas.Shared/Dto/PaggingDto.cs @@ -0,0 +1,7 @@ +namespace GameIdeas.Shared.Dto; + +public class PaggingDto +{ + public int CurrentPage { get; set; } + public int NumberPerPage { get; set; } +} diff --git a/src/GameIdeas/GameIdeas.Shared/Exceptions/NotFoundException.cs b/src/GameIdeas/GameIdeas.Shared/Exceptions/NotFoundException.cs new file mode 100644 index 0000000..7467e55 --- /dev/null +++ b/src/GameIdeas/GameIdeas.Shared/Exceptions/NotFoundException.cs @@ -0,0 +1,7 @@ +namespace GameIdeas.Shared.Exceptions; + +public class NotFoundException : Exception +{ + public NotFoundException(string msg, Exception? innerException = null) : base(msg, innerException) + { } +} diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/GameController.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/GameController.cs index ae31a44..382fb85 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/GameController.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/GameController.cs @@ -12,6 +12,6 @@ public class GameController(GameService gameService) : Controller [HttpGet("Search")] public async Task> FetchGames([FromQuery] GameFilterDto filter) { - return await gameService.SearchGames(filter); + return await gameService.GetGames(filter); } } diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/GameService.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/GameService.cs index 9ff1772..de768e3 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/GameService.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/GameService.cs @@ -1,6 +1,6 @@ using AutoMapper; using GameIdeas.Shared.Dto; -using GameIdeas.Shared.Enum; +using GameIdeas.Shared.Exceptions; using GameIdeas.Shared.Model; using GameIdeas.WebAPI.Context; using Microsoft.EntityFrameworkCore; @@ -9,7 +9,7 @@ namespace GameIdeas.WebAPI.Services; public class GameService(GameIdeasContext context, IMapper mapper) { - public async Task> SearchGames(GameFilterDto filter) + public async Task> GetGames(PaggingDto pagging) { var query = context.Games .Include(g => g.CreationUser) @@ -21,40 +21,75 @@ public class GameService(GameIdeasContext context, IMapper mapper) .Include(g => g.GameDevelopers).ThenInclude(p => p.Developer) .AsQueryable(); - ApplyFilter(ref query); - var games = await query .OrderBy(g => g.Title) - .Skip(filter.CurrentPage * filter.NumberPerPage) - .Take(filter.NumberPerPage) + .Skip(pagging.CurrentPage * pagging.NumberPerPage) + .Take(pagging.NumberPerPage) .ToListAsync(); - List gamesTest = [ new () - { - Id = 1, - Title = "Test", - CreationDate = DateTime.Today - TimeSpan.FromHours(-12), - CreationUser = new User() { Id = 1, Username = "Test", Role = (int)Role.Administrator }, - CreationUserId = 1, - Description = "Test", - GameDevelopers = [ new() { Developer = new Developer() { Id = 1, Name = "THQNordic"} }], - GamePlatforms = [ new() { Platform = new Platform() { Id = 1, Label = "Steam" }, Url = "steam.com?app=55554131" }], - GameProperties = [ new () { Property = new Property() { Id = 1, Label = "Coop"} }], - GamePublishers = [ new () { Publisher = new Publisher() { Id = 1, Name = "Take-Two"} }], - GameTags = [ new () { Tag = new Tag() { Id = 1, Label = "RPG" } }], - Interest = 5, - ModificationDate = DateTime.Today , - ModificationUser = new User() { Id = 2, Username = "Test 2", Role = (int)Role.Member }, - ModificationUserId = 2, - ReleaseDate = new DateTime(2025, 2, 1), - StorageSpace = 40 - } ]; - - return mapper.Map>(gamesTest); + return mapper.Map>(games); } - private void ApplyFilter(ref IQueryable query) + public async Task GetGameById(int gameId) { - + var game = await context.Games + .Include(g => g.CreationUser) + .Include(g => g.ModificationUser) + .Include(g => g.GamePlatforms).ThenInclude(p => p.Platform) + .Include(g => g.GameProperties).ThenInclude(p => p.Property) + .Include(g => g.GameTags).ThenInclude(p => p.Tag) + .Include(g => g.GamePublishers).ThenInclude(p => p.Publisher) + .Include(g => g.GameDevelopers).ThenInclude(p => p.Developer) + .FirstOrDefaultAsync(g => g.Id == gameId); + + if (game == null) + { + throw new NotFoundException($"[{typeof(Game).Name}] with ID {gameId} has not been found in context"); + } + + return mapper.Map(game); + } + + public async Task CreateGame(GameDto gameDto) + { + var game = mapper.Map(gameDto); + + context.GameDevelopers.AttachRange(game.GameDevelopers); + context.Developers.AttachRange(game.GameDevelopers.Select(gd => gd.Developer)); + context.GamePlatforms.AttachRange(game.GamePlatforms); + context.Platforms.AttachRange(game.GamePlatforms.Select(gp => gp.Platform)); + context.GameProperties.AttachRange(game.GameProperties); + context.Properties.AttachRange(game.GameProperties.Select(gp => gp.Property)); + context.GamePublishers.AttachRange(game.GamePublishers); + context.Publishers.AttachRange(game.GamePublishers.Select(gp => gp.Publisher)); + context.GameTags.AttachRange(game.GameTags); + context.Tags.AttachRange(game.GameTags.Select(gt => gt.Tag)); + + await context.Games.AddAsync(game); + await context.SaveChangesAsync(); + + return mapper.Map(game); + } + + public async Task UpdateGame(GameDto gameDto) + { + var gameToUpdate = mapper.Map(gameDto); + + context.GameDevelopers.AttachRange(gameToUpdate.GameDevelopers); + context.Developers.AttachRange(gameToUpdate.GameDevelopers.Select(gd => gd.Developer)); + context.GamePlatforms.AttachRange(gameToUpdate.GamePlatforms); + context.Platforms.AttachRange(gameToUpdate.GamePlatforms.Select(gp => gp.Platform)); + context.GameProperties.AttachRange(gameToUpdate.GameProperties); + context.Properties.AttachRange(gameToUpdate.GameProperties.Select(gp => gp.Property)); + context.GamePublishers.AttachRange(gameToUpdate.GamePublishers); + context.Publishers.AttachRange(gameToUpdate.GamePublishers.Select(gp => gp.Publisher)); + context.GameTags.AttachRange(gameToUpdate.GameTags); + context.Tags.AttachRange(gameToUpdate.GameTags.Select(gt => gt.Tag)); + + + context.Games.Update(gameToUpdate); + await context.SaveChangesAsync(); + + return mapper.Map(gameToUpdate); } }