diff --git a/.drone.yml b/.drone.yml index 69a77cc..8e5d25b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -17,6 +17,27 @@ steps: - dotnet restore LeagueOfLegends.sln - dotnet build LeagueOfLegends.sln -c Release --no-restore - dotnet publish LeagueOfLegends.sln -c Release --no-restore -o CI_PROJECT_DIR/build/release + + - name: docker-build-and-push + image: plugins/docker + settings: + dockerfile: Sources/apiLOL/Dockerfile + context: Sources/ + registry: hub.codefirst.iut.uca.fr + repo: hub.codefirst.iut.uca.fr/bastien.ollier/lol + + username: + from_secret: SECRET_REGISTRY_USERNAME + password: + from_secret: SECRET_REGISTRY_PASSWORD + + - name: deploy-container + image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest + environment: + IMAGENAME: hub.codefirst.iut.uca.fr/bastien.ollier/lol:latest + CONTAINERNAME: container_lol + COMMAND: create + OVERWRITE: true - name: docker-build-and-push image: plugins/docker @@ -52,7 +73,7 @@ steps: - dotnet sonarscanner end /d:sonar.login=$${PLUGIN_SONAR_TOKEN} secrets: [ SECRET_SONAR_LOGIN ] settings: - # accessible en ligne de commande par ${PLUGIN_SONAR_HOST} + # accessible en ligne de commande par ${PLUGIN_SONAR_HOST} sonar_host: https://codefirst.iut.uca.fr/sonar/ # accessible en ligne de commande par ${PLUGIN_SONAR_TOKEN} sonar_token: diff --git a/Sources/EFLol/ChampionEntity.cs b/Sources/EFLol/ChampionEntity.cs index b23a534..39c0042 100644 --- a/Sources/EFLol/ChampionEntity.cs +++ b/Sources/EFLol/ChampionEntity.cs @@ -11,13 +11,17 @@ namespace EFLol public string Name { get; set; } [MaxLength(256, ErrorMessage = "Bio cannot be longer than 256 characters.")] - public string Bio { get; set; } - - //public ChampionClass Class { get; set; } - //public string Icon { get; set; } - //public LargeImage Image { get; set; } - //public ReadOnlyDictionary Characteristics { get; private set; } - //private HashSet skills = new HashSet(); - public ReadOnlyCollection Skins { get; set; } - } + public string Bio { get; set; } + + //public ChampionClass Class { get; set; } + //public string Icon { get; set; } + //public LargeImage Image { get; set; } + //public ReadOnlyDictionary Characteristics { get; private set; } + + + + public HashSet skills = new HashSet(); + public Collection Skins { get; set; } + public Collection ListRunePages { get; set; } +} } diff --git a/Sources/EFLol/DBDataManager/DataConverter.cs b/Sources/EFLol/DBDataManager/DataConverter.cs new file mode 100644 index 0000000..d0e23f8 --- /dev/null +++ b/Sources/EFLol/DBDataManager/DataConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Model; + +namespace EFLol.DBDataManager +{ + public static class DataConverter + { + public static Champion ChampionToPoco(this ChampionEntity champion) + { + return new Champion(champion.Name, champion.Bio); + } + + public static ChampionEntity ChampionToEntity(this Champion champion) + { + return new ChampionEntity + { + Name = champion.Name, + Bio = champion.Bio + }; + } + } +} diff --git a/Sources/EFLol/DBDataManager/EFDataManager.cs b/Sources/EFLol/DBDataManager/EFDataManager.cs new file mode 100644 index 0000000..9c3ab0e --- /dev/null +++ b/Sources/EFLol/DBDataManager/EFDataManager.cs @@ -0,0 +1,165 @@ +using Microsoft.EntityFrameworkCore; +using Model; + + +namespace EFLol.DBDataManager +{ + public class EFDataManager : IDataManager + { + public IChampionsManager ChampionsMgr => new EFChampionManager(); + + public ISkinsManager SkinsMgr => throw new NotImplementedException(); + + public IRunesManager RunesMgr => throw new NotImplementedException(); + + public IRunePagesManager RunePagesMgr => throw new NotImplementedException(); + } + + public class EFChampionManager : IChampionsManager + { + private MyDbContext _context; + + public EFChampionManager() + { + _context = new MyDbContext(); + } + + public async Task AddItem(Champion? item) + { + if (item == null) + { + throw new Exception("Item is null"); + } + + _context.Add(item.ChampionToEntity()); + _context.SaveChanges(); + return item; + } + + + public async Task DeleteItem(Champion? item) + { + if (item == null) + { + return false; + } + + var champ = _context.Champions.Select(c => c == item.ChampionToEntity()); + + if (champ.Count() < 1) + { + return false; + } + + _context.Champions.Remove(item.ChampionToEntity()); + _context.SaveChanges(); + return true; + } + + + public async Task UpdateItem(Champion? oldItem, Champion? newItem) + { + if (oldItem != null && newItem != null) + { + var champEntity = await _context.Champions.FirstOrDefaultAsync(c => c.Name == oldItem.Name); + if (champEntity == null) + { + throw new Exception("Champion not found in database"); + } + champEntity.Bio = newItem.Bio; + _context.SaveChanges(); + return champEntity.ChampionToPoco(); + } + throw new Exception("Invalid input parameters"); + } + + + public async Task GetNbItems() => _context.Champions.Count(); + + + public async Task> GetItems(int index, int count, string? orderingPropertyName = null, + bool descending = false) + { + IEnumerable champions = _context.Champions.Skip(index * count) + .Take(count) + .OrderBy(champions => orderingPropertyName) + .Select(champions => champions.ChampionToPoco()); + return champions; + } + + + private Func filterByName = (champion, substring) => + champion.Name.IndexOf(substring, StringComparison.InvariantCultureIgnoreCase) >= 0; + + + public Task> GetItemsByName(string substring, int index, int count, + string? orderingPropertyName = null, bool descending = false) + => _context.Champions.Select(champion => champion.ChampionToPoco()) + .GetItemsWithFilterAndOrdering(champ => filterByName(champ, substring), index, count, + orderingPropertyName, descending); + + public Task GetNbItemsByName(string substring) + { + throw new NotImplementedException(); + } + + + public Task GetNbItemsByCharacteristic(string charName) + { + throw new NotImplementedException(); + } + + public Task> GetItemsByCharacteristic(string charName, int index, int count, + string? orderingPropertyName = null, + bool @descending = false) + { + throw new NotImplementedException(); + } + + public Task GetNbItemsByClass(ChampionClass championClass) + { + throw new NotImplementedException(); + } + + public Task> GetItemsByClass(ChampionClass championClass, int index, int count, + string? orderingPropertyName = null, + bool @descending = false) + { + throw new NotImplementedException(); + } + + public Task GetNbItemsBySkill(Skill? skill) + { + throw new NotImplementedException(); + } + + public Task> GetItemsBySkill(Skill? skill, int index, int count, + string? orderingPropertyName = null, bool @descending = false) + { + throw new NotImplementedException(); + } + + public Task GetNbItemsByRunePage(RunePage? runePage) + { + throw new NotImplementedException(); + } + + public Task> GetItemsByRunePage(RunePage? runePage, int index, int count, + string? orderingPropertyName = null, + bool @descending = false) + { + throw new NotImplementedException(); + } + + public Task GetNbItemsBySkill(string skill) + { + throw new NotImplementedException(); + } + + public Task> GetItemsBySkill(string skill, int index, int count, + string? orderingPropertyName = null, bool @descending = false) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/Sources/EFLol/DBDataManager/ExtensionsDataManager.cs b/Sources/EFLol/DBDataManager/ExtensionsDataManager.cs new file mode 100644 index 0000000..3b7986c --- /dev/null +++ b/Sources/EFLol/DBDataManager/ExtensionsDataManager.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EFLol.DBDataManager +{ + static class ExtensionsDataManager + { + internal static Task> GetItemsWithFilterAndOrdering(this IEnumerable collection, + Func filter, int index, int count, string? orderingPropertyName = null, bool descending = false) + { + IEnumerable temp = collection; + temp = temp.Where(item => filter(item)); + if (orderingPropertyName != null) + { + var prop = typeof(T).GetProperty(orderingPropertyName!); + if (prop != null) + { + temp = descending + ? temp.OrderByDescending(item => prop.GetValue(item)) + : temp.OrderBy(item => prop.GetValue(item)); + } + } + + return Task.FromResult>(temp.Skip(index * count).Take(count)); + } + + internal static Task GetNbItemsWithFilter(this IEnumerable collection, Func filter) + { + return Task.FromResult(collection.Count(item => filter(item))); + } + + internal static Task AddItem(this IList collection, T? item) + { + if (item == null || collection.Contains(item)) + { + return Task.FromResult(default(T)); + } + + collection.Add(item); + return Task.FromResult(item); + } + + internal static Task DeleteItem(this IList collection, T? item) + { + if (item == null) + { + return Task.FromResult(false); + } + + bool result = collection.Remove(item!); + return Task.FromResult(result); + } + + internal static Task UpdateItem(this IList collection, T? oldItem, T? newItem) + { + if (oldItem == null || newItem == null) return Task.FromResult(default(T)); + + if (!collection.Contains(oldItem)) + { + return Task.FromResult(default(T)); + } + + collection.Remove(oldItem!); + collection.Add(newItem!); + return Task.FromResult(newItem); + } + } +} \ No newline at end of file diff --git a/Sources/EFLol/EFLol.csproj b/Sources/EFLol/EFLol.csproj index bbc403a..17e021f 100644 --- a/Sources/EFLol/EFLol.csproj +++ b/Sources/EFLol/EFLol.csproj @@ -24,5 +24,10 @@ + + + + + diff --git a/Sources/EFLol/MyDbContext.cs b/Sources/EFLol/MyDbContext.cs index 17ad759..b105cc1 100644 --- a/Sources/EFLol/MyDbContext.cs +++ b/Sources/EFLol/MyDbContext.cs @@ -1,37 +1,46 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; - -namespace EFLol -{ - public class MyDbContext : DbContext - { - public DbSet Champions { get; set; } - public DbSet Skins { get; set; } - - public MyDbContext() - { } - - public MyDbContext(DbContextOptions options) - : base(options) - { } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - if (!optionsBuilder.IsConfigured) - { - optionsBuilder.UseSqlite("Data Source=loldb.db"); - } - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - modelBuilder.Entity().Property(c => c.Id).ValueGeneratedOnAdd(); - modelBuilder.Entity().Property(s => s.Id).ValueGeneratedOnAdd(); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; + +namespace EFLol +{ + public class MyDbContext : DbContext + { + public DbSet Champions { get; set; } + public DbSet Skins { get; set; } + public DbSet Skill { get; set; } + public DbSet RunePages { get; set; } + public DbSet Runes { get; set; } + + public MyDbContext() + { } + + public MyDbContext(DbContextOptions options) + : base(options) + { } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (!optionsBuilder.IsConfigured) + { + optionsBuilder.UseSqlite("Data Source=../EFLol/loldb.db"); + } + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + modelBuilder.Entity().Property(c => c.Id).ValueGeneratedOnAdd(); + modelBuilder.Entity().Property(s => s.Id).ValueGeneratedOnAdd(); + modelBuilder.Entity().Property(s => s.Id).ValueGeneratedOnAdd(); + + modelBuilder.Entity().HasMany(p => p.skills).WithMany(p => p.champions).UsingEntity(j => j.ToTable("ChampionSkills")); + + modelBuilder.Entity().Property(s => s.Id).ValueGeneratedOnAdd(); + modelBuilder.Entity().Property(s => s.Id).ValueGeneratedOnAdd(); + } + } +} diff --git a/Sources/EFLol/Program.cs b/Sources/EFLol/Program.cs index fbac836..6720439 100644 --- a/Sources/EFLol/Program.cs +++ b/Sources/EFLol/Program.cs @@ -1,67 +1,105 @@ -using System.Collections.ObjectModel; -using EFLol; - - -using (var context = new MyDbContext()) -{ - // Clean the DB before starting - Console.WriteLine("Clean the DB before starting"); - context.Database.EnsureDeleted(); - context.Database.EnsureCreated(); -} - -SkinEntity black = new SkinEntity { Name = "Black", Description = "Black skin", Icon = "black.png", Price = 0.99f }; -SkinEntity white = new SkinEntity { Name = "White", Description = "White skin", Icon = "white.png", Price = 150.99f }; -SkinEntity green = new SkinEntity { Name = "Green", Description = "Green skin", Icon = "green.png", Price = 4.99f }; - -ChampionEntity Zeus = new ChampionEntity -{ - Name = "Zeus", - Bio = "Zeus is the god of the sky", - Skins = new ReadOnlyCollection(new List { black, white }) - -}; -ChampionEntity Hera = new ChampionEntity -{ - Name = "Hera", - Bio = "Hera is the goddess of marriage", - Skins = new ReadOnlyCollection(new List { green }) - -}; -ChampionEntity Poseidon = new ChampionEntity { Name = "Poseidon", Bio = "Poseidon is the god of the sea" }; - - - -using (var context = new MyDbContext()) -{ - // Crée des champions et les insère dans la base - Console.WriteLine("Creates and inserts new Champions"); - context.Add(Zeus); - context.Add(Hera); - context.Add(Poseidon); - context.SaveChanges(); -} - - -using (var context = new MyDbContext()) -{ - foreach (var n in context.Champions) - { - // Use LINQ to display the skins for each champion - var skins = from s in context.Skins - where n.Id == s.Id - select s; - - Console.WriteLine($"Champion n°{n.Id} - {n.Name}"); - } - context.SaveChanges(); -} - -using (var context = new MyDbContext()) -{ - foreach (var n in context.Skins) - { - Console.WriteLine($"Skin n°{n.Id} - {n.Name}" + (n.Price != null ? $" - {n.Price}" : "")); - } - context.SaveChanges(); +using System.Collections.Generic; +using System.Collections.ObjectModel; +using EFLol; + + +internal class Program +{ + private static void Main(string[] args) + { + using (var context = new MyDbContext()) + { + // Clean the DB before starting + Console.WriteLine("Clean the DB before starting"); + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + } + + + SkinEntity black = new SkinEntity { Name = "Black", Description = "Black skin", Icon = "black.png", Price = 0.99f }; + SkinEntity white = new SkinEntity { Name = "White", Description = "White skin", Icon = "white.png", Price = 150.99f }; + SkinEntity green = new SkinEntity { Name = "Green", Description = "Green skin", Icon = "green.png", Price = 4.99f }; + + + RuneEntity rune1 = new RuneEntity { Id = 1, Name = "rune1", Description = "super rune1" }; + RuneEntity rune2 = new RuneEntity { Id = 2, Name = "rune2", Description = "super rune2" }; + RuneEntity rune3 = new RuneEntity { Id = 3, Name = "rune3", Description = "super rune3" }; + + RunePageEntity runePage1 = new RunePageEntity { Id = 1, Name = "runepage1"/*, Runes = new Dictionary { { Category.Major, rune1 } }*/ }; + + ChampionEntity Zeus = new ChampionEntity { Name = "Zeus", Bio = "Zeus is the god of the sky", Skins = new Collection(new List { black, white }) }; + ChampionEntity Hera = new ChampionEntity { Name = "Hera", Bio = "Hera is the goddess of marriage", Skins = new Collection(new List { green }) }; + ChampionEntity Poseidon = new ChampionEntity { + Name = "Poseidon", Bio = "Poseidon is the god of the sea", + ListRunePages = new Collection(new List { { runePage1 } }) + }; + + SkillEntity skill1 = new SkillEntity + { + Id = 1, + Name = "skill1", + Description = "super skill", + SkillType = SkillTypeEntity.Basic, + champions = new HashSet { Zeus, Hera } + }; + + SkillEntity skill2 = new SkillEntity + { + Id = 2, + Name = "skill2", + Description = "super skill", + SkillType = SkillTypeEntity.Basic, + champions = new HashSet { Zeus} + }; + + Zeus.skills.Add(skill1); + Zeus.skills.Add(skill2); + + Hera.skills.Add(skill1); + + using (var context = new MyDbContext()) + { + Console.WriteLine("Creates and inserts new Champions"); + context.Add(Zeus); + context.Add(Hera); + context.Add(Poseidon); + + context.Add(skill1); + context.Add(skill2); + context.SaveChanges(); + } + + + using (var context = new MyDbContext()) + { + foreach (var n in context.Champions) + { + // LINQ to select the skins of the current champion + var skins = context.Champions.Where(c => c.Id == n.Id).SelectMany(c => c.Skins); + var runePage = context.Champions.Where(c => c.Id == n.Id).SelectMany(c => c.ListRunePages); + + // Display the champion and its skins + Console.WriteLine($"Champion n°{n.Id} - {n.Name} : {skins.Count()} skins, {runePage.Count()} runePage"); + } + context.SaveChanges(); + } + + using (var context = new MyDbContext()) + { + foreach (var n in context.Skins) + { + Console.WriteLine($"Skin n°{n.Id} - {n.Name}" + (n.Price != null ? $" - {n.Price}" : "")); + } + context.SaveChanges(); + } + + using (var context = new MyDbContext()) + { + foreach (var n in context.RunePages) + { + Console.WriteLine($"runePage n°{n.Id} - {n.Name}"); + } + context.SaveChanges(); + } + } } \ No newline at end of file diff --git a/Sources/EFLol/RuneEntity.cs b/Sources/EFLol/RuneEntity.cs new file mode 100644 index 0000000..6b492fb --- /dev/null +++ b/Sources/EFLol/RuneEntity.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EFLol +{ + public class RuneEntity + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public RuneFamilyEntity RuneFamily { get; set; } + public Collection ListRunePages { get; set; } + } + + public enum RuneFamilyEntity + { + Unknown, + Precision, + Domination + } + +} + diff --git a/Sources/EFLol/RunePageEntity.cs b/Sources/EFLol/RunePageEntity.cs new file mode 100644 index 0000000..4649f76 --- /dev/null +++ b/Sources/EFLol/RunePageEntity.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EFLol +{ + public class RunePageEntity + { + public int Id { get; set; } + public String Name { get; set; } + //public Dictionary Runes { get; set; } + } + + public enum Category + { + Major, + Minor1, + Minor2, + Minor3, + OtherMinor1, + OtherMinor2 + } +} diff --git a/Sources/EFLol/SkillEntity.cs b/Sources/EFLol/SkillEntity.cs new file mode 100644 index 0000000..c9c90ee --- /dev/null +++ b/Sources/EFLol/SkillEntity.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EFLol +{ + public class SkillEntity + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public SkillTypeEntity SkillType { get; set; } + public HashSet champions { get; set; } + + } + + public enum SkillTypeEntity + { + Unknown, + Basic, + Passive, + Ultimate + } +} diff --git a/Sources/LeagueOfLegends.sln b/Sources/LeagueOfLegends.sln index 2d87936..b0489f8 100644 --- a/Sources/LeagueOfLegends.sln +++ b/Sources/LeagueOfLegends.sln @@ -1,83 +1,83 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32616.157 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Model", "Model\Model.csproj", "{2960F9BA-49DE-494D-92E3-CE5A794BA1A9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C76D0C23-1FFA-4963-93CD-E12BD643F030}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleTests", "Tests\ConsoleTests\ConsoleTests.csproj", "{1889FA6E-B7C6-416E-8628-9449FB9070B9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{3B720C0C-53FE-4642-A2DB-87FD8634CD74}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stub", "Stub", "{2C607793-B163-4731-A4D1-AFE8A7C4C170}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StubLib", "StubLib\StubLib.csproj", "{B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}" - ProjectSection(ProjectDependencies) = postProject - {3B720C0C-53FE-4642-A2DB-87FD8634CD74} = {3B720C0C-53FE-4642-A2DB-87FD8634CD74} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "apiLOL", "apiLOL\apiLOL.csproj", "{65B824B5-FADB-4C89-8B4B-D541B62B7DCA}" - ProjectSection(ProjectDependencies) = postProject - {1889FA6E-B7C6-416E-8628-9449FB9070B9} = {1889FA6E-B7C6-416E-8628-9449FB9070B9} - {2960F9BA-49DE-494D-92E3-CE5A794BA1A9} = {2960F9BA-49DE-494D-92E3-CE5A794BA1A9} - {3B720C0C-53FE-4642-A2DB-87FD8634CD74} = {3B720C0C-53FE-4642-A2DB-87FD8634CD74} - {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB} = {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFLol", "EFLol\EFLol.csproj", "{7AEE66D2-490B-4049-B9D3-C629D7F78DA7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestUnitaire", "TestUnitaire\TestUnitaire.csproj", "{5702F240-97BD-4757-918C-6E485C57D0EC}" - ProjectSection(ProjectDependencies) = postProject - {65B824B5-FADB-4C89-8B4B-D541B62B7DCA} = {65B824B5-FADB-4C89-8B4B-D541B62B7DCA} - {7AEE66D2-490B-4049-B9D3-C629D7F78DA7} = {7AEE66D2-490B-4049-B9D3-C629D7F78DA7} - {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB} = {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Release|Any CPU.Build.0 = Release|Any CPU - {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Release|Any CPU.Build.0 = Release|Any CPU - {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Release|Any CPU.Build.0 = Release|Any CPU - {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Release|Any CPU.Build.0 = Release|Any CPU - {65B824B5-FADB-4C89-8B4B-D541B62B7DCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {65B824B5-FADB-4C89-8B4B-D541B62B7DCA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {65B824B5-FADB-4C89-8B4B-D541B62B7DCA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {65B824B5-FADB-4C89-8B4B-D541B62B7DCA}.Release|Any CPU.Build.0 = Release|Any CPU - {7AEE66D2-490B-4049-B9D3-C629D7F78DA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7AEE66D2-490B-4049-B9D3-C629D7F78DA7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7AEE66D2-490B-4049-B9D3-C629D7F78DA7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7AEE66D2-490B-4049-B9D3-C629D7F78DA7}.Release|Any CPU.Build.0 = Release|Any CPU - {5702F240-97BD-4757-918C-6E485C57D0EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5702F240-97BD-4757-918C-6E485C57D0EC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5702F240-97BD-4757-918C-6E485C57D0EC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5702F240-97BD-4757-918C-6E485C57D0EC}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {1889FA6E-B7C6-416E-8628-9449FB9070B9} = {C76D0C23-1FFA-4963-93CD-E12BD643F030} - {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB} = {2C607793-B163-4731-A4D1-AFE8A7C4C170} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {92F3083D-793F-4552-8A9A-0AD6534159C9} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32616.157 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Model", "Model\Model.csproj", "{2960F9BA-49DE-494D-92E3-CE5A794BA1A9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C76D0C23-1FFA-4963-93CD-E12BD643F030}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleTests", "Tests\ConsoleTests\ConsoleTests.csproj", "{1889FA6E-B7C6-416E-8628-9449FB9070B9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{3B720C0C-53FE-4642-A2DB-87FD8634CD74}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stub", "Stub", "{2C607793-B163-4731-A4D1-AFE8A7C4C170}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StubLib", "StubLib\StubLib.csproj", "{B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}" + ProjectSection(ProjectDependencies) = postProject + {3B720C0C-53FE-4642-A2DB-87FD8634CD74} = {3B720C0C-53FE-4642-A2DB-87FD8634CD74} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "apiLOL", "apiLOL\apiLOL.csproj", "{65B824B5-FADB-4C89-8B4B-D541B62B7DCA}" + ProjectSection(ProjectDependencies) = postProject + {1889FA6E-B7C6-416E-8628-9449FB9070B9} = {1889FA6E-B7C6-416E-8628-9449FB9070B9} + {2960F9BA-49DE-494D-92E3-CE5A794BA1A9} = {2960F9BA-49DE-494D-92E3-CE5A794BA1A9} + {3B720C0C-53FE-4642-A2DB-87FD8634CD74} = {3B720C0C-53FE-4642-A2DB-87FD8634CD74} + {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB} = {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFLol", "EFLol\EFLol.csproj", "{7AEE66D2-490B-4049-B9D3-C629D7F78DA7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUnitaire", "TestUnitaire\TestUnitaire.csproj", "{5702F240-97BD-4757-918C-6E485C57D0EC}" + ProjectSection(ProjectDependencies) = postProject + {65B824B5-FADB-4C89-8B4B-D541B62B7DCA} = {65B824B5-FADB-4C89-8B4B-D541B62B7DCA} + {7AEE66D2-490B-4049-B9D3-C629D7F78DA7} = {7AEE66D2-490B-4049-B9D3-C629D7F78DA7} + {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB} = {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Release|Any CPU.Build.0 = Release|Any CPU + {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Release|Any CPU.Build.0 = Release|Any CPU + {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Release|Any CPU.Build.0 = Release|Any CPU + {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Release|Any CPU.Build.0 = Release|Any CPU + {65B824B5-FADB-4C89-8B4B-D541B62B7DCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65B824B5-FADB-4C89-8B4B-D541B62B7DCA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65B824B5-FADB-4C89-8B4B-D541B62B7DCA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65B824B5-FADB-4C89-8B4B-D541B62B7DCA}.Release|Any CPU.Build.0 = Release|Any CPU + {7AEE66D2-490B-4049-B9D3-C629D7F78DA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7AEE66D2-490B-4049-B9D3-C629D7F78DA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7AEE66D2-490B-4049-B9D3-C629D7F78DA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7AEE66D2-490B-4049-B9D3-C629D7F78DA7}.Release|Any CPU.Build.0 = Release|Any CPU + {5702F240-97BD-4757-918C-6E485C57D0EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5702F240-97BD-4757-918C-6E485C57D0EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5702F240-97BD-4757-918C-6E485C57D0EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5702F240-97BD-4757-918C-6E485C57D0EC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {1889FA6E-B7C6-416E-8628-9449FB9070B9} = {C76D0C23-1FFA-4963-93CD-E12BD643F030} + {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB} = {2C607793-B163-4731-A4D1-AFE8A7C4C170} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {92F3083D-793F-4552-8A9A-0AD6534159C9} + EndGlobalSection +EndGlobal diff --git a/Sources/LolApp/AddChampionPage.xaml b/Sources/LolApp/AddChampionPage.xaml new file mode 100644 index 0000000..7f38acb --- /dev/null +++ b/Sources/LolApp/AddChampionPage.xaml @@ -0,0 +1,142 @@ + + + + + + + + + diff --git a/Sources/LolApp/ChampionsPage.xaml.cs b/Sources/LolApp/ChampionsPage.xaml.cs new file mode 100644 index 0000000..6aa38a7 --- /dev/null +++ b/Sources/LolApp/ChampionsPage.xaml.cs @@ -0,0 +1,17 @@ +using LolApp.ViewModels; +using ViewModels; + +namespace LolApp; + +public partial class ChampionsPage : ContentPage +{ + public ApplicationVM AppVM { get; } + public ChampionsPageVM VM { get; } + public ChampionsPage(ApplicationVM appVM) + { + InitializeComponent(); + AppVM = appVM; + VM = new ChampionsPageVM(AppVM.ChampionsMgrVM); + BindingContext = this; + } +} diff --git a/Sources/LolApp/ContentViews/ChampionClassSelector.xaml b/Sources/LolApp/ContentViews/ChampionClassSelector.xaml new file mode 100644 index 0000000..6dc66e4 --- /dev/null +++ b/Sources/LolApp/ContentViews/ChampionClassSelector.xaml @@ -0,0 +1,131 @@ + + + + + Assassin + Fighter + Mage + Marksman + Support + Tank + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/ContentViews/ChampionClassSelector.xaml.cs b/Sources/LolApp/ContentViews/ChampionClassSelector.xaml.cs new file mode 100644 index 0000000..74fb508 --- /dev/null +++ b/Sources/LolApp/ContentViews/ChampionClassSelector.xaml.cs @@ -0,0 +1,34 @@ +using Model; + +namespace LolApp.ContentViews; + +public partial class ChampionClassSelector : ContentView +{ + public ChampionClassSelector() + { + InitializeComponent(); + } + + public static readonly BindableProperty SelectedValueProperty = BindableProperty.Create(nameof(SelectedValue), typeof(ChampionClass), typeof(ChampionClassSelector), ChampionClass.Unknown, BindingMode.TwoWay); + public ChampionClass SelectedValue + { + get => (ChampionClass)GetValue(SelectedValueProperty); + set => SetValue(SelectedValueProperty, value); + } + + public static readonly BindableProperty CheckedColorProperty = BindableProperty.Create(nameof(CheckedColor), typeof(Color), typeof(ChampionClassSelector), Colors.DarkSalmon); + + public Color CheckedColor + { + get => (Color)GetValue(CheckedColorProperty); + set => SetValue(CheckedColorProperty, value); + } + + public static readonly BindableProperty UncheckedColorProperty = BindableProperty.Create(nameof(UncheckedColor), typeof(Color), typeof(ChampionClassSelector), Colors.DarkSalmon); + + public Color UncheckedColor + { + get => (Color)GetValue(UncheckedColorProperty); + set => SetValue(UncheckedColorProperty, value); + } +} diff --git a/Sources/LolApp/ContentViews/SearchByStringView.cs b/Sources/LolApp/ContentViews/SearchByStringView.cs new file mode 100644 index 0000000..308ce0d --- /dev/null +++ b/Sources/LolApp/ContentViews/SearchByStringView.cs @@ -0,0 +1,38 @@ +using System.Windows.Input; + +namespace LolApp.ContentViews; + +public class SearchByStringView : ContentView +{ + public static readonly BindableProperty PlaceHolderProperty = BindableProperty.Create(nameof(PlaceHolder), typeof(string), typeof(SearchByStringView), string.Empty); + + public string PlaceHolder + { + get => (string)GetValue(PlaceHolderProperty); + set => SetValue(PlaceHolderProperty, value); + } + + public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(SearchByStringView), string.Empty); + + public string Text + { + get => (string)GetValue(TextProperty); + set => SetValue(TextProperty, value); + } + + public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(SearchByStringView), null); + + public ICommand Command + { + get => (ICommand)GetValue(CommandProperty); + set => SetValue(CommandProperty, value); + } + + public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(SearchByStringView), null); + + public object CommandParameter + { + get => GetValue(CommandParameterProperty); + set => SetValue(CommandParameterProperty, value); + } +} diff --git a/Sources/LolApp/LolApp.csproj b/Sources/LolApp/LolApp.csproj new file mode 100644 index 0000000..ab4fa0c --- /dev/null +++ b/Sources/LolApp/LolApp.csproj @@ -0,0 +1,99 @@ + + + + net7.0-android;net7.0-ios;net7.0-maccatalyst + Exe + LolApp + true + true + enable + + + LolApp + + + fr.uca.iut.lolapp + d3cd18a9-c614-4933-bd36-3008e72004d5 + + + 1.0 + 1 + + 14.2 + 14.0 + 21.0 + 10.0.17763.0 + 10.0.17763.0 + 6.5 + {0C898A04-092A-49AA-BE65-8AE818A2AF50} + + + + false + appleIUT_TP2022 + iPhone Developer: Cedric BOUHOURS (M2E3ZQNZ3K) + + + false + Developer ID Application + 3rd Party Mac Developer Installer + + + false + + + $(TargetFrameworks);net7.0-windows10.0.22621.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/MainPage.xaml b/Sources/LolApp/MainPage.xaml new file mode 100644 index 0000000..9db8163 --- /dev/null +++ b/Sources/LolApp/MainPage.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + diff --git a/Sources/LolApp/MainPage.xaml.cs b/Sources/LolApp/MainPage.xaml.cs new file mode 100644 index 0000000..0750b67 --- /dev/null +++ b/Sources/LolApp/MainPage.xaml.cs @@ -0,0 +1,11 @@ +namespace LolApp; + +public partial class MainPage : ContentPage +{ + public MainPage() + { + InitializeComponent(); + } +} + + diff --git a/Sources/LolApp/MauiProgram.cs b/Sources/LolApp/MauiProgram.cs new file mode 100644 index 0000000..c12deff --- /dev/null +++ b/Sources/LolApp/MauiProgram.cs @@ -0,0 +1,39 @@ +using CommunityToolkit.Maui; +using LolApp.ViewModels; +using Microsoft.Extensions.Logging; +using Microsoft.Maui.Handlers; +using Microsoft.Maui.Platform; +using Model; +using StubLib; +using ViewModels; + +namespace LolApp; + +public static class MauiProgram +{ + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + builder + .UseMauiApp() + .UseMauiCommunityToolkit() + .ConfigureFonts(fonts => + { + fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); + fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); + fonts.AddFont("Font Awesome 6 Free-Solid-900.otf", "FASolid"); + }); + builder.Services.AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton(); + +#if DEBUG + builder.Logging.AddDebug(); +#endif + + return builder.Build(); + } +} + diff --git a/Sources/LolApp/Platforms/Android/AndroidManifest.xml b/Sources/LolApp/Platforms/Android/AndroidManifest.xml new file mode 100644 index 0000000..e6c8a36 --- /dev/null +++ b/Sources/LolApp/Platforms/Android/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Sources/LolApp/Platforms/Android/MainActivity.cs b/Sources/LolApp/Platforms/Android/MainActivity.cs new file mode 100644 index 0000000..016887c --- /dev/null +++ b/Sources/LolApp/Platforms/Android/MainActivity.cs @@ -0,0 +1,11 @@ +using Android.App; +using Android.Content.PM; +using Android.OS; + +namespace LolApp; + +[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] +public class MainActivity : MauiAppCompatActivity +{ +} + diff --git a/Sources/LolApp/Platforms/Android/MainApplication.cs b/Sources/LolApp/Platforms/Android/MainApplication.cs new file mode 100644 index 0000000..95e1d92 --- /dev/null +++ b/Sources/LolApp/Platforms/Android/MainApplication.cs @@ -0,0 +1,16 @@ +using Android.App; +using Android.Runtime; + +namespace LolApp; + +[Application] +public class MainApplication : MauiApplication +{ + public MainApplication(IntPtr handle, JniHandleOwnership ownership) + : base(handle, ownership) + { + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} + diff --git a/Sources/LolApp/Platforms/Android/Resources/values/colors.xml b/Sources/LolApp/Platforms/Android/Resources/values/colors.xml new file mode 100644 index 0000000..c2794f7 --- /dev/null +++ b/Sources/LolApp/Platforms/Android/Resources/values/colors.xml @@ -0,0 +1,7 @@ + + + #512BD4 + #2B0B98 + #2B0B98 + + diff --git a/Sources/LolApp/Platforms/MacCatalyst/AppDelegate.cs b/Sources/LolApp/Platforms/MacCatalyst/AppDelegate.cs new file mode 100644 index 0000000..d5d15a5 --- /dev/null +++ b/Sources/LolApp/Platforms/MacCatalyst/AppDelegate.cs @@ -0,0 +1,10 @@ +using Foundation; + +namespace LolApp; + +[Register("AppDelegate")] +public class AppDelegate : MauiUIApplicationDelegate +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} + diff --git a/Sources/LolApp/Platforms/MacCatalyst/Info.plist b/Sources/LolApp/Platforms/MacCatalyst/Info.plist new file mode 100644 index 0000000..ec44095 --- /dev/null +++ b/Sources/LolApp/Platforms/MacCatalyst/Info.plist @@ -0,0 +1,36 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + NSCameraUsageDescription + New Entry + NSPhotoLibraryUsageDescription + New Entry + NSPhotoLibraryAddUsageDescription + New Entry + + diff --git a/Sources/LolApp/Platforms/MacCatalyst/Program.cs b/Sources/LolApp/Platforms/MacCatalyst/Program.cs new file mode 100644 index 0000000..f1b8f29 --- /dev/null +++ b/Sources/LolApp/Platforms/MacCatalyst/Program.cs @@ -0,0 +1,16 @@ +using ObjCRuntime; +using UIKit; + +namespace LolApp; + +public class Program +{ + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppDelegate)); + } +} + diff --git a/Sources/LolApp/Platforms/Tizen/Main.cs b/Sources/LolApp/Platforms/Tizen/Main.cs new file mode 100644 index 0000000..d58b3d9 --- /dev/null +++ b/Sources/LolApp/Platforms/Tizen/Main.cs @@ -0,0 +1,17 @@ +using System; +using Microsoft.Maui; +using Microsoft.Maui.Hosting; + +namespace LolApp; + +class Program : MauiApplication +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + + static void Main(string[] args) + { + var app = new Program(); + app.Run(args); + } +} + diff --git a/Sources/LolApp/Platforms/Tizen/tizen-manifest.xml b/Sources/LolApp/Platforms/Tizen/tizen-manifest.xml new file mode 100644 index 0000000..109d29f --- /dev/null +++ b/Sources/LolApp/Platforms/Tizen/tizen-manifest.xml @@ -0,0 +1,15 @@ + + + + + + maui-appicon-placeholder + + + + + http://tizen.org/privilege/internet + + + + diff --git a/Sources/LolApp/Platforms/Windows/App.xaml b/Sources/LolApp/Platforms/Windows/App.xaml new file mode 100644 index 0000000..23c64b9 --- /dev/null +++ b/Sources/LolApp/Platforms/Windows/App.xaml @@ -0,0 +1,9 @@ + + + + diff --git a/Sources/LolApp/Platforms/Windows/App.xaml.cs b/Sources/LolApp/Platforms/Windows/App.xaml.cs new file mode 100644 index 0000000..c3b0669 --- /dev/null +++ b/Sources/LolApp/Platforms/Windows/App.xaml.cs @@ -0,0 +1,25 @@ +using Microsoft.UI.Xaml; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace LolApp.WinUI; + +/// +/// Provides application-specific behavior to supplement the default Application class. +/// +public partial class App : MauiWinUIApplication +{ + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + this.InitializeComponent(); + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} + + diff --git a/Sources/LolApp/Platforms/Windows/Package.appxmanifest b/Sources/LolApp/Platforms/Windows/Package.appxmanifest new file mode 100644 index 0000000..52b7801 --- /dev/null +++ b/Sources/LolApp/Platforms/Windows/Package.appxmanifest @@ -0,0 +1,47 @@ + + + + + + + + + $placeholder$ + User Name + $placeholder$.png + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/Platforms/Windows/app.manifest b/Sources/LolApp/Platforms/Windows/app.manifest new file mode 100644 index 0000000..91a1b32 --- /dev/null +++ b/Sources/LolApp/Platforms/Windows/app.manifest @@ -0,0 +1,16 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + + diff --git a/Sources/LolApp/Platforms/iOS/AppDelegate.cs b/Sources/LolApp/Platforms/iOS/AppDelegate.cs new file mode 100644 index 0000000..d5d15a5 --- /dev/null +++ b/Sources/LolApp/Platforms/iOS/AppDelegate.cs @@ -0,0 +1,10 @@ +using Foundation; + +namespace LolApp; + +[Register("AppDelegate")] +public class AppDelegate : MauiUIApplicationDelegate +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} + diff --git a/Sources/LolApp/Platforms/iOS/Info.plist b/Sources/LolApp/Platforms/iOS/Info.plist new file mode 100644 index 0000000..352a326 --- /dev/null +++ b/Sources/LolApp/Platforms/iOS/Info.plist @@ -0,0 +1,38 @@ + + + + + LSRequiresIPhoneOS + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + NSCameraUsageDescription + New Entry + NSPhotoLibraryUsageDescription + Pour accéder aux images... + NSPhotoLibraryAddUsageDescription + Pour accéder aux images... + + diff --git a/Sources/LolApp/Platforms/iOS/Program.cs b/Sources/LolApp/Platforms/iOS/Program.cs new file mode 100644 index 0000000..f1b8f29 --- /dev/null +++ b/Sources/LolApp/Platforms/iOS/Program.cs @@ -0,0 +1,16 @@ +using ObjCRuntime; +using UIKit; + +namespace LolApp; + +public class Program +{ + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppDelegate)); + } +} + diff --git a/Sources/LolApp/Properties/launchSettings.json b/Sources/LolApp/Properties/launchSettings.json new file mode 100644 index 0000000..90f92d9 --- /dev/null +++ b/Sources/LolApp/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Windows Machine": { + "commandName": "MsixPackage", + "nativeDebugging": false + } + } +} diff --git a/Sources/LolApp/Resources/AppIcon/appicon.png b/Sources/LolApp/Resources/AppIcon/appicon.png new file mode 100644 index 0000000..8263b46 Binary files /dev/null and b/Sources/LolApp/Resources/AppIcon/appicon.png differ diff --git a/Sources/LolApp/Resources/AppIcon/appiconfg.svg b/Sources/LolApp/Resources/AppIcon/appiconfg.svg new file mode 100644 index 0000000..e9b7139 --- /dev/null +++ b/Sources/LolApp/Resources/AppIcon/appiconfg.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Sources/LolApp/Resources/Converters/Base64ToImageSourceConverter.cs b/Sources/LolApp/Resources/Converters/Base64ToImageSourceConverter.cs new file mode 100644 index 0000000..e258576 --- /dev/null +++ b/Sources/LolApp/Resources/Converters/Base64ToImageSourceConverter.cs @@ -0,0 +1,34 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using CommunityToolkit.Maui.Converters; + +namespace LolApp.Resources.Converters +{ + public class Base64ToImageSourceConverter : ByteArrayToImageSourceConverter, IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + string base64 = value as string; + if (string.IsNullOrWhiteSpace(base64)) return null; + try + { + byte[] bytes = System.Convert.FromBase64String(base64); + return base.ConvertFrom(bytes, culture); + } + catch + { + return null; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + ImageSource source = value as ImageSource; + if (source == null) return null; + byte[] bytes = base.ConvertBackTo(source, culture) as byte[]; + return System.Convert.ToBase64String(bytes); + } + } +} + diff --git a/Sources/LolApp/Resources/Converters/ChampionClassToIconConverter.cs b/Sources/LolApp/Resources/Converters/ChampionClassToIconConverter.cs new file mode 100644 index 0000000..946b9a6 --- /dev/null +++ b/Sources/LolApp/Resources/Converters/ChampionClassToIconConverter.cs @@ -0,0 +1,42 @@ +using System; +using System.Globalization; +using Model; + +namespace LolApp.Resources.Converters +{ + public class ChampionClassToIconConverter : IValueConverter + { + private static Dictionary icons = new() + { + [ChampionClass.Assassin] = "assassin.png", + [ChampionClass.Fighter] = "fighter.png", + [ChampionClass.Mage] = "mage.png", + [ChampionClass.Marksman] = "marksman.png", + [ChampionClass.Support] = "support.png", + [ChampionClass.Tank] = "tank.png" + }; + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + try + { + ChampionClass champClass = (ChampionClass)value; + if(!icons.TryGetValue(champClass, out string icon)) + { + return ""; + } + return ImageSource.FromFile($"{icon}"); + } + catch + { + return ""; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} + diff --git a/Sources/LolApp/Resources/Converters/ImageRatioConverter.cs b/Sources/LolApp/Resources/Converters/ImageRatioConverter.cs new file mode 100644 index 0000000..a3e0b7e --- /dev/null +++ b/Sources/LolApp/Resources/Converters/ImageRatioConverter.cs @@ -0,0 +1,28 @@ +using System; +using System.Globalization; + +namespace LolApp.Resources.Converters +{ + public class ImageRatioConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + try + { + double parentWidth = (double)value; + double ratio = (double)parameter; + return parentWidth*ratio; + } + catch + { + return 0.0; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} + diff --git a/Sources/LolApp/Resources/Converters/PlusOneConverter.cs b/Sources/LolApp/Resources/Converters/PlusOneConverter.cs new file mode 100644 index 0000000..2d9eaec --- /dev/null +++ b/Sources/LolApp/Resources/Converters/PlusOneConverter.cs @@ -0,0 +1,28 @@ +using System; +using System.Globalization; + +namespace LolApp.Resources.Converters +{ + public class PlusOneConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + int i = -1; + try + { + i = (int)value; + } + catch (InvalidCastException e) + { + throw new InvalidCastException("PlusOneConverter : the value must be an int"); + } + return i + 1; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} + diff --git a/Sources/LolApp/Resources/Fonts/Font Awesome 6 Free-Solid-900.otf b/Sources/LolApp/Resources/Fonts/Font Awesome 6 Free-Solid-900.otf new file mode 100644 index 0000000..f1d88fc Binary files /dev/null and b/Sources/LolApp/Resources/Fonts/Font Awesome 6 Free-Solid-900.otf differ diff --git a/Sources/LolApp/Resources/Fonts/OpenSans-Regular.ttf b/Sources/LolApp/Resources/Fonts/OpenSans-Regular.ttf new file mode 100644 index 0000000..a49f11d Binary files /dev/null and b/Sources/LolApp/Resources/Fonts/OpenSans-Regular.ttf differ diff --git a/Sources/LolApp/Resources/Fonts/OpenSans-Semibold.ttf b/Sources/LolApp/Resources/Fonts/OpenSans-Semibold.ttf new file mode 100644 index 0000000..23911e4 Binary files /dev/null and b/Sources/LolApp/Resources/Fonts/OpenSans-Semibold.ttf differ diff --git a/Sources/LolApp/Resources/Images/assassin.svg b/Sources/LolApp/Resources/Images/assassin.svg new file mode 100644 index 0000000..fb86680 --- /dev/null +++ b/Sources/LolApp/Resources/Images/assassin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Images/fighter.svg b/Sources/LolApp/Resources/Images/fighter.svg new file mode 100644 index 0000000..42cb7df --- /dev/null +++ b/Sources/LolApp/Resources/Images/fighter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Images/lol.png b/Sources/LolApp/Resources/Images/lol.png new file mode 100644 index 0000000..10a552c Binary files /dev/null and b/Sources/LolApp/Resources/Images/lol.png differ diff --git a/Sources/LolApp/Resources/Images/lollogo.jpg b/Sources/LolApp/Resources/Images/lollogo.jpg new file mode 100644 index 0000000..a1b82b5 Binary files /dev/null and b/Sources/LolApp/Resources/Images/lollogo.jpg differ diff --git a/Sources/LolApp/Resources/Images/mage.svg b/Sources/LolApp/Resources/Images/mage.svg new file mode 100644 index 0000000..45d627b --- /dev/null +++ b/Sources/LolApp/Resources/Images/mage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Images/marksman.svg b/Sources/LolApp/Resources/Images/marksman.svg new file mode 100644 index 0000000..f91066f --- /dev/null +++ b/Sources/LolApp/Resources/Images/marksman.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Images/rp.png b/Sources/LolApp/Resources/Images/rp.png new file mode 100644 index 0000000..e025310 Binary files /dev/null and b/Sources/LolApp/Resources/Images/rp.png differ diff --git a/Sources/LolApp/Resources/Images/support.svg b/Sources/LolApp/Resources/Images/support.svg new file mode 100644 index 0000000..2d1f053 --- /dev/null +++ b/Sources/LolApp/Resources/Images/support.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Images/sword.png b/Sources/LolApp/Resources/Images/sword.png new file mode 100644 index 0000000..fb87c07 Binary files /dev/null and b/Sources/LolApp/Resources/Images/sword.png differ diff --git a/Sources/LolApp/Resources/Images/tank.svg b/Sources/LolApp/Resources/Images/tank.svg new file mode 100644 index 0000000..2ec01a3 --- /dev/null +++ b/Sources/LolApp/Resources/Images/tank.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Raw/AboutAssets.txt b/Sources/LolApp/Resources/Raw/AboutAssets.txt new file mode 100644 index 0000000..808d6d3 --- /dev/null +++ b/Sources/LolApp/Resources/Raw/AboutAssets.txt @@ -0,0 +1,17 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories). Deployment of the asset to your application +is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. + + + +These files will be deployed with you package and will be accessible using Essentials: + + async Task LoadMauiAsset() + { + using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); + using var reader = new StreamReader(stream); + + var contents = reader.ReadToEnd(); + } + + diff --git a/Sources/LolApp/Resources/Splash/splash.png b/Sources/LolApp/Resources/Splash/splash.png new file mode 100644 index 0000000..e89e1c2 Binary files /dev/null and b/Sources/LolApp/Resources/Splash/splash.png differ diff --git a/Sources/LolApp/Resources/Styles/Colors.xaml b/Sources/LolApp/Resources/Styles/Colors.xaml new file mode 100644 index 0000000..286775e --- /dev/null +++ b/Sources/LolApp/Resources/Styles/Colors.xaml @@ -0,0 +1,46 @@ + + + + + #D2B977 + #F0E7B7 + #2B0B98 + White + Black + #E1E1E1 + #C8C8C8 + #ACACAC + #919191 + #6E6E6E + #404040 + #212121 + #141414 + + + + + + + + + + + + + + + #F7B548 + #FFD590 + #FFE5B9 + #28C2D1 + #7BDDEF + #C3F2F4 + #3E8EED + #72ACF1 + #A7CBF6 + + Transparent + + diff --git a/Sources/LolApp/Resources/Styles/FontAwesomeGlyphs.xaml b/Sources/LolApp/Resources/Styles/FontAwesomeGlyphs.xaml new file mode 100644 index 0000000..a53b993 --- /dev/null +++ b/Sources/LolApp/Resources/Styles/FontAwesomeGlyphs.xaml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Sources/LolApp/Resources/Styles/MyStyles.xaml b/Sources/LolApp/Resources/Styles/MyStyles.xaml new file mode 100644 index 0000000..b988753 --- /dev/null +++ b/Sources/LolApp/Resources/Styles/MyStyles.xaml @@ -0,0 +1,102 @@ + + + + + 0.59 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/Resources/Styles/Styles.xaml b/Sources/LolApp/Resources/Styles/Styles.xaml new file mode 100644 index 0000000..d23a11d --- /dev/null +++ b/Sources/LolApp/Resources/Styles/Styles.xaml @@ -0,0 +1,406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/SkinPage.xaml b/Sources/LolApp/SkinPage.xaml new file mode 100644 index 0000000..0b082ab --- /dev/null +++ b/Sources/LolApp/SkinPage.xaml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/SkinPage.xaml.cs b/Sources/LolApp/SkinPage.xaml.cs new file mode 100644 index 0000000..f4ac283 --- /dev/null +++ b/Sources/LolApp/SkinPage.xaml.cs @@ -0,0 +1,18 @@ +using LolApp.ViewModels; +using ViewModels; + +namespace LolApp; + +public partial class SkinPage : ContentPage +{ + public ApplicationVM AppVM { get; set; } + public SkinVM SkinVM { get; } + + public SkinPage(SkinVM svm, ApplicationVM appVM) + { + BindingContext = SkinVM = svm; + AppVM = appVM; + + InitializeComponent(); + } +} diff --git a/Sources/LolApp/ViewModels/AddChampionPageVM.cs b/Sources/LolApp/ViewModels/AddChampionPageVM.cs new file mode 100644 index 0000000..31fb1e3 --- /dev/null +++ b/Sources/LolApp/ViewModels/AddChampionPageVM.cs @@ -0,0 +1,80 @@ +using System; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +//using Microsoft.Maui.Graphics.Platform; +using ViewModels; + +namespace LolApp.ViewModels +{ + [ObservableObject] + public partial class AddChampionPageVM + { + ChampionsMgrVM ChampionsMgrVM { get; } + + public AddChampionPageVM(ChampionsMgrVM championsMgrVM, ChampionVM champion = null) + { + ChampionsMgrVM = championsMgrVM; + if(champion == null) return; + + oldChampion = champion; + IsNew = false; + this.champion = new EditableChampionVM(oldChampion); + } + + private ChampionVM oldChampion; + + [ObservableProperty] + bool isNew = true; + + [ObservableProperty] + EditableChampionVM champion = new (); + + [RelayCommand] + public async void PickIcon() => Champion.IconBase64 = await PickIconsAndImagesUtils.PickPhoto(42); + + [RelayCommand] + public async void PickLargeImage() => Champion.LargeImageBase64 = await PickIconsAndImagesUtils.PickPhoto(1000); + + [RelayCommand] + async Task Cancel() + => await App.Current.MainPage.Navigation.PopAsync(); + + [RelayCommand] + async Task AddChampion() + { + ChampionVM champVM = Champion.ToChampionVM(); + await ChampionsMgrVM.AddChampion(champVM); + await App.Current.MainPage.Navigation.PopAsync(); + } + + [RelayCommand] + async Task EditChampion() + { + ChampionVM newChampion = Champion.ToChampionVM(); + await ChampionsMgrVM.EditChampion(oldChampion, newChampion); + await App.Current.MainPage.Navigation.PopAsync(); + } + + [ObservableProperty] + string newCharacteristicDescription; + + [ObservableProperty] + int newCharacteristicValue; + + [RelayCommand] + void AddCharacteristic() + { + Champion?.AddCharacteristic(newCharacteristicDescription, newCharacteristicValue); + } + + [RelayCommand] + void RemoveCharacteristic(KeyValuePair characteristic) + => Champion?.RemoveCharacteristic(characteristic); + + [RelayCommand] + async Task AddSkill() + => await App.Current.MainPage.Navigation.PushModalAsync(new AddSkill(Champion)); + + } +} + diff --git a/Sources/LolApp/ViewModels/AddOrEditSkinPageVM.cs b/Sources/LolApp/ViewModels/AddOrEditSkinPageVM.cs new file mode 100644 index 0000000..09a134c --- /dev/null +++ b/Sources/LolApp/ViewModels/AddOrEditSkinPageVM.cs @@ -0,0 +1,64 @@ +using System; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Model; +using ViewModels; + +namespace LolApp.ViewModels +{ + [ObservableObject] + public partial class AddOrEditSkinPageVM + { + SkinsMgrVM SkinsMgrVM { get; } + + private SkinVM oldSkin; + + [ObservableProperty] + bool isNew = true; + + [ObservableProperty] + EditableSkinVM skin; + + public AddOrEditSkinPageVM(SkinsMgrVM skinsMgrVM, SkinVM oldSkin) + { + SkinsMgrVM = skinsMgrVM; + + this.oldSkin = oldSkin; + IsNew = false; + this.skin = new EditableSkinVM(oldSkin); + } + + public AddOrEditSkinPageVM(SkinsMgrVM skinsMgrVM, ChampionVM champion) + { + SkinsMgrVM = skinsMgrVM; + skin = new EditableSkinVM(champion); + } + + [RelayCommand] + public async void PickIcon() => Skin.IconBase64 = await PickIconsAndImagesUtils.PickPhoto(42); + + [RelayCommand] + public async void PickLargeImage() => Skin.LargeImageBase64 = await PickIconsAndImagesUtils.PickPhoto(1000); + + [RelayCommand] + async Task Cancel() + => await App.Current.MainPage.Navigation.PopAsync(); + + [RelayCommand] + async Task AddSkin() + { + SkinVM skinVM = Skin.ToSkinVM(); + await SkinsMgrVM.AddSkin(skinVM); + await App.Current.MainPage.Navigation.PopAsync(); + } + + [RelayCommand] + async Task EditSkin() + { + SkinVM newSkin = Skin.ToSkinVM(); + await SkinsMgrVM.EditSkin(oldSkin, newSkin); + await App.Current.MainPage.Navigation.PopAsync(); + } + } +} + diff --git a/Sources/LolApp/ViewModels/AddSkillVM.cs b/Sources/LolApp/ViewModels/AddSkillVM.cs new file mode 100644 index 0000000..ef40e97 --- /dev/null +++ b/Sources/LolApp/ViewModels/AddSkillVM.cs @@ -0,0 +1,46 @@ +using System; +using System.Linq; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Model; +using ViewModels; + +namespace LolApp.ViewModels +{ + public partial class AddSkillVM : ObservableObject + { + public AddSkillVM(EditableChampionVM champion) + { + Champion = champion; + } + + [ObservableProperty] + SkillType skillType; + + [ObservableProperty] + string name; + + [ObservableProperty] + string description; + + [ObservableProperty] + EditableChampionVM champion; + + [RelayCommand] + async void AddSkillToChampion() + { + champion.Skills.Add(new SkillVM(new Skill(name, skillType, description))); + await App.Current.MainPage.Navigation.PopModalAsync(); + } + + [RelayCommand] + async void Cancel() + { + await App.Current.MainPage.Navigation.PopModalAsync(); + } + + public IEnumerable AllSkills { get; } + = Enum.GetValues(typeof(SkillType)).Cast().Except(new SkillType[] {SkillType.Unknown}).ToList(); + } +} + diff --git a/Sources/LolApp/ViewModels/ApplicationVM.cs b/Sources/LolApp/ViewModels/ApplicationVM.cs new file mode 100644 index 0000000..9f029f0 --- /dev/null +++ b/Sources/LolApp/ViewModels/ApplicationVM.cs @@ -0,0 +1,58 @@ +using System; +using CommunityToolkit.Mvvm.Input; +using Model; +using ViewModels; + +namespace LolApp.ViewModels +{ + public partial class ApplicationVM + { + public ChampionsMgrVM ChampionsMgrVM { get; set; } + + public SkinsMgrVM SkinsMgrVM { get; set; } + + public ApplicationVM(ChampionsMgrVM championsMgrVM, SkinsMgrVM skinsMgrVM) + { + ChampionsMgrVM = championsMgrVM; + SkinsMgrVM = skinsMgrVM; + } + + [RelayCommand] + async Task NavigateToChampionDetailsPage(ChampionVM cvm) + { + SkinsMgrVM.Champion = cvm; + SkinsMgrVM.Index = 0; + SkinsMgrVM.Count = 5; + await SkinsMgrVM.LoadSkinsCommand.ExecuteAsync(cvm); + await App.Current.MainPage.Navigation.PushAsync(new ChampionPage(cvm, this)); + } + + [RelayCommand] + async Task NavigateToAddNewChampionPage() + => await App.Current.MainPage.Navigation.PushAsync(new AddChampionPage(ChampionsMgrVM)); + + [RelayCommand(CanExecute = nameof(CanNavigateToEditChampionPage))] + async Task NavigateToEditChampionPage(object champ) + => await App.Current.MainPage.Navigation.PushAsync(new AddChampionPage(ChampionsMgrVM, champ as ChampionVM)); + + bool CanNavigateToEditChampionPage(object champ) => champ != null && champ is ChampionVM; + + [RelayCommand] + async Task NavigateToSkinDetailsPage(object svm) + { + if (svm == null || svm is not SkinVM) return; + await App.Current.MainPage.Navigation.PushAsync(new SkinPage(svm as SkinVM, this)); + } + + [RelayCommand] + async Task NavigateToAddNewSkinPage(ChampionVM champion) + => await App.Current.MainPage.Navigation.PushAsync(new AddOrEditSkinPage(SkinsMgrVM, champion)); + + [RelayCommand(CanExecute = nameof(CanNavigateToEditSkinPage))] + async Task NavigateToEditSkinPage(object skin) + => await App.Current.MainPage.Navigation.PushAsync(new AddOrEditSkinPage(SkinsMgrVM, skin as SkinVM)); + + bool CanNavigateToEditSkinPage(object skin) => skin != null && skin is SkinVM; + } +} + diff --git a/Sources/LolApp/ViewModels/ChampionClassVM.cs b/Sources/LolApp/ViewModels/ChampionClassVM.cs new file mode 100644 index 0000000..992f45f --- /dev/null +++ b/Sources/LolApp/ViewModels/ChampionClassVM.cs @@ -0,0 +1,27 @@ +using System; +using System.Linq; +using CommunityToolkit.Mvvm.ComponentModel; +using Model; + +namespace LolApp.ViewModels +{ + [ObservableObject] + public partial class ChampionClassVM + { + [ObservableProperty] + private ChampionClass model; + + [ObservableProperty] + private bool isSelected; + + public ChampionClassVM(ChampionClass model) + { + Model = model; + } + + public static IEnumerable Classes { get; } + = Enum.GetValues(typeof(ChampionClass)).Cast().Except(new ChampionClass[] {ChampionClass.Unknown}) + .Select(cc => new ChampionClassVM(cc)); + } +} + diff --git a/Sources/LolApp/ViewModels/ChampionsPageVM.cs b/Sources/LolApp/ViewModels/ChampionsPageVM.cs new file mode 100644 index 0000000..906875a --- /dev/null +++ b/Sources/LolApp/ViewModels/ChampionsPageVM.cs @@ -0,0 +1,111 @@ +using System; +using System.Reflection; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Model; +using ViewModels; + +namespace LolApp.ViewModels +{ + [ObservableObject] + public partial class ChampionsPageVM + { + public ChampionsMgrVM ChampionsMgrVM { get; set; } + + public ChampionsPageVM(ChampionsMgrVM championsMgrVM) + { + ChampionsMgrVM = championsMgrVM; + PropertyChanged += ChampionsMgrVM_PropertyChanged; + + } + + [ObservableProperty] + private ChampionClassVM selectedClass; + + + [RelayCommand] + public async Task SelectedChampionClassChanged(ChampionClassVM champClass) + { + if(SelectedClass != null) SelectedClass.IsSelected = false; + if(champClass.Model == ChampionClass.Unknown + || champClass.Model == SelectedClass?.Model) + { + SelectedClass = null; + return; + } + SelectedClass = champClass; + SelectedClass.IsSelected = true; + await ChampionsMgrVM.LoadChampionsByClass(SelectedClass.Model);//ChampionsMgrVM.SelectedClass); + + } + + + [ObservableProperty] + private ChampionVM selectedChampion; + + [ObservableProperty] + private string searchedName; + + + + [ObservableProperty] + private string searchedSkill; + + [ObservableProperty] + private string searchedCharacteristic; + + private static string[] searchedStrings = { nameof(SearchedName), nameof(SearchedSkill), nameof(SearchedCharacteristic), nameof(SelectedClass) }; + + private async void ChampionsMgrVM_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if(searchedStrings.Any(s => e.PropertyName == s)) + { + if(GetProperty(e.PropertyName).GetValue(this) != GetProperty(e.PropertyName).GetDefaultValue()) + { + foreach(string s in searchedStrings.Except(new string[]{e.PropertyName })) + { + var prop = GetProperty(s); + prop.ResetPropertyValue(this); + } + return; + } + ChampionsMgrVM.Index=0; + if(searchedStrings.All(s => GetProperty(s).GetValue(this) == GetProperty(s).GetDefaultValue())) + { + await ChampionsMgrVM.LoadChampions(); + } + } + } + + private PropertyInfo? GetProperty(string propName) + => typeof(ChampionsPageVM).GetProperty(propName); + + } + + public static class Extensions + { + public static void ResetPropertyValue(this PropertyInfo pi, ChampionsPageVM instance) + { + if(pi.PropertyType == typeof(ChampionClassVM)) + { + var temp = pi.GetValue(instance); + if(temp != null) + (temp as ChampionClassVM).IsSelected = false; + return; + } + pi.SetValue(instance, pi.GetDefaultValue()); + } + + public static object GetDefaultValue(this Type t) + { + if (t.IsValueType) + return Activator.CreateInstance(t); + + return null; + } + + public static object GetDefaultValue(this PropertyInfo pi) + => pi.PropertyType.GetDefaultValue(); + } +} + diff --git a/Sources/LolApp/ViewModels/PickIconsAndImagesUtils.cs b/Sources/LolApp/ViewModels/PickIconsAndImagesUtils.cs new file mode 100644 index 0000000..6cef1d1 --- /dev/null +++ b/Sources/LolApp/ViewModels/PickIconsAndImagesUtils.cs @@ -0,0 +1,32 @@ +using System; +//using Microsoft.Maui.Graphics.Platform; +using Microsoft.Maui.Graphics.Skia; + +namespace LolApp.ViewModels +{ + public static class PickIconsAndImagesUtils + { + public async static Task PickPhoto(float maxWidthAndHeight) + { + FileResult photo = await MediaPicker.Default.PickPhotoAsync(); + return photo != null ? await ToBase64(photo, maxWidthAndHeight) : null; + } + + public async static Task ToBase64(FileResult photo, float maxWidthAndHeight) + { + using (var stream = await photo.OpenReadAsync()) + using (var memoryStream = new MemoryStream()) + { + var image = SkiaImage.FromStream(memoryStream); + //var image = PlatformImage.FromStream(stream); + if(image != null) + { + var newImage = image.Downsize(maxWidthAndHeight, true); + return newImage.AsBase64(); + } + } + return null; + } + } +} + diff --git a/Sources/Model/Champion.cs b/Sources/Model/Champion.cs index fd4a5ca..0e33455 100644 --- a/Sources/Model/Champion.cs +++ b/Sources/Model/Champion.cs @@ -53,7 +53,13 @@ public class Champion : IEquatable Skins = new ReadOnlyCollection(skins); } - public ReadOnlyCollection Skins { get; private set; } + public Champion(string name, string bio) + { + this.name = name; + this.bio = bio; + } + + public ReadOnlyCollection Skins { get; private set; } private List skins = new (); public ReadOnlyDictionary Characteristics { get; private set; } diff --git a/Sources/TestUnitaire/TestAPILol.cs b/Sources/TestUnitaire/TestAPILol.cs index e819972..62d4a3a 100644 --- a/Sources/TestUnitaire/TestAPILol.cs +++ b/Sources/TestUnitaire/TestAPILol.cs @@ -1,5 +1,5 @@ -using apiLOL; using apiLOL.Controllers; +using apiLOL.DTO; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -10,50 +10,103 @@ namespace TestUnitaire public class TestAPILol { [Theory] - [InlineData("Beatrice", "sdfsdfd")] - [InlineData("Maurice", "Ahri est un champion de League of Legends")] - [InlineData("Loupiotte", "Akali est un champion de League of Legends")] - public async Task TestPostChampion(string name, string bio) + [InlineData("Beatrice", "sdfsdfd", "icon.png")] + [InlineData("Maurice", "Ahri est un champion de League of Legends", "icon.png")] + [InlineData("Loupiotte", "Akali est un champion de League of Legends", "icon.png")] + public async Task TestPostChampion(string name, string bio, string icon) { // Arrange var data = new StubData(); var logger = new NullLogger(); var controller = new ControllerChampions(data, logger); - var champDTO = new ChampionDTO(name, bio); + var champDTO = new ChampionDTO(name, bio, icon); // Act var nbInListBefore = data.ChampionsMgr.GetNbItems().Result; - var result = await controller.Post(champDTO); + var result = await controller.AddChampion(champDTO); var nbInListAfter = data.ChampionsMgr.GetNbItems().Result; // Assert // IS the champion added to the list, number of champions in the list + 1 Assert.Equal(nbInListBefore + 1, nbInListAfter); + // Test le code de retour } [Theory] - [InlineData("Beatrice", "Aatrox est un champion de League of Legends")] - [InlineData("Maurice", "Ahri est un champion de League of Legends")] - [InlineData("Loupiotte", "Akali est un champion de League of Legends")] - public async Task TestGetChampion(string name, string bio) + [InlineData("Beatrice", "Aatrox est un champion de League of Legends", "icon.png")] + [InlineData("Maurice", "Ahri est un champion de League of Legends", "icon.png")] + [InlineData("Loupiotte", "Akali est un champion de League of Legends", "icon.png")] + public async Task TestGetChampion(string name, string bio, string icon) { // Arrange var data = new StubData(); var logger = new NullLogger(); var controller = new ControllerChampions(data, logger); - var champDTO = new ChampionDTO(name, bio); + var champDTO = new ChampionDTO(name, bio, icon); // Act // Call method POST to add a champion - var result = await controller.Post(champDTO); + var result = await controller.AddChampion(champDTO); // Call method GET to get the champion - var resultGet = await controller.GetChampion(name); + var resultGet = await controller.GetChampionByName(name); // Assert - // IS the champion added to the list, number of champions in the list + 1 Assert.Equal(name, champDTO.Name); Assert.Equal(bio, champDTO.Bio); } + + [Theory] + [InlineData("Beatrice", "Nouvelle bio")] + [InlineData("Maurice", "Nouvelle bio")] + [InlineData("Loupiotte", "Nouvelle bio")] + public async Task TestPutChampion(string name, string bio) + { + // Method that change the bio of a champion. Make a test to check if the bio is changed + // Arrange + var data = new StubData(); + var logger = new NullLogger(); + var controller = new ControllerChampions(data, logger); + + // Act + // Add a champion + var champDTO = new ChampionDTO(name, "Ancienne bio", "icon.png"); + var resultPost = await controller.AddChampion(champDTO); + + // Call method PUT to change the bio of a champion + var resultPut = await controller.UpdateChampion(name, bio); + var champion = (await data.ChampionsMgr.GetItemsByName(name, 0, 1)).First(); + var bioOfChampion = champion.Bio; + + // Assert + // Does the bio of the champion is changed + Assert.Equal(bio, bioOfChampion); + } + + + [Theory] + [InlineData("Beatrice")] + [InlineData("Maurice")] + [InlineData("Loupiotte")] + public async Task TestDeleteChampion(string name) + { + // Method that delete a champion. Make a test to check if the champion is deleted + // Arrange + var data = new StubData(); + var logger = new NullLogger(); + var controller = new ControllerChampions(data, logger); + + // Act + // Add a champion + var champDTO = new ChampionDTO(name, "Ancienne bio", "icon.png"); + var resultPost = await controller.AddChampion(champDTO); + + // Call method DELETE to delete the champion + var resultDelete = await controller.DeleteChampion(name); + + // Assert + // Does the type of the result is a OkObjectResult + Assert.IsType(resultDelete); + } } } \ No newline at end of file diff --git a/Sources/TestUnitaire/TestEfLol.cs b/Sources/TestUnitaire/TestEfLol.cs index d9bae90..02244e0 100644 --- a/Sources/TestUnitaire/TestEfLol.cs +++ b/Sources/TestUnitaire/TestEfLol.cs @@ -1,6 +1,7 @@ using EFLol; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; +using System.Collections.ObjectModel; namespace TestUnitaire { @@ -9,14 +10,14 @@ namespace TestUnitaire [Theory] - [InlineData("Zeus", "Dieu de la foudre", true)] - [InlineData("Hades", "Dieu des enfers", true)] - [InlineData("Aphrodite", "Déesse de l'amour", true)] - [InlineData("AresAresAresAresAresAresAresAresAresAres", + [InlineData(0,"Zeus", "Dieu de la foudre", true)] + [InlineData(10,"Hades", "Dieu des enfers", true)] + [InlineData(1,"Aphrodite", "Déesse de l'amour", true)] + [InlineData(10,"AresAresAresAresAresAresAresAresAresAres", "Dieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerre" + "Dieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerre" + "Dieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerreDieu de la guerre", false)] - public async Task TestAddInMemory(String name, String bio, bool expected) + public async Task TestAddChampionInMemory(int id, String name, String bio, bool expected) { var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); @@ -28,11 +29,20 @@ namespace TestUnitaire using (var context = new MyDbContext(options)) { await context.Database.EnsureCreatedAsync(); - var Dieu = new ChampionEntity + SkinEntity black = new SkinEntity { Name = "Black", Description = "Black skin", Icon = "black.png", Price = 0.99f }; + SkinEntity white = new SkinEntity { Name = "White", Description = "White skin", Icon = "white.png", Price = 150.99f }; + SkinEntity green = new SkinEntity { Name = "Green", Description = "Green skin", Icon = "green.png", Price = 4.99f }; + + RunePageEntity runePage1 = new RunePageEntity { Id = 1, Name = "runepage1"}; + + var Dieu = new ChampionEntity { + Id = id, Name = name, - Bio = bio - }; + Bio = bio, + Skins = new Collection(new List { black, white, green }), + ListRunePages = new Collection(new List { { runePage1 } }) + }; ChampionEntity found = await context.Champions.SingleOrDefaultAsync(c => c.Name == "Zeus"); Assert.Null(found); @@ -45,24 +55,26 @@ namespace TestUnitaire Assert.Equal(1, await context.Champions.CountAsync()); Assert.Equal(name, found.Name); + Assert.Equal(3,found.Skins.Count); + Assert.Equal(1, found.ListRunePages.Count); - // Test if the max length of the name is respected (30) and the max length of the bio is respected (256) - if (expected) + // Test if the max length of the name is respected (30) and the max length of the bio is respected (256) + if (expected) { Assert.True(found.Name.Length <= 30); Assert.True(found.Bio.Length <= 256); } else { - Assert.False(found.Bio.Length <= 256); Assert.False(found.Name.Length <= 30); + Assert.False(found.Bio.Length <= 256); } } } [Fact] - public void ModifyTestInMemory() + public void TestModifyChampionInMemory() { var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); @@ -79,7 +91,7 @@ namespace TestUnitaire ChampionEntity chewie = new ChampionEntity { Name = "Chewbacca", Bio = "Zeus is the king of the gods." }; ChampionEntity yoda = new ChampionEntity { Name = "Yoda", Bio = "Zeus is the king of the gods." }; - ChampionEntity ewok = new ChampionEntity { Name = "Ewok", Bio = "Zeus is the king of the gods." }; + ChampionEntity ewok = new ChampionEntity {Name = "Ewok", Bio = "Zeus is the king of the gods." }; context.Champions.Add(chewie); @@ -113,5 +125,54 @@ namespace TestUnitaire Assert.Equal(1, context.Champions.Where(n => n.Name.ToLower().Contains(nameToFind)).Count()); } } - } + + [Theory] + + [InlineData(0,"black", "super Skin", "icon1.png",190000000.2f,true)] + [InlineData(1,"White", "skin1", "icon1", 19, true)] + [InlineData(2,"Green", "skin", "icon1.jpg", -1, false)] + public async Task TestAddSkinToChampionInMemory(int id,String name, String description, String icon,float price,bool expected) + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new MyDbContext(options)) + { + await context.Database.EnsureCreatedAsync(); + + var Dieu = new ChampionEntity + { + Id = 0, + Name = "Zeus", + Bio = "Dieu de la foudre", + Skins = new Collection() + }; + + SkinEntity item = new SkinEntity + { + Id = id, + Name = name, + Description = description, + Icon = icon, + Price = price + }; + + Dieu.Skins.Add(item); + + ChampionEntity found = await context.Champions.SingleOrDefaultAsync(c => c.Name == "Zeus"); + Assert.Null(found); + + await context.Champions.AddAsync(Dieu); + await context.SaveChangesAsync(); + + found = await context.Champions.SingleOrDefaultAsync(c => c.Name == name); + } + + } + + } } \ No newline at end of file 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..eea4ab7 --- /dev/null +++ b/Sources/ViewModels/ViewModels.csproj @@ -0,0 +1,16 @@ + + + + net6.0 + enable + enable + true + + + + + + + + + diff --git a/Sources/apiLOL/ChampionDTO.cs b/Sources/apiLOL/ChampionDTO.cs deleted file mode 100644 index f015a14..0000000 --- a/Sources/apiLOL/ChampionDTO.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace apiLOL -{ - public class ChampionDTO - { - - public ChampionDTO(string name, string bio) - { - Name = name; - Bio = bio; - } - - public string Name { get; set; } - - public string Bio { get; set; } - } -} diff --git a/Sources/apiLOL/ChampionPageDTO.cs b/Sources/apiLOL/ChampionPageDTO.cs deleted file mode 100644 index 5fff791..0000000 --- a/Sources/apiLOL/ChampionPageDTO.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace apiLOL -{ - public class ChampionPageDTO - { - public IEnumerable Data { get; set; } - - public int Index { get; set; } - - public int Count { get; set; } - - public int TotalCount { get; set; } - } -} diff --git a/Sources/apiLOL/Controllers/ControllerChampions.cs b/Sources/apiLOL/Controllers/ControllerChampions.cs index 5e129e5..38435e3 100644 --- a/Sources/apiLOL/Controllers/ControllerChampions.cs +++ b/Sources/apiLOL/Controllers/ControllerChampions.cs @@ -1,4 +1,5 @@ using System.Security.Cryptography; +using apiLOL.DTO; using Microsoft.AspNetCore.Mvc; using Model; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 @@ -11,110 +12,165 @@ namespace apiLOL.Controllers public class ControllerChampions : Controller { - private readonly IDataManager data; + //private readonly IDataManager data; + private IChampionsManager _dataManager; private readonly ILogger _logger; public ControllerChampions(IDataManager manager, ILogger log) { - data = manager; + _dataManager = manager.ChampionsMgr; _logger = log; } - // GET: api/ [HttpGet] - public async Task Get([FromQuery]int index = 0, int count = 10) + [ProducesResponseType(typeof(ChampionPageDTO), 200)] + public async Task GetChampions([FromQuery] int index = 0, int count = 10, string? name = "") { - //FromQuery permet de filtrer dans la collection de champions en fonction du nom - // Possible de faire une classe PageRequest pour gérer les paramètres index et count _logger.LogInformation($"methode Get de ControllerChampions appelée"); - int nbChampions = await data.ChampionsMgr.GetNbItems(); + int nbChampions = await _dataManager.GetNbItems(); _logger.LogInformation($"Nombre de champions : {nbChampions}"); - var champs = (await data.ChampionsMgr.GetItems(index, count)).Select(Model => Model.ToDTO()); + var champs = (await _dataManager.GetItemsByName(name, index, int.MaxValue)) + .Where(champ => string.IsNullOrEmpty(name) || champ.Name.Contains(name, StringComparison.InvariantCultureIgnoreCase)) + .Take(count) + .Select(Model => Model.ToDTO()); var page = new ChampionPageDTO { Data = champs, Index = index, - Count = count, + Count = champs.Count(), TotalCount = nbChampions }; return Ok(page); } - - // GET api//Charle [HttpGet] [Route("{name}")] - public async Task GetChampion(string name) + [ProducesResponseType(typeof(ChampionDTO), 200)] + public async Task GetChampionByName(string name) { _logger.LogInformation($"methode GetChampion de ControllerChampions appelée avec le paramètre {name}"); try { - var champs = (await data.ChampionsMgr.GetItemsByName(name, 0, 1)); - return Ok(champs.First().ToDTO()); + var champs = await _dataManager.GetItemsByName(name, 0, 1); + if (champs.Any()) + { + return Ok(champs.First().ToDTO()); + } + else + { + return NotFound(); + } } - catch - { + catch (Exception ex) + { + _logger.LogError($"erreur methode Get de ControllerChampions: {ex}"); return BadRequest("erreur de nom de champion"); } } - // POST api/ [HttpPost] - public async Task Post(ChampionDTO champDTO) + public async Task AddChampion(ChampionDTO champDTO) { _logger.LogInformation($"methode Post de ControllerChampions appelée avec le paramètre {champDTO.Name}"); - - try { + // Check if the champion already exists in the database + var champs = await _dataManager.GetItemsByName(champDTO.Name, 0, 1); + if (champs.Any()) + { + return BadRequest("le champion existe deja"); + } + Champion tmp = champDTO.ToModel(); - Champion champion = await data.ChampionsMgr.AddItem(tmp); + Champion champion = await _dataManager.AddItem(tmp); ChampionDTO dtoChamp = champion.ToDTO(); - return CreatedAtAction(nameof(GetChampion), new { name = dtoChamp.Name }, dtoChamp); + return CreatedAtAction(nameof(GetChampionByName), new { name = dtoChamp.Name }, dtoChamp); } - catch + catch (Exception ex) { - return BadRequest("le champion existe deja"); + _logger.LogError($"erreur methode Post de ControllerChampions: {ex}"); + return BadRequest("erreur lors de l'ajout du champion"); } } - // PUT api//5 + [HttpPut("{name}")] - public async Task Put(string name, string bio) + public async Task UpdateChampion(string name, string bio) { - _logger.LogInformation($"methode Put de ControllerChampions appelée avec le paramètre name: {name} et bio: {bio}"); + _logger.LogInformation( + $"methode Put de ControllerChampions appelée avec le paramètre name: {name} et bio: {bio}"); try { - var champs = (await data.ChampionsMgr.GetItemsByName(name, 0, 1)).First(); + var champs = (await _dataManager.GetItemsByName(name, 0, 1)).First(); champs.Bio = bio; return Ok(champs.ToDTO()); } - catch + catch (Exception ex) { + _logger.LogError($"erreur methode Put de ControllerChampions: {ex}"); return BadRequest("erreur de nom de champion"); } } - // DELETE api//5 [HttpDelete("{name}")] - public async Task Delete(String name) + public async Task DeleteChampion(string name) { + _logger.LogInformation($"methode Delete de ControllerChampions appelée avec le paramètre name: {name}"); + try { - var champ = (await data.ChampionsMgr.GetItemsByName(name, 0, 1)).First(); - data.ChampionsMgr.DeleteItem(champ); + var champ = (await _dataManager.GetItemsByName(name, 0, 1)).First(); + _dataManager.DeleteItem(champ); return Ok(champ.ToDTO()); } - catch + catch (Exception ex) { + _logger.LogError($"erreur methode Delete de ControllerChampions: {ex}"); return BadRequest("erreur de nom de champion"); } } } + + [ApiController] + [Route("api/v2/[controller]")] + [ApiVersion("2.0")] + + public class ControllerChampionsSecondVersion : Controller + { + private readonly ILogger _logger; + + public ControllerChampionsSecondVersion(ILogger log) + { + _logger = log; + } + + + [HttpGet()] + public string Get(int id) + { + return "Version 2 of GET"; + } + + [HttpPost] + public void Post([FromBody] string value) + { + } + + [HttpPut("{id}")] + public void Put(int id, [FromBody] string value) + { + } + + [HttpDelete("{id}")] + public void Delete(int id) + { + } + + } } \ No newline at end of file diff --git a/Sources/apiLOL/Controllers/ControllerSkins.cs b/Sources/apiLOL/Controllers/ControllerSkins.cs new file mode 100644 index 0000000..fdbcaad --- /dev/null +++ b/Sources/apiLOL/Controllers/ControllerSkins.cs @@ -0,0 +1,64 @@ +using apiLOL.DTO; +using Microsoft.AspNetCore.Mvc; +using Model; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace apiLOL.Controllers +{ + [Route("api/[controller]")] + [ApiController] + [ApiVersion("1.0")] + public class ControllerSkins : ControllerBase + { + private readonly IDataManager data; + // EFdata manager qui implémente l'interface IDataManager + // coté client : Refaire un APIdata manager qui implémente l'interface IDataManager + private readonly ILogger _logger; + + public ControllerSkins(IDataManager manager, ILogger log) + { + data = manager; + _logger = log; + } + + + // GET api//5 + [HttpGet] + public async Task Get([FromQuery] int index = 0, int count = 10, string? name = "") + { + _logger.LogInformation($"methode Get de ControllerSkins appelée index:{index}, count: {count} et name:{name}"); + int nbSkins = await data.SkinsMgr.GetNbItems(); + _logger.LogInformation($"Nombre de skins : {nbSkins}"); + + var skin = (await data.SkinsMgr.GetItems(index, await data.SkinsMgr.GetNbItems())).Select(Model => Model.ToDTO());//.Where(Model => Model.Name.Contains(name)).Skip(index * count).Take(count).Select(Model => Model.ToDTO()); + + var page = new SkinPageDTO + { + Data = (IEnumerable)skin, + Index = index, + Count = count, + TotalCount = nbSkins + }; + return Ok(page); + } + + // POST api/ + [HttpPost] + public void Post([FromBody] string value) + { + } + + // PUT api//5 + [HttpPut("{id}")] + public void Put(int id, [FromBody] string value) + { + } + + // DELETE api//5 + [HttpDelete("{id}")] + public void Delete(int id) + { + } + } +} diff --git a/Sources/apiLOL/DTO/ChampionDTO.cs b/Sources/apiLOL/DTO/ChampionDTO.cs new file mode 100644 index 0000000..19f4c60 --- /dev/null +++ b/Sources/apiLOL/DTO/ChampionDTO.cs @@ -0,0 +1,21 @@ +namespace apiLOL.DTO +{ + public class ChampionDTO + { + + public ChampionDTO(string name, string bio, string icon) + { + Name = name; + Bio = bio; + Icon = icon; + } + + public string Name { get; set; } + public string Bio { get; set; } + public string Icon { get; set; } + + public bool Equals(ChampionDTO other) => other.Name == this.Name && other.Bio == this.Bio && other.Icon == this.Icon; + + public string toString() => $"ChampionDTO: {Name} {Bio} {Icon}"; + } +} diff --git a/Sources/apiLOL/ChampionMapper.cs b/Sources/apiLOL/DTO/ChampionMapper.cs similarity index 65% rename from Sources/apiLOL/ChampionMapper.cs rename to Sources/apiLOL/DTO/ChampionMapper.cs index a7009ab..5f767c1 100644 --- a/Sources/apiLOL/ChampionMapper.cs +++ b/Sources/apiLOL/DTO/ChampionMapper.cs @@ -1,18 +1,20 @@ -using Model; - -namespace apiLOL -{ - public static class ChampionMapper - { - public static ChampionDTO ToDTO(this Champion champion) => new ChampionDTO(champion.Name, champion.Bio); - - - public static Champion ToModel(this ChampionDTO championDTO) - { - Champion champ = new Champion(championDTO.Name); - champ.Bio = championDTO.Bio; - return champ; - } - - } -} +using Model; + +namespace apiLOL.DTO +{ + public static class ChampionMapper + { + public static ChampionDTO ToDTO(this Champion champion) + => new ChampionDTO(champion.Name, champion.Bio, champion.Icon); + + + public static Champion ToModel(this ChampionDTO championDTO) + { + Champion champ = new Champion(championDTO.Name); + champ.Bio = championDTO.Bio; + champ.Icon = championDTO.Icon; + return champ; + } + + } +} diff --git a/Sources/apiLOL/DTO/ChampionPageDTO.cs b/Sources/apiLOL/DTO/ChampionPageDTO.cs new file mode 100644 index 0000000..4d5f71d --- /dev/null +++ b/Sources/apiLOL/DTO/ChampionPageDTO.cs @@ -0,0 +1,13 @@ +namespace apiLOL.DTO +{ + public class ChampionPageDTO + { + public IEnumerable Data { get; set; } + + public int Index { get; set; } + + public int Count { get; set; } + + public int TotalCount { get; set; } + } +} diff --git a/Sources/apiLOL/DTO/SkinDTO.cs b/Sources/apiLOL/DTO/SkinDTO.cs new file mode 100644 index 0000000..01d16a6 --- /dev/null +++ b/Sources/apiLOL/DTO/SkinDTO.cs @@ -0,0 +1,20 @@ +using Model; + +namespace apiLOL.DTO +{ + public class SkinDTO + { + public SkinDTO(string name, float price = 0.0f, string icon = "", string image = "", string description = "") + { + Name = name; + Price = price; + Icon = icon; + Description = description; + } + + public string Name { get; set; } + public float Price { get; } + public string Icon { get; } + public string Description { get; } + } +} diff --git a/Sources/apiLOL/DTO/SkinMapper.cs b/Sources/apiLOL/DTO/SkinMapper.cs new file mode 100644 index 0000000..19c98a3 --- /dev/null +++ b/Sources/apiLOL/DTO/SkinMapper.cs @@ -0,0 +1,12 @@ +using Model; + +namespace apiLOL.DTO +{ + public static class SkinMapper + { + public static SkinDTO ToDTO(this Skin skin) + => new SkinDTO(skin.Name, skin.Price, skin.Icon, skin.Description); + public static Skin ToModel(this SkinDTO skinDTO) + => new Skin(skinDTO.Name, null, skinDTO.Price, skinDTO.Icon,"",skinDTO.Description); + } +} diff --git a/Sources/apiLOL/DTO/SkinPageDTO.cs b/Sources/apiLOL/DTO/SkinPageDTO.cs new file mode 100644 index 0000000..b6e645e --- /dev/null +++ b/Sources/apiLOL/DTO/SkinPageDTO.cs @@ -0,0 +1,13 @@ +namespace apiLOL.DTO +{ + public class SkinPageDTO + { + public IEnumerable Data { get; set; } + + public int Index { get; set; } + + public int Count { get; set; } + + public int TotalCount { get; set; } + } +} diff --git a/Sources/apiLOL/Program.cs b/Sources/apiLOL/Program.cs index 1a8abfa..063a905 100644 --- a/Sources/apiLOL/Program.cs +++ b/Sources/apiLOL/Program.cs @@ -1,3 +1,6 @@ +using Microsoft.AspNetCore.Mvc.Versioning; +using Microsoft.AspNetCore.Mvc; +using EFLol.DBDataManager; using Model; using StubLib; @@ -10,21 +13,35 @@ builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); -builder.Services.AddSingleton(); +//builder.Services.AddSingleton(); +builder.Services.AddScoped(); +// Scoped et Transient sont des types de cycle de vie +// Transient : une instance a chaque contruction d'objet +// Scoped : une instance par requete client + +// Configure API versioning +builder.Services.AddApiVersioning(options => +{ + options.ReportApiVersions = true; + options.AssumeDefaultVersionWhenUnspecified = true; + options.DefaultApiVersion = new ApiVersion(1, 0); + options.ApiVersionReader = new HeaderApiVersionReader("api-version"); +}); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { - app.UseSwagger(); - app.UseSwaggerUI(); + app.UseSwagger(); + app.UseSwaggerUI(); } + app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); -app.Run(); +app.Run(); \ No newline at end of file diff --git a/Sources/apiLOL/apiLOL.csproj b/Sources/apiLOL/apiLOL.csproj index b90f766..d8a99b3 100644 --- a/Sources/apiLOL/apiLOL.csproj +++ b/Sources/apiLOL/apiLOL.csproj @@ -20,6 +20,7 @@ +