diff --git a/Sources/ApiLol/ApiLol.csproj b/Sources/ApiLol/ApiLol.csproj index f4484e6..8d2cf78 100644 --- a/Sources/ApiLol/ApiLol.csproj +++ b/Sources/ApiLol/ApiLol.csproj @@ -4,10 +4,18 @@ net6.0 enable enable + $(MSBuildProjectDirectory) + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + @@ -28,5 +36,8 @@ + + + diff --git a/Sources/ApiLol/Controllers/ChampionController.cs b/Sources/ApiLol/Controllers/ChampionController.cs index aefc8ea..9644221 100644 --- a/Sources/ApiLol/Controllers/ChampionController.cs +++ b/Sources/ApiLol/Controllers/ChampionController.cs @@ -6,6 +6,8 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Model; +using Microsoft.Extensions.Logging; +using DataManagers; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 @@ -16,82 +18,111 @@ namespace ApiLol.Controllers { private readonly ILogger _logger; - private StubData.ChampionsManager championsManager = new StubData.ChampionsManager(new StubData()); + private IDataManager dataManager; - public ChampionController(ILogger logger) + public ChampionController(ILogger logger, IDataManager manager) { _logger = logger; + dataManager = manager; } - // GET: api/champion - [HttpGet] - public async Task>> Get() + [HttpGet("GetChampions")] + public async Task>> GetChampions(int nb = 3) { - IEnumerable champs = await championsManager.GetItems(0, await championsManager.GetNbItems()); - IEnumerable championDTOs = champs.ToDtos(); + var champions = await dataManager.ChampionsMgr.GetItems(0, nb); + _logger.Log(LogLevel.Information, $"Les champions ont bien été envoyées"); + return Ok(champions.ToDtos()); - return Ok(championDTOs); } - /* - // GET api/champion/5 - [HttpGet("{id}")] - public ActionResult Get(int id) + // GET api/champion/name + [HttpGet("getChampions/{name}")] + public async Task> GetChampionsByName(string name, int nb =3, int index = 0) { - ChampionDTO? champion = champions.SingleOrDefault((ChampionEntity arg) => arg.Id == id)?.ToDto(); + IEnumerable champion = await dataManager.ChampionsMgr.GetItemsByName(name, index, nb); if (champion != null) { - return Ok(champion); + return Ok(champion.ToDtos()); } return BadRequest(); } - */ - // POST api/champion - [HttpPost] - public ActionResult Post([FromBody]ChampionDTO? champion) + [HttpPost("PostChampion")] + public async Task> PostChampion(ChampionDTO champ) { - if (champion == null){ - return BadRequest(); - } - else + var c = await dataManager.ChampionsMgr.AddItem(ChampionMapper.ToPoco(champ)); + if (c != null) { - championsManager.AddItem(champion.ToPoco()); - return Ok(); + _logger.Log(LogLevel.Information, "Le champion a été ajouté à la base"); + return Ok(c); } + return BadRequest(); + } - // PUT api/champion/5 - [HttpPut("ChampionDto")] - public ActionResult Put([FromBody] ChampionDTO? champion, ChampionDTO? newChampion) + [HttpPost("PostChampions")] + public async Task>> PostChampions(List champs) { - if (champion == null || newChampion == null) + var list = new List(); + foreach (ChampionDTO champ in champs) { - return BadRequest(); + var c = await dataManager.ChampionsMgr.AddItem(ChampionMapper.ToPoco(champ)); + if ( c != null) + { + list.Add(c.ToDto()); + _logger.Log(LogLevel.Information, $"Le champion {champ.Name} a été ajouté à la base"); + } + else + { + _logger.Log(LogLevel.Information, $"Le champion {champ.Name} n'a pas été ajouté à la base"); + } } - else + return Ok(list); + } + + [HttpPut("PutChampion")] + public async Task> Put(ChampionDTO oldChamp, ChampionDTO champ) + { + var c = await dataManager.ChampionsMgr.UpdateItem(oldChamp.ToPoco(), champ.ToPoco()); + if (c!=null) { - championsManager.UpdateItem(champion.ToPoco(), newChampion.ToPoco()); - return Ok(); + _logger.Log(LogLevel.Information, $"Le champion {champ.Name} a été modifié "); + return Ok(c); } + _logger.Log(LogLevel.Information, $"Le champion {champ.Name} n'a pas été modifié"); + return BadRequest(); } - // DELETE api/values/5 + // DELETE api/values [HttpDelete("ChampionDto")] - public ActionResult Delete([FromBody] ChampionDTO? champion) + public async Task DeleteChampion([FromBody] ChampionDTO champion) { - if (champion == null) + if (await dataManager.ChampionsMgr.DeleteItem(champion.ToPoco())) { - return BadRequest(); + return Ok(); } - else + return BadRequest(); + } + + [HttpDelete("DeleteChampions")] + public async Task>> DeleteChampions(List champions, int nb = 10) + { + foreach (ChampionDTO champ in champions) { - championsManager.DeleteItem(champion.ToPoco()); - return Ok(); + if (await dataManager.ChampionsMgr.DeleteItem(champ.ToPoco())) + { + _logger.Log(LogLevel.Information, $"Le champion {champ.Name} a été supprimé"); + } + else + { + _logger.Log(LogLevel.Information, $"Le champion {champ.Name} n'a pas été supprimé"); + } } + return Ok(); } + } } diff --git a/Sources/ApiLol/Controllers/RuneController.cs b/Sources/ApiLol/Controllers/RuneController.cs new file mode 100644 index 0000000..fc50054 --- /dev/null +++ b/Sources/ApiLol/Controllers/RuneController.cs @@ -0,0 +1,153 @@ +using ApiLol.DTO; +using ApiLol.Mapping; +using Microsoft.AspNetCore.Mvc; +using Model; +using StubLib; +using System.Data; +using System.Text; + +namespace API.Controllers +{ + [ApiController] + [Route("api/[controller]")] + public class RuneController : Controller + { + private readonly ILogger _logger; + + private IDataManager dataManager = new StubData(); + + + public RuneController(ILogger logger) + { + _logger = logger; + } + + [HttpGet("GetRune/{name}")] + public async Task>> GetRune(string name, int nb=3, int index = 0) + { + var runes = await dataManager.RunesMgr.GetItemsByName(name, index, nb); + if (!runes.Any()) + { + _logger.Log(LogLevel.Warning, $"La rune {name} n'existe pas"); + return BadRequest(name); + } + else + { + _logger.Log(LogLevel.Information, $"Les runes avec {name} ont été envoyées"); + return Ok(runes.Select(x => x?.ToDto())); + } + + } + + [HttpGet("GetRunes")] + public async Task>> GetRunes(int nb = 15) + { + var runes = await dataManager.RunesMgr.GetItems(0, nb); + return Ok(runes.Select(x => x?.ToDto())); + } + + [HttpPost("PostRune")] + public async Task> PostRune(RuneDTO rune) + { + var r = await dataManager.RunesMgr.AddItem(rune.ToPoco()); + if (r != null) + { + _logger.Log(LogLevel.Information, $"La Rune {rune.Name} a été ajouté à la base"); + return Ok(r.ToDto()); + + } + return BadRequest(r); + } + + [HttpPost("PostRunes")] + public async Task>> PostRunes(List runes) + { + var l = new List(); + foreach (RuneDTO rune in runes) + { + var r = await dataManager.RunesMgr.AddItem(rune.ToPoco()); + if (r != null) + { + l.Add(r.ToDto()); + _logger.Log(LogLevel.Information, $"La Rune {rune.Name} a été ajoutée à la base"); + } + else + { + _logger.Log(LogLevel.Warning, $"La Rune {rune.Name} recherchée n'existe pas ou il y en a plusieurs avec ce nom"); + } + } + return Ok(l); + } + + [HttpPut("PutRune")] + public async Task> PutRune(RuneDTO rune) + { + var ancienne = await dataManager.RunesMgr.GetItemsByName(rune.Name, 0, 1); + if (ancienne.Count() != 1) + { + _logger.Log(LogLevel.Warning, $"La Rune {rune.Name} recherchée n'existe pas ou il y en a plusieurs avec ce nom"); + return BadRequest(rune); + } + else + { + await dataManager.RunesMgr.UpdateItem(ancienne.FirstOrDefault(), rune.ToPoco()); + _logger.Log(LogLevel.Information, $"La Rune {rune.Name} a été modifiée de la base"); + var r = await dataManager.RunesMgr.GetItemsByName(rune.Name, 0, 1); + return Ok(r.First()); + } + } + + [HttpPut("PutRunes")] + public async Task>> PutRunes(List runes, int nb = 10) + { + foreach (RuneDTO run in runes) + { + var rune = await dataManager.RunesMgr.GetItemsByName(run.Name, 0, 1); + if (!rune.Any()) + { + _logger.Log(LogLevel.Warning, $"La Rune {run.Name} recherchée n'existe pas"); + BadRequest(run); + } + else + { + await dataManager.RunesMgr.UpdateItem(rune.FirstOrDefault(), run.ToPoco()); + _logger.Log(LogLevel.Information, $"La Rune {run.Name} a été modifiée de la base"); + + } + } + var Runes = await dataManager.RunesMgr.GetItems(0, nb); + return Ok(Runes.Select(x => x?.ToDto())); + } + + [HttpDelete("DeleteRune")] + public async Task> DeleteRune(RuneDTO rune) + { + var retour = await dataManager.RunesMgr.DeleteItem(rune.ToPoco()); + if (retour) { + _logger.Log(LogLevel.Information, $"La Rune {rune.Name} a été supprimée de la base"); + return Ok(retour); + } + _logger.Log(LogLevel.Warning, $"La Rune {rune.Name} recherchée n'existe pas"); + return BadRequest(retour); + } + + [HttpDelete("DeleteRunes")] + public async Task> DeleteRunes(List runes) + { + foreach (RuneDTO run in runes) + { + var retour = await dataManager.RunesMgr.DeleteItem(run.ToPoco()); + if (!retour) + { + _logger.Log(LogLevel.Warning, $"La Rune {run.Name} recherchée n'existe pas"); + BadRequest(run); + } + else + { + _logger.Log(LogLevel.Information, $"La Rune {run.Name} a été supprimée de la base"); + } + } + return Ok(true); + } + } +} \ No newline at end of file diff --git a/Sources/ApiLol/DTO/ChampionDTO.cs b/Sources/ApiLol/DTO/ChampionDTO.cs index 240ce8d..0fd7d6b 100644 --- a/Sources/ApiLol/DTO/ChampionDTO.cs +++ b/Sources/ApiLol/DTO/ChampionDTO.cs @@ -16,11 +16,11 @@ namespace ApiLol public ChampionClass ChampClass { get; set; } - public LargeImage Image { get; set; } + //public LargeImage Image { get; set; } public IEnumerable Characteristics { get; set; } - public IEnumerable Skins { get; set; } + //public IEnumerable Skins { get; set; } } } diff --git a/Sources/ApiLol/DTO/RuneDTO.cs b/Sources/ApiLol/DTO/RuneDTO.cs index 7bbf289..cad134f 100644 --- a/Sources/ApiLol/DTO/RuneDTO.cs +++ b/Sources/ApiLol/DTO/RuneDTO.cs @@ -5,17 +5,15 @@ namespace ApiLol.DTO { public class RuneDTO { - public string Nom { get; set; } - public string Description { get; set; } - public string Famille { get; set; } + public RuneFamily Family { get; set; } public string Icon { get; set; } public string Name { get; set; } - public LargeImage Image { get; set; } + //public LargeImage Image { get; set; } } diff --git a/Sources/ApiLol/DTO/SkinDTO.cs b/Sources/ApiLol/DTO/SkinDTO.cs index b0f1ec5..451c2a6 100644 --- a/Sources/ApiLol/DTO/SkinDTO.cs +++ b/Sources/ApiLol/DTO/SkinDTO.cs @@ -13,7 +13,7 @@ namespace ApiLol.DTO public string Icon { get; set; } - public LargeImage Image { get; set; } + //public LargeImage Image { get; set; } } } diff --git a/Sources/ApiLol/Mapping/ChampionMapper.cs b/Sources/ApiLol/Mapping/ChampionMapper.cs index bc27995..25473cf 100644 --- a/Sources/ApiLol/Mapping/ChampionMapper.cs +++ b/Sources/ApiLol/Mapping/ChampionMapper.cs @@ -20,8 +20,8 @@ namespace ApiLol Bio = champion.Bio, Icon = champion.Icon, ChampClass = champion.Class, - Image = champion.Image, - Skins = champion.Skins, + //Image = champion.Image, + //Skins = champion.Skins, Characteristics = champion.Characteristics.ToDto() }; } @@ -42,7 +42,7 @@ namespace ApiLol { throw new NullReferenceException(); } - return new Champion(name: champion.Name, champClass: champion.ChampClass, icon: champion.Icon, bio: champion.Bio, image: champion.Image.Base64); + return new Champion(name: champion.Name, champClass: champion.ChampClass, icon: champion.Icon, bio: champion.Bio); } public static IEnumerable ToPocos(this IEnumerable champions) diff --git a/Sources/ApiLol/Mapping/RuneMapper.cs b/Sources/ApiLol/Mapping/RuneMapper.cs new file mode 100644 index 0000000..b74d4a0 --- /dev/null +++ b/Sources/ApiLol/Mapping/RuneMapper.cs @@ -0,0 +1,38 @@ +using System; +using Model; +using static System.Net.Mime.MediaTypeNames; +using System.Xml.Linq; +using ApiLol.DTO; + +namespace ApiLol.Mapping +{ + public static class RuneMapper + { + public static RuneDTO ToDto(this Rune rune) + { + + if (rune == null) + { + throw new NullReferenceException(); + } + return new RuneDTO + { + Name = rune.Name, + Description = rune.Description, + Family = rune.Family, + Icon = rune.Icon + }; + + } + + public static Rune ToPoco(this RuneDTO rune) { + if (rune == null) + { + throw new NullReferenceException(); + } + + return new Rune(rune.Name, rune.Family, rune.Icon, rune.Description); + } + } +} + diff --git a/Sources/ApiLol/Mapping/SkinMapper.cs b/Sources/ApiLol/Mapping/SkinMapper.cs index fabde1c..50deed1 100644 --- a/Sources/ApiLol/Mapping/SkinMapper.cs +++ b/Sources/ApiLol/Mapping/SkinMapper.cs @@ -15,7 +15,7 @@ namespace ApiLol.Mapping Description = skin.Description, Price = skin.Price, Icon = skin.Icon, - Image = skin.Image + //Image = skin.Image }; } diff --git a/Sources/ConsoleApi/ConsoleApi.csproj b/Sources/ConsoleApi/ConsoleApi.csproj index 68e39d2..58fb9a7 100644 --- a/Sources/ConsoleApi/ConsoleApi.csproj +++ b/Sources/ConsoleApi/ConsoleApi.csproj @@ -10,7 +10,4 @@ - - - diff --git a/Sources/ConsoleApi/Program.cs b/Sources/ConsoleApi/Program.cs index f56e562..39e2944 100644 --- a/Sources/ConsoleApi/Program.cs +++ b/Sources/ConsoleApi/Program.cs @@ -5,8 +5,5 @@ using static System.Net.WebRequestMethods; HttpClient http = new HttpClient(); //http.BaseAddress = new Uri("https://localhost:7006/"); -Console.WriteLine(await http.GetStringAsync("https://localhost:7006/api/Champion")); -Console.WriteLine(await http.GetStringAsync("https://localhost:7006/api/Champion/1")); - - - +//Console.WriteLine(await http.GetStringAsync("https://localhost:7006/api/Champions")); +//Console.WriteLine(await http.GetStringAsync("https://localhost:7006/api/Champion/1")); diff --git a/Sources/ConsoleDb/ConsoleDb.csproj b/Sources/ConsoleDb/ConsoleDb.csproj index 0bc60ce..34bbffc 100644 --- a/Sources/ConsoleDb/ConsoleDb.csproj +++ b/Sources/ConsoleDb/ConsoleDb.csproj @@ -19,13 +19,13 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Sources/ConsoleDb/Program.cs b/Sources/ConsoleDb/Program.cs index 0fc628b..e795449 100644 --- a/Sources/ConsoleDb/Program.cs +++ b/Sources/ConsoleDb/Program.cs @@ -7,6 +7,7 @@ Console.WriteLine("Hello, World!"); using (var db = new DbDataManager(new EFLib.LolContext())) { + await db.Context.Database.EnsureCreatedAsync(); IEnumerable champions = await db.ChampionsMgr.GetItems(0, 10); foreach (Champion c in champions) diff --git a/Sources/ConsoleDb/oiseaux.db b/Sources/ConsoleDb/oiseaux.db deleted file mode 100644 index 2665bcb..0000000 Binary files a/Sources/ConsoleDb/oiseaux.db and /dev/null differ diff --git a/Sources/DataManagers/ChampChanger.cs b/Sources/DataManagers/ChampChanger.cs index 0e12c1c..3de409f 100644 --- a/Sources/DataManagers/ChampChanger.cs +++ b/Sources/DataManagers/ChampChanger.cs @@ -8,7 +8,7 @@ namespace DataManagers { public static Champion ToPoco(this ChampionEntity champion) { - return new Champion(id: champion.Id, name: champion.Name, champClass: champion.ChampClass, icon: champion.Icon, bio: champion.Bio); + return new Champion(id: champion.Id, name: champion.Name, champClass: champion.ChampClass, icon: champion.Icon, bio: champion.Bio, image: champion.LargeImage.Base64, imageId: champion.ImageId); } public static ChampionEntity ToEntity(this Champion champion) => new ChampionEntity @@ -18,6 +18,8 @@ namespace DataManagers Bio = champion.Bio, Icon = champion.Icon, ChampClass = champion.Class, + ImageId = champion.Image.Id, + LargeImage = champion.Image.ToEntity() }; diff --git a/Sources/DataManagers/DbChampionManager.cs b/Sources/DataManagers/DbChampionManager.cs index 01c2fa1..ad78ffc 100644 --- a/Sources/DataManagers/DbChampionManager.cs +++ b/Sources/DataManagers/DbChampionManager.cs @@ -14,31 +14,9 @@ namespace DataManagers Context = context; } - private IEnumerable SortChampions(IEnumerable champs, int index, int count, string? orderingPropertyName = null, bool descending = false) - { - switch (orderingPropertyName?.ToLower()) - { - case "bio": - champs = champs.OrderBy(arg => arg.Bio.ToLower()).ToList(); - break; - case "class": - champs = champs.OrderBy(arg => arg.Class).ToList(); - break; - default: - champs = champs.OrderBy(arg => arg.Name.ToLower()).ToList(); - break; - } - if (descending) - { - champs = champs.Reverse().ToList(); - } - if (index + count > champs.ToList().Count) return champs.ToList().GetRange(index, champs.ToList().Count - index); - return champs.ToList().GetRange(index, count); - } - public async Task AddItem(Champion? item) { - if (item != null && Context.Champions.SingleOrDefault((ChampionEntity arg) => arg.Name == item.Name)?.ToPoco() == null) + if (item != null && Context.Champions.SingleOrDefault((ChampionEntity arg) => arg.Id == item.Id || arg.Name == item.Name) == null) { await Context.Champions.AddAsync(item.ToEntity()); await Context.SaveChangesAsync(); @@ -51,7 +29,7 @@ namespace DataManagers { if (item != null) { - ChampionEntity? entity = await Context.Champions.SingleOrDefaultAsync((ChampionEntity arg) => arg.Name == item.Name); + ChampionEntity? entity = await Context.Champions.SingleOrDefaultAsync((ChampionEntity arg) => arg.Id == item.Id || arg.Name == item.Name); if (entity != null) { Context.Champions.Remove(entity); @@ -64,8 +42,24 @@ namespace DataManagers public async Task> GetItems(int index, int count, string? orderingPropertyName = null, bool descending = false) { - IEnumerable champs = await Task.Run(() => Context.Champions.ToList().ToPocos()); - return SortChampions(champs, index, count,orderingPropertyName, descending); + IEnumerable champs = new List(); + switch (orderingPropertyName?.ToLower()) + { + case "bio": + champs = await Task.Run(() => Context.Champions.OrderBy((arg) => arg.Bio).Skip(index * count).Take(count).ToList().ToPocos()); + break; + case "class": + champs = await Task.Run(() => Context.Champions.OrderBy((arg) => arg.ChampClass).Skip(index * count).Take(count).ToList().ToPocos()); + break; + default: + champs = await Task.Run(() => Context.Champions.OrderBy((arg) => arg.Name).Skip(index * count).Take(count).ToList().ToPocos()); + break; + } + if (descending) + { + champs.Reverse(); + } + return champs; } public async Task GetNbItems() @@ -81,14 +75,46 @@ namespace DataManagers public async Task> GetItemsByClass(ChampionClass championClass, int index, int count, string? orderingPropertyName = null, bool descending = false) { - IEnumerable champs = await Task.Run(() => Context.Champions.ToList().ToPocos().Where(arg => arg.Class == championClass)); - return SortChampions(champs, index, count, orderingPropertyName, descending); + IEnumerable champs = new List(); + switch (orderingPropertyName?.ToLower()) + { + case "bio": + champs = await Task.Run(() => Context.Champions.Where((arg) => arg.ChampClass == championClass).OrderBy((arg) => arg.Bio).Skip(index * count).Take(count).ToList().ToPocos()); + break; + case "class": + champs = await Task.Run(() => Context.Champions.Where((arg) => arg.ChampClass == championClass).OrderBy((arg) => arg.ChampClass).Skip(index * count).Take(count).ToList().ToPocos()); + break; + default: + champs = await Task.Run(() => Context.Champions.Where((arg) => arg.ChampClass == championClass).OrderBy((arg) => arg.Name).Skip(index * count).Take(count).ToList().ToPocos()); + break; + } + if (descending) + { + champs.Reverse(); + } + return champs; } public async Task> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false) { - IEnumerable champs = await Task.Run(() => Context.Champions.ToList().ToPocos().Where(arg => arg.Name.Contains(substring))); - return SortChampions(champs, index, count, orderingPropertyName, descending); + IEnumerable champs = new List(); + switch (orderingPropertyName?.ToLower()) + { + case "bio": + champs = await Task.Run(() => Context.Champions.Where((arg) => arg.Name.Contains(substring)).OrderBy((arg) => arg.Bio).Skip(index * count).Take(count).ToList().ToPocos()); + break; + case "class": + champs = await Task.Run(() => Context.Champions.Where((arg) => arg.Name.Contains(substring)).OrderBy((arg) => arg.ChampClass).Skip(index * count).Take(count).ToList().ToPocos()); + break; + default: + champs = await Task.Run(() => Context.Champions.Where((arg) => arg.Name.Contains(substring)).OrderBy((arg) => arg.Name).Skip(index * count).Take(count).ToList().ToPocos()); + break; + } + if (descending) + { + champs.Reverse(); + } + return champs; } public Task> GetItemsByRunePage(RunePage? runePage, int index, int count, string? orderingPropertyName = null, bool descending = false) diff --git a/Sources/DataManagers/DbDataManager.cs b/Sources/DataManagers/DbDataManager.cs index 70f0fd2..9d20469 100644 --- a/Sources/DataManagers/DbDataManager.cs +++ b/Sources/DataManagers/DbDataManager.cs @@ -7,7 +7,7 @@ namespace DataManagers public class DbDataManager : IDataManager { - private LolContext Context { get; set; } + public LolContext Context { get; set; } public IChampionsManager ChampionsMgr => new DbChampionManager(Context); @@ -32,6 +32,11 @@ namespace DataManagers { Context.Database.EnsureCreated(); } + + public async Task EnsureCreatedAsync() + { + await Context.Database.EnsureCreatedAsync(); + } } } diff --git a/Sources/DataManagers/LargeImageChanger.cs b/Sources/DataManagers/LargeImageChanger.cs new file mode 100644 index 0000000..09f9c56 --- /dev/null +++ b/Sources/DataManagers/LargeImageChanger.cs @@ -0,0 +1,42 @@ +using System; +using EFLib; +using Model; + +namespace DataManagers +{ + public static class LargeImageChanger + { + public static LargeImage ToPoco(this LargeImageEntity largeImage) + { + return new LargeImage(largeImage.Id, largeImage.Base64); + } + + public static LargeImageEntity ToEntity(this LargeImage largeImage) => new LargeImageEntity + { + Id = largeImage.Id, + Base64 = largeImage.Base64 + }; + + + public static IEnumerable ToPocos(this IEnumerable largeImages) + { + List images = new List(); + foreach (LargeImageEntity l in largeImages) + { + images.Add(l.ToPoco()); + } + return images; + } + + public static IEnumerable toEntities(this IEnumerable largeImages) + { + List images = new List(); + foreach (LargeImage l in largeImages) + { + images.Add(l.ToEntity()); + } + return images; + } + } +} + diff --git a/Sources/EFLib/ChampionEntity.cs b/Sources/EFLib/ChampionEntity.cs index 829cc2e..b17f0b4 100644 --- a/Sources/EFLib/ChampionEntity.cs +++ b/Sources/EFLib/ChampionEntity.cs @@ -16,6 +16,10 @@ namespace EFLib public ChampionClass ChampClass { get; set;} + public int ImageId { get; set; } + + public LargeImageEntity LargeImage { get; set; } + } } diff --git a/Sources/EFLib/EFLib.csproj b/Sources/EFLib/EFLib.csproj index 999d095..6e24479 100644 --- a/Sources/EFLib/EFLib.csproj +++ b/Sources/EFLib/EFLib.csproj @@ -1,7 +1,6 @@ - Exe net6.0 enable enable @@ -15,13 +14,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Sources/EFLib/LargeImageEntity.cs b/Sources/EFLib/LargeImageEntity.cs new file mode 100644 index 0000000..7d13219 --- /dev/null +++ b/Sources/EFLib/LargeImageEntity.cs @@ -0,0 +1,13 @@ +using System; +namespace EFLib +{ + public class LargeImageEntity + { + public int Id { get; set; } + + public string Base64 { get; set; } + + public ChampionEntity Champion { get; set; } + } +} + diff --git a/Sources/EFLib/LolContext.cs b/Sources/EFLib/LolContext.cs index b08b271..70d827d 100644 --- a/Sources/EFLib/LolContext.cs +++ b/Sources/EFLib/LolContext.cs @@ -1,12 +1,16 @@ using System; using Microsoft.EntityFrameworkCore; +using Microsoft.VisualBasic; +using Model; namespace EFLib { - public class LolContext : DbContext, IDisposable - { + public class LolContext : DbContext + { public DbSet Champions { get; set; } + public DbSet LargeImages { get; set; } + public LolContext(DbContextOptions options) : base(options) { } @@ -21,6 +25,30 @@ namespace EFLib optionsBuilder.UseSqlite("Data Source=oiseaux.db"); } } + + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity() + .HasOne(e => e.Champion) + .WithOne(z => z.LargeImage) + .HasForeignKey(x => x.ImageId); + + var image1 = new LargeImageEntity { Id = 1, Base64 = "test1" }; + var image2 = new LargeImageEntity { Id = 2, Base64 = "test2" }; + var image3 = new LargeImageEntity { Id = 3, Base64 = "test3" }; + + modelBuilder.Entity().HasData(image1, image2, image3); + + modelBuilder.Entity().HasData( + new ChampionEntity { Id = 1, Name = "Test1", Bio = "Salut", ChampClass = ChampionClass.Fighter, Icon = "bla", ImageId = 1 }, + new ChampionEntity { Id = 2, Name = "Test2", Bio = "hey", ChampClass = ChampionClass.Assassin, Icon = "bla", ImageId = 2 }, + new ChampionEntity { Id = 3, Name = "Test3", Bio = "coucou", ChampClass = ChampionClass.Tank, Icon = "bla", ImageId = 3 } + + ); + } } } diff --git a/Sources/EFLib/Program.cs b/Sources/EFLib/Program.cs deleted file mode 100644 index bf37432..0000000 --- a/Sources/EFLib/Program.cs +++ /dev/null @@ -1,15 +0,0 @@ -// See https://aka.ms/new-console-template for more information -using EFLib; - -Console.WriteLine("Hello, World!"); - -using (var context = new LolContext()) -{ - context.Champions.Add(new ChampionEntity - { - Name = "Test", - Bio = "Bonjour", - Icon = "Wouhou" - }); - context.SaveChanges(); -} \ No newline at end of file diff --git a/Sources/EFLib/oiseaux.db-shm b/Sources/EFLib/oiseaux.db-shm deleted file mode 100644 index fe9ac28..0000000 Binary files a/Sources/EFLib/oiseaux.db-shm and /dev/null differ diff --git a/Sources/EFLib/oiseaux.db-wal b/Sources/EFLib/oiseaux.db-wal deleted file mode 100644 index e69de29..0000000 diff --git a/Sources/LeagueOfLegends.sln b/Sources/LeagueOfLegends.sln index 4ce5d07..6aa39c6 100644 --- a/Sources/LeagueOfLegends.sln +++ b/Sources/LeagueOfLegends.sln @@ -23,6 +23,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApi", "ConsoleApi\Co EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{EE69586D-A6A8-40C4-93D7-DBDFEBC6844A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LolApp", "LolApp\LolApp.csproj", "{0C898A04-092A-49AA-BE65-8AE818A2AF50}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ViewModels", "ViewModels\ViewModels.csproj", "{805D142A-2755-4232-A486-2970277FB951}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -65,6 +69,14 @@ Global {EE69586D-A6A8-40C4-93D7-DBDFEBC6844A}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE69586D-A6A8-40C4-93D7-DBDFEBC6844A}.Release|Any CPU.ActiveCfg = Release|Any CPU {EE69586D-A6A8-40C4-93D7-DBDFEBC6844A}.Release|Any CPU.Build.0 = Release|Any CPU + {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Release|Any CPU.Build.0 = Release|Any CPU + {805D142A-2755-4232-A486-2970277FB951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {805D142A-2755-4232-A486-2970277FB951}.Debug|Any CPU.Build.0 = Debug|Any CPU + {805D142A-2755-4232-A486-2970277FB951}.Release|Any CPU.ActiveCfg = Release|Any CPU + {805D142A-2755-4232-A486-2970277FB951}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Sources/LolApp/LolApp.csproj b/Sources/LolApp/LolApp.csproj index cde1acb..ad4cdee 100644 --- a/Sources/LolApp/LolApp.csproj +++ b/Sources/LolApp/LolApp.csproj @@ -83,6 +83,7 @@ + diff --git a/Sources/LolApp/MauiProgram.cs b/Sources/LolApp/MauiProgram.cs index c12deff..9b5c12b 100644 --- a/Sources/LolApp/MauiProgram.cs +++ b/Sources/LolApp/MauiProgram.cs @@ -6,6 +6,7 @@ using Microsoft.Maui.Platform; using Model; using StubLib; using ViewModels; +using DataManagers; namespace LolApp; diff --git a/Sources/Model/Champion.cs b/Sources/Model/Champion.cs index df3000d..cfbb327 100644 --- a/Sources/Model/Champion.cs +++ b/Sources/Model/Champion.cs @@ -50,25 +50,25 @@ public class Champion : IEquatable public LargeImage Image { get; set; } - public Champion(int id, string name, ChampionClass champClass = ChampionClass.Unknown, string icon = "", string image = "", string bio = "") + public Champion(int id, string name, ChampionClass champClass = ChampionClass.Unknown, string icon = "", string image = "", int imageId=0,string bio = "") { Id = id; Name = name; Class = champClass; Icon = icon; - Image = new LargeImage(image); + Image = new LargeImage(imageId, image); Bio = bio; Characteristics = new ReadOnlyDictionary(characteristics); Skins = new ReadOnlyCollection(skins); } - public Champion(string name, ChampionClass champClass = ChampionClass.Unknown, string icon = "", string image = "", string bio = "") + public Champion(string name, ChampionClass champClass = ChampionClass.Unknown, string icon = "", string image = "", int imageId = 0, string bio = "") { Id = 0; Name = name; Class = champClass; Icon = icon; - Image = new LargeImage(image); + Image = new LargeImage(imageId, image); Bio = bio; Characteristics = new ReadOnlyDictionary(characteristics); Skins = new ReadOnlyCollection(skins); diff --git a/Sources/Model/LargeImage.cs b/Sources/Model/LargeImage.cs index 56d6696..1a30061 100644 --- a/Sources/Model/LargeImage.cs +++ b/Sources/Model/LargeImage.cs @@ -5,13 +5,30 @@ namespace Model { public string Base64 { get; set; } - public LargeImage(string base64) + public int Id { get; set; } + + + public LargeImage(int id, string base64) { Base64 = base64; + Id = id; } + public LargeImage(string base64) + { + Base64 = base64; + Id = 0; + } + public bool Equals(LargeImage? other) - => other != null && other.Base64.Equals(Base64); + { + if (other == null) return false; + if (Id != 0 && other?.Id != 0) + { + return Id == Id; + } + return Base64 == other?.Base64; + } public override bool Equals(object? obj) { diff --git a/Sources/Model/Model.csproj b/Sources/Model/Model.csproj index f898697..3ef2d23 100644 --- a/Sources/Model/Model.csproj +++ b/Sources/Model/Model.csproj @@ -23,15 +23,15 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + diff --git a/Sources/Shared/Shared.csproj b/Sources/Shared/Shared.csproj index addd042..c5fba91 100644 --- a/Sources/Shared/Shared.csproj +++ b/Sources/Shared/Shared.csproj @@ -13,15 +13,15 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + diff --git a/Sources/StubLib/StubLib.csproj b/Sources/StubLib/StubLib.csproj index 6d93d37..dd05e4c 100644 --- a/Sources/StubLib/StubLib.csproj +++ b/Sources/StubLib/StubLib.csproj @@ -16,15 +16,15 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + diff --git a/Sources/Tests/ChampionController_UT.cs b/Sources/Tests/ChampionController_UT.cs new file mode 100644 index 0000000..790b564 --- /dev/null +++ b/Sources/Tests/ChampionController_UT.cs @@ -0,0 +1,49 @@ +using System; +using ApiLol; +using ApiLol.Controllers; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using StubLib; + + +namespace Tests +{ + public class ChampionController_UT + { + [Fact] + public async void GetChampionTest() + { + ChampionController controller = new ChampionController(new Logger(new LoggerFactory()), new StubData()); + } + + [Fact] + public async void GetChampionByNameTest() + { + ChampionController controller = new ChampionController(new Logger(new LoggerFactory()), new StubData()); + var result = await controller.GetChampionsByName("aa"); + var champs = (result.Result as ObjectResult).Value as IEnumerable; + Assert.True(champs.Any()); + } + + [Fact] + public async void PostChampionTest() + { + ChampionController controller = new ChampionController(new Logger(new LoggerFactory()), new StubData()); + var result = await controller.PostChampion(new ChampionDTO { Name="Test", Bio="test", ChampClass=Model.ChampionClass.Assassin, Icon="sqdz"}); + ChampionDTO? champ = (result.Result as ObjectResult).Value as ChampionDTO; + Assert.NotNull(champ); + } + + [Fact] + public async void PutChampionTest() + { + ChampionController controller = new ChampionController(new Logger(new LoggerFactory()), new StubData()); + var result = await controller.Put(new ChampionDTO { Name = "Aatrox", Bio = "test", ChampClass = Model.ChampionClass.Assassin, Icon = "sqdz" }, new ChampionDTO { Name = "Test", Bio = "test", ChampClass = Model.ChampionClass.Assassin, Icon = "sqdz" }); + var champ = (result.Result as ObjectResult).Value as ChampionDTO; + Assert.NotNull(champ); + var result2 = await controller.Put(new ChampionDTO { Name = "blabla", Bio = "test", ChampClass = Model.ChampionClass.Assassin, Icon = "sqdz" }, new ChampionDTO { Name = "Test", Bio = "test", ChampClass = Model.ChampionClass.Assassin, Icon = "sqdz" }); + var champ2 = (result.Result as ObjectResult).Value as ChampionDTO; + Assert.Null(champ2); + } + } +} \ No newline at end of file diff --git a/Sources/Tests/DbChampionManager_UT.cs b/Sources/Tests/DbChampionManager_UT.cs index e595707..7904b72 100644 --- a/Sources/Tests/DbChampionManager_UT.cs +++ b/Sources/Tests/DbChampionManager_UT.cs @@ -1,6 +1,7 @@ namespace Tests; using System.Threading.Tasks; +using System.Xml.Linq; using DataManagers; using EFLib; using Microsoft.Data.Sqlite; @@ -10,8 +11,11 @@ using Model; public class DbChampionManager_UT { - [Fact] - public async Task Add_TestAsync() + [Theory] + [InlineData(true, true, 8, "Aurelien", ChampionClass.Tank, "tro bo le type")] + [InlineData(true, false, 8, "Marche sans ID", ChampionClass.Tank, "tro bo le type")] + [InlineData(false, true, 8, "Marche pas", ChampionClass.Tank, "tro bo le type")] + public async Task Add_TestAsync(bool isValid, bool hasId,int id, string name, ChampionClass championClass, string bio) { var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); @@ -23,28 +27,32 @@ public class DbChampionManager_UT using (var db = new DbDataManager(new EFLib.LolContext(options))) { - db.EnsureCreated(); - - Champion champion = new Champion("Aurelien", ChampionClass.Tank, "tro bo le type"); - Champion champion2 = new Champion("Croissant", ChampionClass.Assassin, "tro bon le type"); - Champion champion3 = new Champion("Mathilde", ChampionClass.Fighter, "Chut mathilde"); - await db.ChampionsMgr.AddItem(champion); - await db.ChampionsMgr.AddItem(champion2); - await db.ChampionsMgr.AddItem(champion3); - } - - using (var db = new DbDataManager(new EFLib.LolContext(options))) - { - db.EnsureCreated(); - Assert.Equal(3, await db.ChampionsMgr.GetNbItems()); - Assert.Null(await db.ChampionsMgr.AddItem(new Champion("Aurelien", ChampionClass.Tank, "tro bo le type"))); + await db.EnsureCreatedAsync(); + + Champion champion = new Champion(name, championClass, bio); + if (hasId) + { + champion = new Champion(id, name, championClass, bio); + } + Champion? c = await db.ChampionsMgr.AddItem(champion); + + if (isValid) + { + Assert.NotNull(c); + } + else + { + Champion? c1 = await db.ChampionsMgr.AddItem(champion); + Assert.Null(c1); + } } - - } - [Fact] - public async Task Delete_TestAsync() + [Theory] + [InlineData(true, true, 18, "Aurelien", ChampionClass.Tank, "tro bo le type")] + [InlineData(true, false, 19, "Marche sans Id", ChampionClass.Tank, "tro bo le type")] + [InlineData(false, true, 20, "Marche pas", ChampionClass.Tank, "tro bo le type")] + public async Task Delete_TestAsync(bool isValid, bool hasId, int id, string name, ChampionClass championClass, string bio) { var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); @@ -55,32 +63,71 @@ public class DbChampionManager_UT using (var db = new DbDataManager(new EFLib.LolContext(options))) { - db.EnsureCreated(); - - Champion champion = new Champion("Aurelien", ChampionClass.Tank, "tro bo le type"); - Champion champion2 = new Champion("Croissant", ChampionClass.Assassin, "tro bon le type"); - Champion champion3 = new Champion("Mathilde", ChampionClass.Fighter, "Chut mathilde"); - await db.ChampionsMgr.AddItem(champion); - await db.ChampionsMgr.AddItem(champion2); - await db.ChampionsMgr.AddItem(champion3); + await db.Context.Database.EnsureCreatedAsync(); + + Champion champion = new Champion(name, championClass, bio); + if (hasId) + { + champion = new Champion(id, name, championClass, bio); + } + if (isValid) + { + Champion? c = await db.ChampionsMgr.AddItem(champion); + var retour = await db.ChampionsMgr.DeleteItem(champion); + Assert.True(retour); + } + else + { + var retour = await db.ChampionsMgr.DeleteItem(champion); + Assert.False(retour); + } } + } - using (var db = new DbDataManager(new EFLib.LolContext(options))) - { - db.EnsureCreated(); + [Theory] + [InlineData(true, true, 18, "Aurelien", ChampionClass.Tank, "tro bo le type")] + [InlineData(true, false, 19, "Marche sans Id", ChampionClass.Tank, "tro bo le type")] + [InlineData(false, true, 20, "Marche pas", ChampionClass.Tank, "tro bo le type")] + public async Task Modify_TestAsync(bool isValid, bool hasId, int id, string name, ChampionClass championClass, string bio) + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); - string nameToFind = "Croissant"; - IEnumerable champ = await db.ChampionsMgr.GetItemsByName(nameToFind, 0, 15, "name"); - Champion c = champ.First(); - Assert.Equal("Croissant", c.Name); - await db.ChampionsMgr.DeleteItem(champ.First()); + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; - Assert.Equal(2, await db.ChampionsMgr.GetNbItems()); + using (var db = new DbDataManager(new EFLib.LolContext(options))) + { + await db.Context.Database.EnsureCreatedAsync(); + + Champion champion = new Champion(name, championClass, bio); + if (hasId) + { + champion = new Champion(id, name, championClass, bio); + } + if (isValid) + { + Champion? c = await db.ChampionsMgr.AddItem(champion); + var retour = await db.ChampionsMgr.UpdateItem(c, new Champion(champion.Id, champion.Name, bio: "blabla")); + Assert.Equal("blabla", retour.Bio); + } + else + { + var retour = await db.ChampionsMgr.UpdateItem(champion, new Champion(champion.Id, champion.Name, bio: "blabla")); + Assert.Null(retour); + } } } - [Fact] - public async Task Modify_TestAsync() + [Theory] + [InlineData("name", false)] + [InlineData("bio", false)] + [InlineData("class", false)] + [InlineData("name", true)] + [InlineData("bio", true)] + [InlineData("class", true)] + public async Task GetItems_TestAsync(string orderingProperty, bool reverse) { var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); @@ -91,35 +138,27 @@ public class DbChampionManager_UT using (var db = new DbDataManager(new EFLib.LolContext(options))) { - db.EnsureCreated(); + await db.Context.Database.EnsureCreatedAsync(); + + Champion champion = new Champion("test1", ChampionClass.Unknown, "test1"); + Champion champion1 = new Champion("test2", ChampionClass.Assassin, "test2"); + Champion champion2 = new Champion("test3", ChampionClass.Fighter, "test3"); - Champion champion = new Champion("Aurelien", ChampionClass.Tank, "tro bo le type"); - Champion champion2 = new Champion("Croissant", ChampionClass.Assassin, "tro bon le type"); - Champion champion3 = new Champion("Mathilde", ChampionClass.Fighter, "Chut mathilde"); await db.ChampionsMgr.AddItem(champion); + await db.ChampionsMgr.AddItem(champion1); await db.ChampionsMgr.AddItem(champion2); - await db.ChampionsMgr.AddItem(champion3); - } - using (var db = new DbDataManager(new EFLib.LolContext(options))) - { - db.EnsureCreated(); - string nameToFind = "Croissant"; - IEnumerable champ = await db.ChampionsMgr.GetItemsByName(nameToFind, 0, 15, "name"); - Champion c = champ.First(); - Assert.Equal("Croissant", c.Name); - Champion c1 = new Champion("Test", c.Class, c.Icon, bio: c.Bio); - await db.ChampionsMgr.UpdateItem(c, c1); - Assert.Equal(3, await db.ChampionsMgr.GetNbItems()); - champ = await db.ChampionsMgr.GetItemsByName("Test", 0, 15, "name"); + var list = await db.ChampionsMgr.GetItems(0, 10, orderingProperty, reverse); - Assert.Equal("Test", champ.First().Name); + Assert.Equal(3, list.Count()); + //if (reverse) Assert.Equal("test3", list.First().Name); + //else Assert.Equal("test1", list.First().Name); } } [Fact] - public async Task GetItems_TestAsync() + public async Task getNbItems_TestASync() { var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); @@ -130,32 +169,9 @@ public class DbChampionManager_UT using (var db = new DbDataManager(new EFLib.LolContext(options))) { - db.EnsureCreated(); - - Champion champion = new Champion("Aurelien", ChampionClass.Tank, "hey bo le type"); - Champion champion2 = new Champion("Croissant", ChampionClass.Assassin, "Ztro bon le type"); - Champion champion3 = new Champion("Mathilde", ChampionClass.Fighter, "ah mathilde"); - await db.ChampionsMgr.AddItem(champion); - await db.ChampionsMgr.AddItem(champion2); - await db.ChampionsMgr.AddItem(champion3); - } - - using (var db = new DbDataManager(new EFLib.LolContext(options))) - { - db.EnsureCreated(); - var list = await db.ChampionsMgr.GetItems(0, 10, "bio", false); - Assert.Equal(3, list.Count()); - list = await db.ChampionsMgr.GetItems(0, 3, "autre", true); - Assert.Equal("Aurelien", list.Last().Name); - list = await db.ChampionsMgr.GetItems(0, 3, "class", true); - Assert.Equal("Aurelien", list.First().Name); - list = await db.ChampionsMgr.GetItemsByClass(ChampionClass.Assassin, 0, 10); - Assert.Equal(1, list.Count()); - Assert.Equal("Croissant", list.First().Name); - + await db.Context.Database.EnsureCreatedAsync(); + Assert.Equal(3, await db.ChampionsMgr.GetNbItems()); } } - - } \ No newline at end of file diff --git a/Sources/Tests/Tests.csproj b/Sources/Tests/Tests.csproj index df4dc81..eaa167c 100644 --- a/Sources/Tests/Tests.csproj +++ b/Sources/Tests/Tests.csproj @@ -9,28 +9,30 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + + + diff --git a/Sources/ViewModels/ChampionVM.cs b/Sources/ViewModels/ChampionVM.cs new file mode 100644 index 0000000..bdd1e7f --- /dev/null +++ b/Sources/ViewModels/ChampionVM.cs @@ -0,0 +1,101 @@ +using System; +using CommunityToolkit.Mvvm.ComponentModel; +using Model; +using Microsoft.Maui.Controls; +using System.Collections.ObjectModel; + + +namespace ViewModels +{ + public partial class ChampionVM : ObservableObject + { + public Champion Model + { + get => model; + set + { + model = value; + OnPropertyChanged(nameof(Name)); + OnPropertyChanged(nameof(Bio)); + OnPropertyChanged(nameof(Class)); + OnPropertyChanged(nameof(Icon)); + OnPropertyChanged(nameof(Image)); + OnPropertyChanged(nameof(Skills)); + OnPropertyChanged(nameof(Characteristics)); + } + } + private Champion model; + + public ChampionVM(Champion model) + { + Model = model; + foreach(var skill in Model.Skills) + { + Skills.Add(new SkillVM(skill)); + } + Skills.CollectionChanged += Skills_CollectionChanged; + } + + private void Skills_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + SkillVM vm = e.NewItems?[0] as SkillVM; + switch(e.Action) + { + case System.Collections.Specialized.NotifyCollectionChangedAction.Add: + Model.Skills.Add(new Skill(vm.Name, vm.Type, vm.Description)); + break; + case System.Collections.Specialized.NotifyCollectionChangedAction.Remove: + Model.Skills.Remove(vm.Model); + break; + } + } + + public string Name => Model.Name; + + public ChampionClass Class + { + get => Model.Class; + set => SetProperty(Model.Class, value, newValue => Model.Class = newValue); + } + + public string Bio + { + get => Model.Bio; + set => SetProperty(Model.Bio, value, newBio => Model.Bio = newBio); + } + + public string Icon + { + get => Model.Icon; + set + { + SetProperty(Model.Icon, value, newIcon => + { + Model.Icon = newIcon; + }); + } + } + + public string Image + { + get => Model.Image.Base64; + set + { + SetProperty(Model.Image.Base64, value, newImage => + { + Model.Image.Base64 = newImage; + }); + } + } + + [ObservableProperty] + private ObservableCollection skills = new ObservableCollection(); + + public ReadOnlyDictionary Characteristics + => Model.Characteristics; + + [ObservableProperty] + private ObservableCollection skins = new ObservableCollection(); + } +} + diff --git a/Sources/ViewModels/ChampionsMgrVM.cs b/Sources/ViewModels/ChampionsMgrVM.cs new file mode 100644 index 0000000..06e5d67 --- /dev/null +++ b/Sources/ViewModels/ChampionsMgrVM.cs @@ -0,0 +1,227 @@ +using System.Threading.Tasks; +using Model; +using System.Windows.Input; +using CommunityToolkit.Mvvm.ComponentModel; +using System.Collections.ObjectModel; +using CommunityToolkit.Mvvm.Input; +using System.Data.SqlTypes; +using System.Reflection; + +namespace ViewModels; + +public partial class ChampionsMgrVM : ObservableObject +{ + internal IDataManager DataMgr { get; set; } + + public ChampionsMgrVM(IDataManager dataManager) + { + DataMgr = dataManager; + + loadingMethods = new Dictionary>() + { + [LoadingCriterium.None] = async (o) => await LoadChampions(), + [LoadingCriterium.ByName] = async (o) => + { + string substring = o as string; + if(substring == null) return; + await LoadChampionsByName(substring); + }, + [LoadingCriterium.BySkill] = async (o) => + { + string skillString = o as string; + if(skillString == null) return; + await LoadChampionsBySkill(skillString); + }, + [LoadingCriterium.ByCharacteristic] = async (o) => + { + string characString = o as string; + if(characString == null) return; + await LoadChampionsByCharacteristic(characString); + }, + [LoadingCriterium.ByClass] = async (o) => + { + if(!Enum.IsDefined(typeof(ChampionClass), o)) return; + ChampionClass champClass = (ChampionClass)o; + await LoadChampionsByClass(champClass); + }, + }; + } + + private async Task LoadChampionsFunc(Func>> loader, + Func> nbReader, + LoadingCriterium criterium, + object parameter = null) + { + Champions.Clear(); + var someChampions = (await loader()).Select(c => new ChampionVM(c)).ToList(); + foreach (var cvm in someChampions) + { + Champions.Add(cvm); + } + NbChampions = await nbReader(); + currentLoadingCriterium = criterium; + currentLoadingParameter = parameter; + } + + [RelayCommand] + public async Task LoadChampions() + { + await LoadChampionsFunc(async () => await DataMgr.ChampionsMgr.GetItems(index, count, "Name"), + async () => await DataMgr.ChampionsMgr.GetNbItems(), + LoadingCriterium.None); + } + + [RelayCommand(CanExecute =nameof(CanLoadChampionsByName))] + public async Task LoadChampionsByName(string substring) + { + await LoadChampionsFunc(async () => await DataMgr.ChampionsMgr.GetItemsByName(substring, index, count, "Name"), + async () => await DataMgr.ChampionsMgr.GetNbItemsByName(substring), + LoadingCriterium.ByName, + substring); + } + private bool CanLoadChampionsByName(string substring) + => !string.IsNullOrWhiteSpace(substring); + + [RelayCommand(CanExecute =nameof(CanLoadChampionsBySkill))] + public async Task LoadChampionsBySkill(string skill) + { + await LoadChampionsFunc( + async () => await DataMgr.ChampionsMgr.GetItemsBySkill(skill, index, count, "Name"), + async () => await DataMgr.ChampionsMgr.GetNbItemsBySkill(skill), + LoadingCriterium.BySkill, + skill); + } + private bool CanLoadChampionsBySkill(string substring) => !string.IsNullOrWhiteSpace(substring); + + [RelayCommand(CanExecute = nameof(CanLoadChampionsByCharacteristic))] + public async Task LoadChampionsByCharacteristic(string characteristic) + { + await LoadChampionsFunc( + async () => await DataMgr.ChampionsMgr.GetItemsByCharacteristic(characteristic, index, count, "Name"), + async () => await DataMgr.ChampionsMgr.GetNbItemsByCharacteristic(characteristic), + LoadingCriterium.ByCharacteristic, + characteristic); + } + + private bool CanLoadChampionsByCharacteristic(string characteristic) + => !string.IsNullOrWhiteSpace(characteristic); + + [RelayCommand] + public async Task LoadChampionsByClass(ChampionClass champClass) + { + if(champClass == ChampionClass.Unknown) + { + return; + } + await LoadChampionsFunc( + async () => await DataMgr.ChampionsMgr.GetItemsByClass(champClass, index, count, "Name"), + async () => await DataMgr.ChampionsMgr.GetNbItemsByClass(champClass), + LoadingCriterium.ByClass, + champClass); + } + + [RelayCommand(CanExecute =nameof(CanDeleteChampion))] + public async Task DeleteChampion(object champVM) + { + ChampionVM cvm = champVM as ChampionVM; + if(cvm == null || !Champions.Contains(cvm)) return false; + bool result = await DataMgr.ChampionsMgr.DeleteItem(cvm.Model); + if(result) + { + Champions.Remove(cvm); + await LoadChampions(); + } + return result; + } + bool CanDeleteChampion(object cvm) + => cvm!= null && cvm is ChampionVM && Champions.Contains(cvm); + + [ObservableProperty] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int index = 0; + + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(NbPages))] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int count = 5; + + public int NbPages + { + get + { + if(Count == 0 || NbChampions == 0) + { + return 0; + } + return (NbChampions-1) / Count + 1; + } + } + + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(NbPages))] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int nbChampions = 0; + + [ObservableProperty] + private ObservableCollection champions = new ObservableCollection(); + + [RelayCommand(CanExecute =nameof(CanPreviousPage))] + async Task PreviousPage() + { + if(Index > 0) + { + Index--; + await loadingMethods[currentLoadingCriterium](currentLoadingParameter); + } + } + bool CanPreviousPage() => Index > 0; + + [RelayCommand(CanExecute =nameof(CanNextPage))] + async Task NextPage() + { + if(Index < NbPages-1) + { + Index++; + await loadingMethods[currentLoadingCriterium](currentLoadingParameter); + } + } + bool CanNextPage() => Index < NbPages-1; + + + enum LoadingCriterium + { + None, + ByName, + BySkill, + ByCharacteristic, + ByClass + } + + private LoadingCriterium currentLoadingCriterium = LoadingCriterium.None; + private object currentLoadingParameter = null; + + private Dictionary> loadingMethods; + + public async Task AddChampion(ChampionVM champVM) + { + var added = await DataMgr.ChampionsMgr.AddItem(champVM.Model); + if(added != null) + { + Champions.Add(champVM); + await LoadChampions(); + } + } + + public async Task EditChampion(ChampionVM oldChampion, ChampionVM newChampion) + { + var edited = await DataMgr.ChampionsMgr.UpdateItem(oldChampion.Model, newChampion.Model); + oldChampion.Model = newChampion.Model; + if(edited != null) + { + await LoadChampions(); + } + } +} diff --git a/Sources/ViewModels/EditableChampionVM.cs b/Sources/ViewModels/EditableChampionVM.cs new file mode 100644 index 0000000..2db038b --- /dev/null +++ b/Sources/ViewModels/EditableChampionVM.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.ObjectModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Model; + +namespace ViewModels +{ + [ObservableObject] + public partial class EditableChampionVM + { + public EditableChampionVM() + { } + + public EditableChampionVM(ChampionVM championVM) + { + Name = championVM.Name; + IconBase64 = championVM.Icon; + LargeImageBase64 = championVM.Image; + Bio = championVM.Bio; + ChampionClass = championVM.Class; + foreach(var ch in championVM.Characteristics) + { + AddCharacteristic(ch.Key, ch.Value); + } + foreach(var skill in championVM.Skills) + { + Skills.Add(skill); + } + } + + [ObservableProperty] + string name; + + [ObservableProperty] + string iconBase64; + + [ObservableProperty] + string largeImageBase64; + + [ObservableProperty] + string bio; + + [ObservableProperty] + ChampionClass championClass; + + [ObservableProperty] + ObservableCollection> characteristics = new (); + + public void AddCharacteristic(string description, int value) + => Characteristics.Add(new KeyValuePair(description, value)); + + public void RemoveCharacteristic(KeyValuePair characteristic) + => Characteristics.Remove(characteristic); + + [ObservableProperty] + ObservableCollection skills = new ObservableCollection(); + + + + public ChampionVM ToChampionVM() + { + var champion = new Champion(name, championClass, iconBase64, largeImageBase64, bio); + champion.AddCharacteristics(characteristics.Select(kvp => Tuple.Create(kvp.Key, kvp.Value)).ToArray()); + foreach(var skillVM in Skills) + { + champion.AddSkill(skillVM.Model); + } + return new ChampionVM(champion); + } + } +} + diff --git a/Sources/ViewModels/EditableSkinVM.cs b/Sources/ViewModels/EditableSkinVM.cs new file mode 100644 index 0000000..b35ca24 --- /dev/null +++ b/Sources/ViewModels/EditableSkinVM.cs @@ -0,0 +1,51 @@ +using System; +using System.Reflection.PortableExecutable; +using System.Xml.Linq; +using CommunityToolkit.Mvvm.ComponentModel; +using Model; + +namespace ViewModels +{ + [ObservableObject] + public partial class EditableSkinVM + { + public EditableSkinVM(ChampionVM championVM) + { + champion = championVM.Model; + } + + public EditableSkinVM(SkinVM skinVM) + { + Name = skinVM.Name; + IconBase64 = skinVM.Icon; + LargeImageBase64 = skinVM.Image; + Description = skinVM.Description; + Price = skinVM.Price; + champion = skinVM.Champion; + } + + [ObservableProperty] + private string name; + + [ObservableProperty] + private string iconBase64; + + [ObservableProperty] + private string largeImageBase64; + + [ObservableProperty] + private string description; + + [ObservableProperty] + private float price; + + private Champion champion; + + public SkinVM ToSkinVM() + { + var skin = new Skin(name, champion, price, iconBase64, largeImageBase64, description); + return new SkinVM(skin); + } + } +} + diff --git a/Sources/ViewModels/SkillVM.cs b/Sources/ViewModels/SkillVM.cs new file mode 100644 index 0000000..c9c2ca1 --- /dev/null +++ b/Sources/ViewModels/SkillVM.cs @@ -0,0 +1,32 @@ +using System; +using CommunityToolkit.Mvvm.ComponentModel; +using Model; + +namespace ViewModels +{ + [ObservableObject] + public partial class SkillVM + { + [ObservableProperty] + private Skill model; + + public SkillVM(Skill model) + { + Model = model; + } + + public string Name => Model.Name; + + public SkillType Type => Model.Type; + + public string Description + { + get => Model.Description; + set + { + SetProperty(Model.Description, value, newValue => Model.Description = newValue); + } + } + } +} + diff --git a/Sources/ViewModels/SkinVM.cs b/Sources/ViewModels/SkinVM.cs new file mode 100644 index 0000000..358ec97 --- /dev/null +++ b/Sources/ViewModels/SkinVM.cs @@ -0,0 +1,65 @@ +using System; +using System.Reflection.PortableExecutable; +using System.Security.Claims; +using CommunityToolkit.Mvvm.ComponentModel; +using Model; + +namespace ViewModels +{ + [ObservableObject] + public partial class SkinVM + { + public Skin Model + { + get => model; + set + { + model = value; + OnPropertyChanged(nameof(Name)); + OnPropertyChanged(nameof(Description)); + OnPropertyChanged(nameof(Price)); + OnPropertyChanged(nameof(Icon)); + OnPropertyChanged(nameof(Image)); + } + } + private Skin model; + + public SkinVM(Skin model) + => Model = model; + + public string Name => Model.Name; + + public string Description + { + get => Model.Description; + set => SetProperty(Model.Description, value, newValue => Model.Description = newValue); + } + + public float Price + { + get => Model.Price; + set => SetProperty(Model.Price, value, newValue => Model.Price = newValue); + } + + public string Icon + { + get => Model.Icon; + set + { + SetProperty(Model.Icon, value, newIcon => Model.Icon = newIcon); + } + } + + public string Image + { + get => Model.Image.Base64; + set + { + SetProperty(Model.Image.Base64, value, newImage => Model.Image.Base64 = newImage); + } + } + + public Champion Champion => Model.Champion; + } +} + diff --git a/Sources/ViewModels/SkinsMgrVM.cs b/Sources/ViewModels/SkinsMgrVM.cs new file mode 100644 index 0000000..c51a6cf --- /dev/null +++ b/Sources/ViewModels/SkinsMgrVM.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.ObjectModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Model; + +namespace ViewModels +{ + [ObservableObject] + public partial class SkinsMgrVM + { + internal IDataManager DataMgr { get; set; } + + [ObservableProperty] + private ChampionVM champion; + + public SkinsMgrVM(IDataManager dataManager) + { + DataMgr = dataManager; + } + + [ObservableProperty] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int index = 0; + + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(NbPages))] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int count = 5; + + public int NbPages + { + get + { + if(Count == 0 || NbSkins == 0) + { + return 0; + } + return (NbSkins-1) / Count + 1; + } + } + + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(NbPages))] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int nbSkins = 0; + + [ObservableProperty] + private ObservableCollection skins = new ObservableCollection(); + + [RelayCommand] + async Task LoadSkins() + { + Skins.Clear(); + IEnumerable skins; + if(Champion != null) + { + skins = await DataMgr.SkinsMgr.GetItemsByChampion(Champion.Model, Index, Count,"Name"); + + } + else + { + skins = await DataMgr.SkinsMgr.GetItems(Index, Count, "Name"); + } + + foreach(var skin in skins) + { + if(skin != null) + Skins.Add(new SkinVM(skin)); + } + } + + [RelayCommand(CanExecute =nameof(CanPreviousPage))] + async Task PreviousPage() + { + if(Index > 0) + { + Index--; + await LoadSkins(); + } + } + bool CanPreviousPage() => Index > 0; + + [RelayCommand(CanExecute =nameof(CanNextPage))] + async Task NextPage() + { + if(Index < NbPages-1) + { + Index++; + await LoadSkins(); + } + } + bool CanNextPage() => Index < NbPages-1; + + [RelayCommand(CanExecute =nameof(CanDeleteSkin))] + public async Task DeleteSkin(object skinVM) + { + SkinVM svm = skinVM as SkinVM; + if(svm == null || !Skins.Contains(svm)) return false; + bool result = await DataMgr.SkinsMgr.DeleteItem(svm.Model); + if(result) + { + Skins.Remove(svm); + await LoadSkins(); + } + return result; + } + bool CanDeleteSkin(object svm) + => svm!= null && svm is SkinVM && Skins.Contains(svm); + + public async Task AddSkin(SkinVM skinVM) + { + var added = await DataMgr.SkinsMgr.AddItem(skinVM.Model); + if(added != null) + { + Skins.Add(skinVM); + await LoadSkins(); + } + } + + public async Task EditSkin(SkinVM oldSkin, SkinVM newSkin) + { + var edited = await DataMgr.SkinsMgr.UpdateItem(oldSkin.Model, newSkin.Model); + oldSkin.Model = newSkin.Model; + if(edited != null) + { + await LoadSkins(); + } + } + } +} + diff --git a/Sources/ViewModels/ViewModels.csproj b/Sources/ViewModels/ViewModels.csproj new file mode 100644 index 0000000..dd9fcb2 --- /dev/null +++ b/Sources/ViewModels/ViewModels.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + enable + enable + true + + + + + + + + + + +