Add services and controllers for games (#12)
Co-authored-by: Maxime Adler <madler@sqli.com> Reviewed-on: #12
This commit was merged in pull request #12.
This commit is contained in:
@@ -21,7 +21,7 @@ public partial class GameFilter
|
||||
];
|
||||
|
||||
private readonly IEnumerable<SelectElement<Func<GameDto?, object?>>> GameProperties = [
|
||||
new() { Item = game => game?.Name, Label = "Nom", IsSelected = true },
|
||||
new() { Item = game => game?.Title, Label = "Nom", IsSelected = true },
|
||||
new() { Item = game => game?.ReleaseDate, Label = "Date de parution" }
|
||||
];
|
||||
|
||||
@@ -40,7 +40,7 @@ public partial class GameFilter
|
||||
];
|
||||
|
||||
private EditContext? EditContext;
|
||||
private SliderRangeParams SliderRangeParams =
|
||||
private readonly SliderRangeParams SliderRangeParams =
|
||||
new() { Min = 1, ValueMin = 1, ValueMax = 5, Max = 5 };
|
||||
|
||||
protected override void OnInitialized()
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
|
||||
<PageTitle>@ResourcesKey.GamesIdeas</PageTitle>
|
||||
|
||||
<GamesHeader>
|
||||
<GameHeader>
|
||||
<GameFilter @bind-DisplayType=DisplayType
|
||||
@bind-GameFilterParams=GameFilterParams />
|
||||
</GamesHeader>
|
||||
</GameHeader>
|
||||
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
@@ -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();
|
||||
@@ -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<AddType> AddTypeChanged { get; set; }
|
||||
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||
7
src/GameIdeas/GameIdeas.Shared/Dto/DeveloperDto.cs
Normal file
7
src/GameIdeas/GameIdeas.Shared/Dto/DeveloperDto.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace GameIdeas.Shared.Dto;
|
||||
|
||||
public class DeveloperDto
|
||||
{
|
||||
public int? Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
}
|
||||
@@ -2,6 +2,21 @@
|
||||
|
||||
public class GameDto
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public string? ReleaseDate { get; set; }
|
||||
public int? Id { get; set; }
|
||||
public string? Title { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public DateTime? CreationDate { get; set; }
|
||||
public UserDto? CreationUser { get; set; }
|
||||
public int? CreationUserId { get; set; }
|
||||
public DateTime? ModificationDate { get; set; }
|
||||
public UserDto? ModificationUser { get; set; }
|
||||
public int? ModificationUserId { get; set; }
|
||||
public double? StorageSpace { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public int? Interest { get; set; }
|
||||
public IEnumerable<PlatformDto>? Platforms { get; set; }
|
||||
public IEnumerable<PropertyDto>? Properties { get; set; }
|
||||
public IEnumerable<TagDto>? Tags { get; set; }
|
||||
public IEnumerable<PublisherDto>? Publishers { get; set; }
|
||||
public IEnumerable<DeveloperDto>? Developers { get; set; }
|
||||
}
|
||||
16
src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs
Normal file
16
src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace GameIdeas.Shared.Dto;
|
||||
|
||||
public class GameFilterDto
|
||||
{
|
||||
public IEnumerable<string>? Platforms { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public IEnumerable<string>? Tags { get; set; }
|
||||
public IEnumerable<string>? Properties { get; set; }
|
||||
public int? MinInterest { get; set; }
|
||||
public int? MaxInterest { get; set; }
|
||||
public IEnumerable<int>? ReleaseYears { get; set; }
|
||||
public IEnumerable<int>? PublisherIds { get; set; }
|
||||
public IEnumerable<int>? DeveloperIds { get; set; }
|
||||
public IEnumerable<int>? CreationUserIds { get; set; }
|
||||
public IEnumerable<int>? ModificationUserIds { get; set; }
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
namespace GameIdeas.Shared.Dto;
|
||||
using GameIdeas.Shared.Enum;
|
||||
|
||||
namespace GameIdeas.Shared.Dto;
|
||||
|
||||
public class LoginDto
|
||||
{
|
||||
public int? Id { get; set; }
|
||||
public string? Username { get; set; }
|
||||
public string? Password { get; set; }
|
||||
public Role? Role { get; set; }
|
||||
}
|
||||
|
||||
7
src/GameIdeas/GameIdeas.Shared/Dto/PaggingDto.cs
Normal file
7
src/GameIdeas/GameIdeas.Shared/Dto/PaggingDto.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace GameIdeas.Shared.Dto;
|
||||
|
||||
public class PaggingDto
|
||||
{
|
||||
public int CurrentPage { get; set; }
|
||||
public int NumberPerPage { get; set; }
|
||||
}
|
||||
8
src/GameIdeas/GameIdeas.Shared/Dto/PlatformDto.cs
Normal file
8
src/GameIdeas/GameIdeas.Shared/Dto/PlatformDto.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace GameIdeas.Shared.Dto;
|
||||
|
||||
public class PlatformDto
|
||||
{
|
||||
public int? Id { get; set; }
|
||||
public string? Label { get; set; }
|
||||
public string? Url { get; set; }
|
||||
}
|
||||
7
src/GameIdeas/GameIdeas.Shared/Dto/PropertyDto.cs
Normal file
7
src/GameIdeas/GameIdeas.Shared/Dto/PropertyDto.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace GameIdeas.Shared.Dto;
|
||||
|
||||
public class PropertyDto
|
||||
{
|
||||
public int? Id { get; set; }
|
||||
public string? Label { get; set; }
|
||||
}
|
||||
7
src/GameIdeas/GameIdeas.Shared/Dto/PublisherDto.cs
Normal file
7
src/GameIdeas/GameIdeas.Shared/Dto/PublisherDto.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace GameIdeas.Shared.Dto;
|
||||
|
||||
public class PublisherDto
|
||||
{
|
||||
public int? Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
}
|
||||
8
src/GameIdeas/GameIdeas.Shared/Dto/TagDto.cs
Normal file
8
src/GameIdeas/GameIdeas.Shared/Dto/TagDto.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
namespace GameIdeas.Shared.Dto;
|
||||
|
||||
public class TagDto
|
||||
{
|
||||
public int? Id { get; set; }
|
||||
public string? Label { get; set; }
|
||||
}
|
||||
11
src/GameIdeas/GameIdeas.Shared/Dto/UserDto.cs
Normal file
11
src/GameIdeas/GameIdeas.Shared/Dto/UserDto.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using GameIdeas.Shared.Enum;
|
||||
|
||||
namespace GameIdeas.Shared.Dto;
|
||||
|
||||
public class UserDto
|
||||
{
|
||||
public int? Id { get; set; }
|
||||
public string? Username { get; set; }
|
||||
public string? Password { get; set; }
|
||||
public Role? Role { get; set; }
|
||||
}
|
||||
8
src/GameIdeas/GameIdeas.Shared/Enum/Role.cs
Normal file
8
src/GameIdeas/GameIdeas.Shared/Enum/Role.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace GameIdeas.Shared.Enum;
|
||||
|
||||
public enum Role
|
||||
{
|
||||
Guest = 1,
|
||||
Member = 2,
|
||||
Administrator = 3
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace GameIdeas.Shared.Exceptions;
|
||||
|
||||
public class NotFoundException(string msg, Exception? innerException = null) : Exception(msg, innerException);
|
||||
@@ -8,7 +8,7 @@ public partial class Platform
|
||||
}
|
||||
|
||||
public int Id { get; set; }
|
||||
public string Libelle { get; set; } = null!;
|
||||
public string Label { get; set; } = null!;
|
||||
|
||||
public virtual ICollection<GamePlatform> GamePlatforms { get; set; }
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@ public class GameIdeasContext : DbContext
|
||||
{
|
||||
public GameIdeasContext(DbContextOptions<GameIdeasContext> option)
|
||||
: base(option)
|
||||
{ }
|
||||
{
|
||||
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
||||
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
|
||||
}
|
||||
|
||||
public virtual DbSet<User> Users { get; set; } = null!;
|
||||
public virtual DbSet<Developer> Developers { get; set; } = null!;
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
using GameIdeas.Shared.Dto;
|
||||
using GameIdeas.WebAPI.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace GameIdeas.WebAPI.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
|
||||
public class GameController(GameService gameService, ILoggerFactory loggerFactory) : Controller
|
||||
{
|
||||
private readonly ILogger<GameController> logger = loggerFactory.CreateLogger<GameController>();
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<IEnumerable<GameDto>>> SearchGames([FromQuery] PaggingDto pagging)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await gameService.GetGames(pagging));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Internal error while search games");
|
||||
return StatusCode(500, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("{id:int}")]
|
||||
public async Task<ActionResult<GameDto>> GetGameById(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await gameService.GetGameById(id));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Internal error while get game with id {id}", id);
|
||||
return StatusCode(500, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("Create")]
|
||||
public async Task<ActionResult<GameDto>> CreateGame([FromBody] GameDto game)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Created("/Create", await gameService.CreateGame(game));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Internal error while create game");
|
||||
return StatusCode(500, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut("Update")]
|
||||
public async Task<ActionResult<GameDto>> UpdateGame([FromBody] GameDto game)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Created($"/Update", await gameService.UpdateGame(game));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Internal error while update game");
|
||||
return StatusCode(500, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("Delete/{id:int}")]
|
||||
public async Task<ActionResult<bool>> DeleteGame(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await gameService.DeleteGame(id));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Internal error while delete game");
|
||||
return StatusCode(500, e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.4">
|
||||
|
||||
@@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace GameIdeas.WebAPI.Migrations
|
||||
{
|
||||
[DbContext(typeof(GameIdeasContext))]
|
||||
[Migration("20250409210640_InitialCreate")]
|
||||
[Migration("20250409225125_InitialCreate")]
|
||||
partial class InitialCreate
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@@ -176,7 +176,7 @@ namespace GameIdeas.WebAPI.Migrations
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Libelle")
|
||||
b.Property<string>("Label")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace GameIdeas.WebAPI.Migrations
|
||||
{
|
||||
Id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
Libelle = table.Column<string>(type: "text", nullable: false)
|
||||
Label = table.Column<string>(type: "text", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
@@ -173,7 +173,7 @@ namespace GameIdeas.WebAPI.Migrations
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Libelle")
|
||||
b.Property<string>("Label")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
using AutoMapper;
|
||||
using GameIdeas.Shared.Dto;
|
||||
using GameIdeas.Shared.Model;
|
||||
|
||||
namespace GameIdeas.WebAPI.Profiles;
|
||||
|
||||
public class CategoryProfile : Profile
|
||||
{
|
||||
public CategoryProfile()
|
||||
{
|
||||
CreatePlaformMap();
|
||||
CreatePropertyMap();
|
||||
CreateTagMap();
|
||||
CreateDeveloperMap();
|
||||
CreatePublisherMap();
|
||||
}
|
||||
|
||||
private void CreatePublisherMap()
|
||||
{
|
||||
CreateMap<Publisher, PublisherDto>()
|
||||
.ForMember(d => d.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForMember(d => d.Name, o => o.MapFrom(s => s.Name))
|
||||
.ReverseMap();
|
||||
|
||||
CreateMap<PublisherDto, GamePublisher>()
|
||||
.ForMember(d => d.PublisherId, o => o.MapFrom(s => s.Id))
|
||||
.ForPath(d => d.Publisher.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForPath(d => d.Publisher.Name, o => o.MapFrom(s => s.Name));
|
||||
}
|
||||
|
||||
private void CreateDeveloperMap()
|
||||
{
|
||||
CreateMap<Developer, DeveloperDto>()
|
||||
.ForMember(d => d.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForMember(d => d.Name, o => o.MapFrom(s => s.Name))
|
||||
.ReverseMap();
|
||||
|
||||
CreateMap<DeveloperDto, GameDeveloper>()
|
||||
.ForMember(d => d.DeveloperId, o => o.MapFrom(s => s.Id))
|
||||
.ForPath(d => d.Developer.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForPath(d => d.Developer.Name, o => o.MapFrom(s => s.Name));
|
||||
}
|
||||
|
||||
private void CreateTagMap()
|
||||
{
|
||||
CreateMap<Tag, TagDto>()
|
||||
.ForMember(d => d.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForMember(d => d.Label, o => o.MapFrom(s => s.Label))
|
||||
.ReverseMap();
|
||||
|
||||
CreateMap<TagDto, GameTag>()
|
||||
.ForMember(d => d.TagId, o => o.MapFrom(s => s.Id))
|
||||
.ForPath(d => d.Tag.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForPath(d => d.Tag.Label, o => o.MapFrom(s => s.Label));
|
||||
}
|
||||
|
||||
private void CreatePropertyMap()
|
||||
{
|
||||
CreateMap<Property, PropertyDto>()
|
||||
.ForMember(d => d.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForMember(d => d.Label, o => o.MapFrom(s => s.Label))
|
||||
.ReverseMap();
|
||||
|
||||
CreateMap<PropertyDto, GameProperty>()
|
||||
.ForMember(d => d.PropertyId, o => o.MapFrom(s => s.Id))
|
||||
.ForPath(d => d.Property.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForPath(d => d.Property.Label, o => o.MapFrom(s => s.Label));
|
||||
}
|
||||
|
||||
private void CreatePlaformMap()
|
||||
{
|
||||
CreateMap<Platform, PlatformDto>()
|
||||
.ForMember(d => d.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForMember(d => d.Label, o => o.MapFrom(s => s.Label))
|
||||
.ReverseMap();
|
||||
|
||||
CreateMap<PlatformDto, GamePlatform>()
|
||||
.ForMember(d => d.PlatformId, o => o.MapFrom(s => s.Id))
|
||||
.ForPath(d => d.Platform.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForPath(d => d.Platform.Label, o => o.MapFrom(s => s.Label))
|
||||
.ForMember(d => d.Url, o => o.MapFrom(s => s.Url));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using AutoMapper;
|
||||
using GameIdeas.Shared.Dto;
|
||||
using GameIdeas.Shared.Model;
|
||||
|
||||
namespace GameIdeas.WebAPI.Profiles;
|
||||
|
||||
public class GameProfile : Profile
|
||||
{
|
||||
public GameProfile()
|
||||
{
|
||||
CreateMap<Game, GameDto>()
|
||||
.ForMember(d => d.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForMember(d => d.Title, o => o.MapFrom(s => s.Title))
|
||||
.ForMember(d => d.ReleaseDate, o => o.MapFrom(s => s.ReleaseDate))
|
||||
.ForMember(d => d.CreationDate, o => o.MapFrom(s => s.CreationDate))
|
||||
.ForMember(d => d.CreationUserId, o => o.MapFrom(s => s.CreationUserId))
|
||||
.ForMember(d => d.CreationUser, o => o.MapFrom(s => s.CreationUser))
|
||||
.ForMember(d => d.ModificationDate, o => o.MapFrom(s => s.ModificationDate))
|
||||
.ForMember(d => d.ModificationUserId, o => o.MapFrom(s => s.ModificationUserId))
|
||||
.ForMember(d => d.ModificationUser, o => o.MapFrom(s => s.ModificationUser))
|
||||
.ForMember(d => d.StorageSpace, o => o.MapFrom(s => s.StorageSpace))
|
||||
.ForMember(d => d.Description, o => o.MapFrom(s => s.Description))
|
||||
.ForMember(d => d.Interest, o => o.MapFrom(s => s.Interest))
|
||||
.ForMember(d => d.Platforms, o => o.MapFrom(s => s.GamePlatforms.Select(p => new PlatformDto() { Id = p.Platform.Id, Label = p.Platform.Label, Url = p.Url })))
|
||||
.ForMember(d => d.Properties, o => o.MapFrom(s => s.GameProperties.Select(p => p.Property)))
|
||||
.ForMember(d => d.Tags, o => o.MapFrom(s => s.GameTags.Select(t => t.Tag)))
|
||||
.ForMember(d => d.Publishers, o => o.MapFrom(s => s.GamePublishers.Select(p => p.Publisher)))
|
||||
.ForMember(d => d.Developers, o => o.MapFrom(s => s.GameDevelopers.Select(gd => gd.Developer)))
|
||||
.ReverseMap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using AutoMapper;
|
||||
using GameIdeas.Shared.Dto;
|
||||
using GameIdeas.Shared.Enum;
|
||||
using GameIdeas.Shared.Model;
|
||||
|
||||
namespace GameIdeas.WebAPI.Profiles;
|
||||
|
||||
public class UserProfile : Profile
|
||||
{
|
||||
public UserProfile()
|
||||
{
|
||||
CreateMap<User, UserDto>()
|
||||
.ForMember(d => d.Id, o => o.MapFrom(s => s.Id))
|
||||
.ForMember(d => d.Username, o => o.MapFrom(s => s.Username))
|
||||
.ForMember(d => d.Password, o => o.MapFrom(s => s.Password))
|
||||
.ForMember(d => d.Role, o => o.MapFrom(s => s.Role))
|
||||
.ReverseMap();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
using GameIdeas.Resources;
|
||||
using GameIdeas.WebAPI.Context;
|
||||
using GameIdeas.WebAPI.Profiles;
|
||||
using GameIdeas.WebAPI.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var services = builder.Services;
|
||||
|
||||
#if DEBUG
|
||||
Load("../../../../.env");
|
||||
LoadEnvironmentVariable("../../../../.env");
|
||||
#else
|
||||
Load(".env");
|
||||
LoadEnvironmentVariable(".env");
|
||||
#endif
|
||||
|
||||
Action<DbContextOptionsBuilder> dbContextOptions = options =>
|
||||
@@ -22,8 +22,7 @@ Action<DbContextOptionsBuilder> dbContextOptions = options =>
|
||||
{
|
||||
npgOption.CommandTimeout(60);
|
||||
npgOption.MigrationsAssembly("GameIdeas.WebAPI");
|
||||
})
|
||||
.LogTo(Console.WriteLine);
|
||||
});
|
||||
};
|
||||
|
||||
// Add services to the container.
|
||||
@@ -32,7 +31,14 @@ services.AddDbContext<GameIdeasContext>(dbContextOptions);
|
||||
services.AddSingleton<TranslationService>();
|
||||
services.AddSingleton<Translations>();
|
||||
|
||||
services.AddScoped<GameService>();
|
||||
|
||||
services.AddAutoMapper(typeof(GameProfile).Assembly);
|
||||
services.AddAutoMapper(typeof(UserProfile).Assembly);
|
||||
services.AddAutoMapper(typeof(CategoryProfile).Assembly);
|
||||
|
||||
services.AddControllers();
|
||||
|
||||
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
|
||||
services.AddOpenApi();
|
||||
|
||||
@@ -40,6 +46,7 @@ services.AddCors(option => option.AddDefaultPolicy(policy =>
|
||||
policy.WithOrigins("http://localhost:5172", "http://localhost:7060")
|
||||
.AllowAnyHeader()
|
||||
.WithMethods("GET", "POST", "PUT", "DELETE")));
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
await LoadTranslations();
|
||||
@@ -85,7 +92,7 @@ string GetConnectionString()
|
||||
return $"Host={host};Username={login};Password={pass};Database={database}";
|
||||
}
|
||||
|
||||
static void Load(string filePath)
|
||||
static void LoadEnvironmentVariable(string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
return;
|
||||
|
||||
174
src/GameIdeas/Server/GameIdeas.WebAPI/Services/GameService.cs
Normal file
174
src/GameIdeas/Server/GameIdeas.WebAPI/Services/GameService.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
using AutoMapper;
|
||||
using GameIdeas.Shared.Dto;
|
||||
using GameIdeas.Shared.Exceptions;
|
||||
using GameIdeas.Shared.Model;
|
||||
using GameIdeas.WebAPI.Context;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace GameIdeas.WebAPI.Services;
|
||||
|
||||
public class GameService(GameIdeasContext context, IMapper mapper)
|
||||
{
|
||||
public async Task<IEnumerable<GameDto>> GetGames(PaggingDto pagging)
|
||||
{
|
||||
var games = await SelectGames()
|
||||
.OrderBy(g => g.Title)
|
||||
.Skip((pagging.CurrentPage - 1) * pagging.NumberPerPage)
|
||||
.Take(pagging.NumberPerPage)
|
||||
.ToListAsync();
|
||||
|
||||
return mapper.Map<IEnumerable<GameDto>>(games);
|
||||
}
|
||||
|
||||
public async Task<GameDto> GetGameById(int gameId)
|
||||
{
|
||||
var game = await SelectGames()
|
||||
.FirstOrDefaultAsync(g => g.Id == gameId);
|
||||
|
||||
return game == null
|
||||
? throw new NotFoundException($"[{typeof(Game).FullName}] with ID {gameId} has not been found in context")
|
||||
: mapper.Map<GameDto>(game);
|
||||
}
|
||||
|
||||
public async Task<GameDto> CreateGame(GameDto gameDto)
|
||||
{
|
||||
var gameToCreate = mapper.Map<Game>(gameDto);
|
||||
|
||||
await context.Games.AddAsync(gameToCreate);
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
await HandlePlatformsCreation(gameDto.Platforms, gameToCreate.Id);
|
||||
await HandlePropertiesCreation(gameDto.Properties, gameToCreate.Id);
|
||||
await HandleTagsCreation(gameDto.Tags, gameToCreate.Id);
|
||||
await HandlePublishersCreation(gameDto.Publishers, gameToCreate.Id);
|
||||
await HandleDevelopersCreation(gameDto.Developers, gameToCreate.Id);
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
return mapper.Map<GameDto>(gameToCreate);
|
||||
}
|
||||
|
||||
public async Task<GameDto> UpdateGame(GameDto gameDto)
|
||||
{
|
||||
if (await context.Games.CountAsync(g => g.Id == gameDto.Id) == 0)
|
||||
{
|
||||
throw new NotFoundException($"[{typeof(Game).FullName}] with ID {gameDto.Id} has not been found in context");
|
||||
}
|
||||
|
||||
var gameToUpdate = mapper.Map<Game>(gameDto);
|
||||
|
||||
await HandlePlatformsCreation(gameDto.Platforms, gameToUpdate.Id);
|
||||
await HandlePropertiesCreation(gameDto.Properties, gameToUpdate.Id);
|
||||
await HandleTagsCreation(gameDto.Tags, gameToUpdate.Id);
|
||||
await HandlePublishersCreation(gameDto.Publishers, gameToUpdate.Id);
|
||||
await HandleDevelopersCreation(gameDto.Developers, gameToUpdate.Id);
|
||||
|
||||
context.Games.Update(gameToUpdate);
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
return mapper.Map<GameDto>(gameToUpdate);
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteGame(int gameId)
|
||||
{
|
||||
var gameToRemove = await context.Games
|
||||
.FirstOrDefaultAsync(g => g.Id == gameId)
|
||||
?? throw new NotFoundException($"[{typeof(Game).FullName}] with ID {gameId} has not been found in context");
|
||||
|
||||
context.Games.Remove(gameToRemove);
|
||||
return await context.SaveChangesAsync() != 0;
|
||||
}
|
||||
|
||||
private IQueryable<Game> SelectGames()
|
||||
{
|
||||
return 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)
|
||||
.AsQueryable();
|
||||
}
|
||||
|
||||
private async Task HandlePlatformsCreation(IEnumerable<PlatformDto>? categoriesToCreate, int gameId)
|
||||
{
|
||||
if (categoriesToCreate != null)
|
||||
{
|
||||
var gps = mapper.Map<ICollection<GamePlatform>>(categoriesToCreate);
|
||||
|
||||
foreach (var gp in gps)
|
||||
{
|
||||
gp.GameId = gameId;
|
||||
}
|
||||
|
||||
context.Platforms.AttachRange(gps.Select(gp => gp.Platform));
|
||||
await context.GamePlatforms.AddRangeAsync(gps);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandlePropertiesCreation(IEnumerable<PropertyDto>? categoriesToCreate, int gameId)
|
||||
{
|
||||
if (categoriesToCreate != null)
|
||||
{
|
||||
var gps = mapper.Map<ICollection<GameProperty>>(categoriesToCreate);
|
||||
|
||||
foreach (var gp in gps)
|
||||
{
|
||||
gp.GameId = gameId;
|
||||
}
|
||||
|
||||
context.Properties.AttachRange(gps.Select(gp => gp.Property));
|
||||
await context.GameProperties.AddRangeAsync(gps);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleTagsCreation(IEnumerable<TagDto>? categoriesToCreate, int gameId)
|
||||
{
|
||||
if (categoriesToCreate != null)
|
||||
{
|
||||
var gts = mapper.Map<ICollection<GameTag>>(categoriesToCreate);
|
||||
|
||||
foreach (var gt in gts)
|
||||
{
|
||||
gt.GameId = gameId;
|
||||
}
|
||||
|
||||
context.Tags.AttachRange(gts.Select(gt => gt.Tag));
|
||||
await context.GameTags.AddRangeAsync(gts);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandlePublishersCreation(IEnumerable<PublisherDto>? categoriesToCreate, int gameId)
|
||||
{
|
||||
if (categoriesToCreate != null)
|
||||
{
|
||||
var gps = mapper.Map<ICollection<GamePublisher>>(categoriesToCreate);
|
||||
|
||||
foreach (var gp in gps)
|
||||
{
|
||||
gp.GameId = gameId;
|
||||
}
|
||||
|
||||
context.Publishers.AttachRange(gps.Select(gp => gp.Publisher));
|
||||
await context.GamePublishers.AddRangeAsync(gps);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleDevelopersCreation(IEnumerable<DeveloperDto>? categoriesToCreate, int gameId)
|
||||
{
|
||||
if (categoriesToCreate != null)
|
||||
{
|
||||
var gds = mapper.Map<ICollection<GameDeveloper>>(categoriesToCreate);
|
||||
|
||||
foreach (var gd in gds)
|
||||
{
|
||||
gd.GameId = gameId;
|
||||
}
|
||||
|
||||
context.Developers.AttachRange(gds.Select(gd => gd.Developer));
|
||||
await context.GameDevelopers.AddRangeAsync(gds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace GameIdeas.WebAPI.Services;
|
||||
|
||||
public class UserService
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user