From 8c082b7e8d442deccc23b0297dafd2e750083ebe Mon Sep 17 00:00:00 2001 From: Yaser Moradi Date: Mon, 1 Jan 2024 00:00:52 +0100 Subject: [PATCH] feat: update to bit 8.6.0 #37 (#38) --- .github/workflows/cd.yml | 2 +- README.md | 2 +- .../Bit.TemplatePlayground.Server.csproj | 4 +- .../Components/App.razor | 1 + .../Categories/CategoryController.cs | 2 +- .../Identity/IdentityController.cs | 22 +- .../Controllers/Products/ProductController.cs | 2 +- .../Product/ProductConfiguration.cs | 2 +- ...0231214130430_InitialMigration.Designer.cs | 624 --------- ...0231231214231_InitialMigration.Designer.cs | 629 +++++++++ ....cs => 20231231214231_InitialMigration.cs} | 50 +- .../Migrations/AppDbContextModelSnapshot.cs | 1210 +++++++++-------- .../Models/Emailing/EmailConfirmationModel.cs | 2 +- .../Startup/Middlewares.cs | 8 + .../.well-known/apple-app-site-association | 30 + .../wwwroot/.well-known/assetlinks.json | 26 + .../Bit.TemplatePlayground.Shared.csproj | 4 +- .../Dtos/AppJsonContext.cs | 11 +- ...equestDto.cs => ConfirmEmailRequestDto.cs} | 5 +- .../Dtos/PagedResultDto.cs | 10 +- .../Bit.TemplatePlayground.Client.Core.csproj | 14 +- .../Components/AppComponentBase.cs | 6 +- .../Components/Layout/ConfirmMessageBox.razor | 2 +- .../Layout/ConfirmMessageBox.razor.cs | 3 - .../Components/Layout/Footer.razor.cs | 9 +- .../Components/Layout/Footer.razor.scss | 26 +- .../Components/Layout/MainLayout.razor.scss | 26 +- .../Components/Layout/MessageBox.razor | 2 +- .../Components/Layout/MessageBox.razor.cs | 4 - .../Components/Layout/NavMenu.razor | 2 +- .../Components/Layout/NavMenu.razor.cs | 7 + .../Components/Layout/NavMenu.razor.scss | 5 +- .../Layout/SignOutConfirmModal.razor | 2 +- .../Layout/SignOutConfirmModal.razor.cs | 22 +- .../Pages/Categories/CategoriesPage.razor | 42 +- .../Pages/Categories/CategoriesPage.razor.cs | 2 +- .../Categories/CategoriesPage.razor.scss | 9 +- .../Identity/DeleteAccountConfirmModal.razor | 2 +- .../Pages/Identity/EditProfilePage.razor.scss | 40 +- .../Identity/EmailConfirmationPage.razor | 74 +- .../Identity/EmailConfirmationPage.razor.cs | 37 +- .../Identity/EmailConfirmationPage.razor.scss | 9 - .../Identity/ForgotPasswordPage.razor.scss | 11 +- .../Pages/Identity/ResetPasswordPage.razor | 63 +- .../Pages/Identity/ResetPasswordPage.razor.cs | 12 +- .../Identity/ResetPasswordPage.razor.scss | 11 +- .../Pages/Identity/SignInPage.razor.cs | 9 +- .../Pages/Identity/SignInPage.razor.scss | 13 - .../Pages/Identity/SignUpPage.razor | 2 +- .../Pages/Identity/SignUpPage.razor.cs | 10 - .../Pages/Identity/SignUpPage.razor.scss | 33 - .../Products/AddOrEditProductModal.razor | 2 +- .../Products/AddOrEditProductModal.razor.cs | 6 - .../Pages/Products/ProductsPage.razor | 36 +- .../Pages/Products/ProductsPage.razor.cs | 2 +- .../Pages/Products/ProductsPage.razor.scss | 9 +- .../Identity/IIdentityController.cs | 3 + .../Extensions/IJSRuntimeExtensions.cs | 25 - .../IServiceCollectionExtensions.cs | 1 + .../Routes.razor.cs | 16 + .../Scripts/app.ts | 28 - .../Services/AppRenderMode.cs | 10 +- .../Services/AuthenticationManager.cs | 13 +- .../Services/ExceptionHandlerBase.cs | 2 +- .../Services/PrerenderStateService.cs | 8 +- .../Styles/abstracts/_media-queries.scss | 12 +- .../Styles/app.scss | 35 +- .../_Imports.razor | 1 + .../Bit.TemplatePlayground.Client.Maui.csproj | 12 +- .../MauiProgram.cs | 43 +- .../Platforms/Android/MainActivity.cs | 35 +- .../Platforms/iOS/Entitlements.plist | 10 + .../wwwroot/index.html | 3 +- .../Bit.TemplatePlayground.Client.Web.csproj | 8 +- .../wwwroot/service-worker.published.js | 2 +- src/Directory.Build.props | 2 +- 76 files changed, 1771 insertions(+), 1708 deletions(-) delete mode 100644 src/Bit.TemplatePlayground.Server/Data/Migrations/20231214130430_InitialMigration.Designer.cs create mode 100644 src/Bit.TemplatePlayground.Server/Data/Migrations/20231231214231_InitialMigration.Designer.cs rename src/Bit.TemplatePlayground.Server/Data/Migrations/{20231214130430_InitialMigration.cs => 20231231214231_InitialMigration.cs} (90%) create mode 100644 src/Bit.TemplatePlayground.Server/wwwroot/.well-known/apple-app-site-association create mode 100644 src/Bit.TemplatePlayground.Server/wwwroot/.well-known/assetlinks.json rename src/Bit.TemplatePlayground.Shared/Dtos/Identity/{EmailConfirmedRequestDto.cs => ConfirmEmailRequestDto.cs} (69%) create mode 100644 src/Client/Bit.TemplatePlayground.Client.Maui/Platforms/iOS/Entitlements.plist diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 32e721d..0ed1f4e 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -3,7 +3,7 @@ name: Bit.TemplatePlayground CD # https://bitplatform.dev/templates/dev-ops env: - API_SERVER_ADDRESS: 'https://bp.bitplatform.dev/api/' + API_SERVER_ADDRESS: 'https://bp.bitplatform.dev/' APP_SERVICE_NAME: 'app-service-bp-test' IOS_CODE_SIGN_PROVISION: 'Bit.TemplatePlayground' diff --git a/README.md b/README.md index 42b3791..3613fdf 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Done! This sample project gets created by the following command: ```bash -dotnet new install Bit.Boilerplate && dotnet new bit-bp --name Bit.TemplatePlayground --database sqlite --sample adminpanel +dotnet new install Bit.Boilerplate && dotnet new bit-bp --name Bit.TemplatePlayground --database sqlite --sample admin ``` Note: In order to view sign-up's `confirmation email`, read [Email settings docs](https://bitplatform.dev/templates/settings). \ No newline at end of file diff --git a/src/Bit.TemplatePlayground.Server/Bit.TemplatePlayground.Server.csproj b/src/Bit.TemplatePlayground.Server/Bit.TemplatePlayground.Server.csproj index 20a1b26..95859d2 100644 --- a/src/Bit.TemplatePlayground.Server/Bit.TemplatePlayground.Server.csproj +++ b/src/Bit.TemplatePlayground.Server/Bit.TemplatePlayground.Server.csproj @@ -6,11 +6,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Bit.TemplatePlayground.Server/Components/App.razor b/src/Bit.TemplatePlayground.Server/Components/App.razor index 9d04fa8..bb363f1 100644 --- a/src/Bit.TemplatePlayground.Server/Components/App.razor +++ b/src/Bit.TemplatePlayground.Server/Components/App.razor @@ -52,6 +52,7 @@ { } + diff --git a/src/Bit.TemplatePlayground.Server/Controllers/Categories/CategoryController.cs b/src/Bit.TemplatePlayground.Server/Controllers/Categories/CategoryController.cs index e17f735..1579d4d 100644 --- a/src/Bit.TemplatePlayground.Server/Controllers/Categories/CategoryController.cs +++ b/src/Bit.TemplatePlayground.Server/Controllers/Categories/CategoryController.cs @@ -28,7 +28,7 @@ public async Task> GetCategories(ODataQueryOptions(query.AsAsyncEnumerable(), totalCount); + return new PagedResult(await query.ToArrayAsync(cancellationToken), totalCount); } [HttpGet("{id}")] diff --git a/src/Bit.TemplatePlayground.Server/Controllers/Identity/IdentityController.cs b/src/Bit.TemplatePlayground.Server/Controllers/Identity/IdentityController.cs index fc44fff..d2ce019 100644 --- a/src/Bit.TemplatePlayground.Server/Controllers/Identity/IdentityController.cs +++ b/src/Bit.TemplatePlayground.Server/Controllers/Identity/IdentityController.cs @@ -93,9 +93,7 @@ private async Task SendConfirmationEmail(SendConfirmationEmailRequestDto sendCon var controller = RouteData.Values["controller"]!.ToString(); - var confirmationLink = Url.Action(nameof(ConfirmEmail), controller, - new { user.Email, token }, - HttpContext.Request.Scheme); + var confirmationLink = new Uri(HttpContext.Request.GetBaseUrl(), $"email-confirmation?email={HttpUtility.UrlEncode(user.Email)}&token={HttpUtility.UrlEncode(token)}"); var body = await htmlRenderer.Dispatcher.InvokeAsync(async () => { @@ -127,28 +125,22 @@ private async Task SendConfirmationEmail(SendConfirmationEmailRequestDto sendCon throw new ResourceValidationException(result.ErrorMessages.Select(err => Localizer[err]).ToArray()); } - [HttpGet] - public async Task ConfirmEmail(string email, string token) + [HttpPost] + public async Task ConfirmEmail(ConfirmEmailRequestDto body) { - var user = await userManager.FindByEmailAsync(email); + var user = await userManager.FindByEmailAsync(body.Email!); if (user is null) - throw new BadRequestException(Localizer.GetString(nameof(AppStrings.UserNameNotFound), email)); + throw new BadRequestException(Localizer.GetString(nameof(AppStrings.UserNameNotFound), body.Email!)); var emailConfirmed = user.EmailConfirmed; - var errors = string.Empty; if (emailConfirmed is false) { - var result = await userManager.ConfirmEmailAsync(user, token); + var result = await userManager.ConfirmEmailAsync(user, body.Token!); if (!result.Succeeded) - errors = string.Join(", ", result.Errors.Select(e => $"{e.Code}: {e.Description}")); - emailConfirmed = result.Succeeded; + throw new ResourceValidationException(result.Errors.Select(e => new LocalizedString(e.Code, e.Description)).ToArray()); } - - string url = $"/email-confirmation?email={email}&email-confirmed={emailConfirmed}{(string.IsNullOrEmpty(errors) ? "" : ($"&error={errors}"))}"; - - return Redirect(url); } [HttpPost, ProducesResponseType(statusCode: 200)] diff --git a/src/Bit.TemplatePlayground.Server/Controllers/Products/ProductController.cs b/src/Bit.TemplatePlayground.Server/Controllers/Products/ProductController.cs index f98248d..d78102f 100644 --- a/src/Bit.TemplatePlayground.Server/Controllers/Products/ProductController.cs +++ b/src/Bit.TemplatePlayground.Server/Controllers/Products/ProductController.cs @@ -28,7 +28,7 @@ public async Task> GetProducts(ODataQueryOptions(query.AsAsyncEnumerable(), totalCount); + return new PagedResult(await query.ToArrayAsync(cancellationToken), totalCount); } [HttpGet("{id}")] diff --git a/src/Bit.TemplatePlayground.Server/Data/Configurations/Product/ProductConfiguration.cs b/src/Bit.TemplatePlayground.Server/Data/Configurations/Product/ProductConfiguration.cs index 177872d..b750c38 100644 --- a/src/Bit.TemplatePlayground.Server/Data/Configurations/Product/ProductConfiguration.cs +++ b/src/Bit.TemplatePlayground.Server/Data/Configurations/Product/ProductConfiguration.cs @@ -6,7 +6,7 @@ public class ProductConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { - DateTime baseDate = DateTime.Parse("2023-12-14"); + DateTime baseDate = DateTime.Parse("2023-12-31"); builder.HasData( new() { Id = 1, Name = "Mustang", Price = 27155, Description = "The Ford Mustang is ranked #1 in Sports Cars", CreatedOn = baseDate.AddDays(-10), CategoryId = 1 }, diff --git a/src/Bit.TemplatePlayground.Server/Data/Migrations/20231214130430_InitialMigration.Designer.cs b/src/Bit.TemplatePlayground.Server/Data/Migrations/20231214130430_InitialMigration.Designer.cs deleted file mode 100644 index f79e111..0000000 --- a/src/Bit.TemplatePlayground.Server/Data/Migrations/20231214130430_InitialMigration.Designer.cs +++ /dev/null @@ -1,624 +0,0 @@ -// -using Microsoft.EntityFrameworkCore.Infrastructure; - -#nullable disable - -namespace Bit.TemplatePlayground.Server.Data.Migrations; - -[DbContext(typeof(AppDbContext))] -[Migration("20231214130430_InitialMigration")] -partial class InitialMigration -{ - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.0"); - - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Categories.Category", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Color") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("Categories"); - - b.HasData( - new - { - Id = 1, - Color = "#FFCD56", - Name = "Ford" - }, - new - { - Id = 2, - Color = "#FF6384", - Name = "Nissan" - }, - new - { - Id = 3, - Color = "#4BC0C0", - Name = "Benz" - }, - new - { - Id = 4, - Color = "#FF9124", - Name = "BMW" - }, - new - { - Id = 5, - Color = "#2B88D8", - Name = "Tesla" - }); - }); - - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Identity.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Name") - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex"); - - b.ToTable("Roles", (string)null); - }); - - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Identity.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessFailedCount") - .HasColumnType("INTEGER"); - - b.Property("BirthDate") - .HasColumnType("INTEGER"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("ConfirmationEmailRequestedOn") - .HasColumnType("INTEGER"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("EmailConfirmed") - .HasColumnType("INTEGER"); - - b.Property("FullName") - .HasColumnType("TEXT"); - - b.Property("Gender") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnabled") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnd") - .HasColumnType("INTEGER"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("PasswordHash") - .HasColumnType("TEXT"); - - b.Property("PhoneNumber") - .HasColumnType("TEXT"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("INTEGER"); - - b.Property("ProfileImageName") - .HasColumnType("TEXT"); - - b.Property("ResetPasswordEmailRequestedOn") - .HasColumnType("INTEGER"); - - b.Property("SecurityStamp") - .HasColumnType("TEXT"); - - b.Property("TwoFactorEnabled") - .HasColumnType("INTEGER"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex"); - - b.ToTable("Users", (string)null); - - b.HasData( - new - { - Id = 1, - AccessFailedCount = 0, - BirthDate = 1306790461440000060L, - ConcurrencyStamp = "315e1a26-5b3a-4544-8e91-2760cd28e231", - Email = "test@bitplatform.dev", - EmailConfirmed = true, - FullName = "Bit.TemplatePlayground test account", - Gender = 2, - LockoutEnabled = true, - NormalizedEmail = "TEST@BITPLATFORM.DEV", - NormalizedUserName = "TEST@BITPLATFORM.DEV", - PasswordHash = "AQAAAAIAAYagAAAAEP0v3wxkdWtMkHA3Pp5/JfS+42/Qto9G05p2mta6dncSK37hPxEHa3PGE4aqN30Aag==", - PhoneNumberConfirmed = false, - SecurityStamp = "959ff4a9-4b07-4cc1-8141-c5fc033daf83", - TwoFactorEnabled = false, - UserName = "test@bitplatform.dev" - }); - }); - - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Products.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CategoryId") - .HasColumnType("INTEGER"); - - b.Property("CreatedOn") - .HasColumnType("INTEGER"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("Price") - .HasColumnType("money"); - - b.HasKey("Id"); - - b.HasIndex("CategoryId"); - - b.ToTable("Products"); - - b.HasData( - new - { - Id = 1, - CategoryId = 1, - CreatedOn = 1307386773504000060L, - Description = "The Ford Mustang is ranked #1 in Sports Cars", - Name = "Mustang", - Price = 27155m - }, - new - { - Id = 2, - CategoryId = 1, - CreatedOn = 1307377926144000060L, - Description = "The Ford GT is a mid-engine two-seater sports car manufactured and marketed by American automobile manufacturer", - Name = "GT", - Price = 500000m - }, - new - { - Id = 3, - CategoryId = 1, - CreatedOn = 1307360231424000060L, - Description = "Ford Ranger is a nameplate that has been used on multiple model lines of pickup trucks sold by Ford worldwide.", - Name = "Ranger", - Price = 25000m - }, - new - { - Id = 4, - CategoryId = 1, - CreatedOn = 1307351384064000060L, - Description = "Raptor is a SCORE off-road trophy truck living in a asphalt world", - Name = "Raptor", - Price = 53205m - }, - new - { - Id = 5, - CategoryId = 1, - CreatedOn = 1307342536704000060L, - Description = "The Ford Maverick is a compact pickup truck produced by Ford Motor Company.", - Name = "Maverick", - Price = 22470m - }, - new - { - Id = 6, - CategoryId = 2, - CreatedOn = 1307386773504000060L, - Description = "A powerful convertible sports car", - Name = "Roadster", - Price = 42800m - }, - new - { - Id = 7, - CategoryId = 2, - CreatedOn = 1307377926144000060L, - Description = "A perfectly adequate family sedan with sharp looks", - Name = "Altima", - Price = 24550m - }, - new - { - Id = 8, - CategoryId = 2, - CreatedOn = 1307360231424000060L, - Description = "Legendary supercar with AWD, 4 seats, a powerful V6 engine and the latest tech", - Name = "GT-R", - Price = 113540m - }, - new - { - Id = 9, - CategoryId = 2, - CreatedOn = 1307342536704000060L, - Description = "A new smart SUV", - Name = "Juke", - Price = 28100m - }, - new - { - Id = 10, - CategoryId = 3, - CreatedOn = 1307386773504000060L, - Description = "", - Name = "H247", - Price = 54950m - }, - new - { - Id = 11, - CategoryId = 3, - CreatedOn = 1307377926144000060L, - Description = "", - Name = "V297", - Price = 103360m - }, - new - { - Id = 12, - CategoryId = 3, - CreatedOn = 1307342536704000060L, - Description = "", - Name = "R50", - Price = 2000000m - }, - new - { - Id = 13, - CategoryId = 4, - CreatedOn = 1307386773504000060L, - Description = "", - Name = "M550i", - Price = 77790m - }, - new - { - Id = 14, - CategoryId = 4, - CreatedOn = 1307377926144000060L, - Description = "", - Name = "540i", - Price = 60945m - }, - new - { - Id = 15, - CategoryId = 4, - CreatedOn = 1307369078784000060L, - Description = "", - Name = "530e", - Price = 56545m - }, - new - { - Id = 16, - CategoryId = 4, - CreatedOn = 1307360231424000060L, - Description = "", - Name = "530i", - Price = 55195m - }, - new - { - Id = 17, - CategoryId = 4, - CreatedOn = 1307351384064000060L, - Description = "", - Name = "M850i", - Price = 100045m - }, - new - { - Id = 18, - CategoryId = 4, - CreatedOn = 1307342536704000060L, - Description = "", - Name = "X7", - Price = 77980m - }, - new - { - Id = 19, - CategoryId = 4, - CreatedOn = 1307333689344000060L, - Description = "", - Name = "IX", - Price = 87000m - }, - new - { - Id = 20, - CategoryId = 5, - CreatedOn = 1307386773504000060L, - Description = "rapid acceleration and dynamic handling", - Name = "Model 3", - Price = 61990m - }, - new - { - Id = 21, - CategoryId = 5, - CreatedOn = 1307377926144000060L, - Description = "finishes near the top of our luxury electric car rankings.", - Name = "Model S", - Price = 135000m - }, - new - { - Id = 22, - CategoryId = 5, - CreatedOn = 1307369078784000060L, - Description = "Heart-pumping acceleration, long drive range", - Name = "Model X", - Price = 138890m - }, - new - { - Id = 23, - CategoryId = 5, - CreatedOn = 1307342536704000060L, - Description = "extensive driving range, lots of standard safety features", - Name = "Model Y", - Price = 67790m - }); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("FriendlyName") - .HasColumnType("TEXT"); - - b.Property("Xml") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("DataProtectionKeys"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("RoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("UserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("TEXT"); - - b.Property("ProviderKey") - .HasColumnType("TEXT"); - - b.Property("ProviderDisplayName") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("INTEGER"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("UserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("INTEGER"); - - b.Property("RoleId") - .HasColumnType("INTEGER"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("UserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("INTEGER"); - - b.Property("LoginProvider") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("UserTokens", (string)null); - }); - - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Products.Product", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Categories.Category", "Category") - .WithMany("Products") - .HasForeignKey("CategoryId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Category"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.Role", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.Role", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Categories.Category", b => - { - b.Navigation("Products"); - }); -#pragma warning restore 612, 618 - } -} diff --git a/src/Bit.TemplatePlayground.Server/Data/Migrations/20231231214231_InitialMigration.Designer.cs b/src/Bit.TemplatePlayground.Server/Data/Migrations/20231231214231_InitialMigration.Designer.cs new file mode 100644 index 0000000..e345649 --- /dev/null +++ b/src/Bit.TemplatePlayground.Server/Data/Migrations/20231231214231_InitialMigration.Designer.cs @@ -0,0 +1,629 @@ +// +using Bit.TemplatePlayground.Server.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Bit.TemplatePlayground.Server.Data.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20231231214231_InitialMigration")] + partial class InitialMigration + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.0"); + + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Categories.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Color") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = 1, + Color = "#FFCD56", + Name = "Ford" + }, + new + { + Id = 2, + Color = "#FF6384", + Name = "Nissan" + }, + new + { + Id = 3, + Color = "#4BC0C0", + Name = "Benz" + }, + new + { + Id = 4, + Color = "#FF9124", + Name = "BMW" + }, + new + { + Id = 5, + Color = "#2B88D8", + Name = "Tesla" + }); + }); + + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Identity.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Identity.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("BirthDate") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("ConfirmationEmailRequestedOn") + .HasColumnType("INTEGER"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("FullName") + .HasColumnType("TEXT"); + + b.Property("Gender") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProfileImageName") + .HasColumnType("TEXT"); + + b.Property("ResetPasswordEmailRequestedOn") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("Users", (string)null); + + b.HasData( + new + { + Id = 1, + AccessFailedCount = 0, + BirthDate = 1306790461440000060L, + ConcurrencyStamp = "315e1a26-5b3a-4544-8e91-2760cd28e231", + Email = "test@bitplatform.dev", + EmailConfirmed = true, + FullName = "Bit.TemplatePlayground test account", + Gender = 2, + LockoutEnabled = true, + NormalizedEmail = "TEST@BITPLATFORM.DEV", + NormalizedUserName = "TEST@BITPLATFORM.DEV", + PasswordHash = "AQAAAAIAAYagAAAAEP0v3wxkdWtMkHA3Pp5/JfS+42/Qto9G05p2mta6dncSK37hPxEHa3PGE4aqN30Aag==", + PhoneNumberConfirmed = false, + SecurityStamp = "959ff4a9-4b07-4cc1-8141-c5fc033daf83", + TwoFactorEnabled = false, + UserName = "test@bitplatform.dev" + }); + }); + + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Products.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CategoryId") + .HasColumnType("INTEGER"); + + b.Property("CreatedOn") + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("money"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.ToTable("Products"); + + b.HasData( + new + { + Id = 1, + CategoryId = 1, + CreatedOn = 1307416854528000060L, + Description = "The Ford Mustang is ranked #1 in Sports Cars", + Name = "Mustang", + Price = 27155m + }, + new + { + Id = 2, + CategoryId = 1, + CreatedOn = 1307408007168000060L, + Description = "The Ford GT is a mid-engine two-seater sports car manufactured and marketed by American automobile manufacturer", + Name = "GT", + Price = 500000m + }, + new + { + Id = 3, + CategoryId = 1, + CreatedOn = 1307390312448000060L, + Description = "Ford Ranger is a nameplate that has been used on multiple model lines of pickup trucks sold by Ford worldwide.", + Name = "Ranger", + Price = 25000m + }, + new + { + Id = 4, + CategoryId = 1, + CreatedOn = 1307381465088000060L, + Description = "Raptor is a SCORE off-road trophy truck living in a asphalt world", + Name = "Raptor", + Price = 53205m + }, + new + { + Id = 5, + CategoryId = 1, + CreatedOn = 1307372617728000060L, + Description = "The Ford Maverick is a compact pickup truck produced by Ford Motor Company.", + Name = "Maverick", + Price = 22470m + }, + new + { + Id = 6, + CategoryId = 2, + CreatedOn = 1307416854528000060L, + Description = "A powerful convertible sports car", + Name = "Roadster", + Price = 42800m + }, + new + { + Id = 7, + CategoryId = 2, + CreatedOn = 1307408007168000060L, + Description = "A perfectly adequate family sedan with sharp looks", + Name = "Altima", + Price = 24550m + }, + new + { + Id = 8, + CategoryId = 2, + CreatedOn = 1307390312448000060L, + Description = "Legendary supercar with AWD, 4 seats, a powerful V6 engine and the latest tech", + Name = "GT-R", + Price = 113540m + }, + new + { + Id = 9, + CategoryId = 2, + CreatedOn = 1307372617728000060L, + Description = "A new smart SUV", + Name = "Juke", + Price = 28100m + }, + new + { + Id = 10, + CategoryId = 3, + CreatedOn = 1307416854528000060L, + Description = "", + Name = "H247", + Price = 54950m + }, + new + { + Id = 11, + CategoryId = 3, + CreatedOn = 1307408007168000060L, + Description = "", + Name = "V297", + Price = 103360m + }, + new + { + Id = 12, + CategoryId = 3, + CreatedOn = 1307372617728000060L, + Description = "", + Name = "R50", + Price = 2000000m + }, + new + { + Id = 13, + CategoryId = 4, + CreatedOn = 1307416854528000060L, + Description = "", + Name = "M550i", + Price = 77790m + }, + new + { + Id = 14, + CategoryId = 4, + CreatedOn = 1307408007168000060L, + Description = "", + Name = "540i", + Price = 60945m + }, + new + { + Id = 15, + CategoryId = 4, + CreatedOn = 1307399159808000060L, + Description = "", + Name = "530e", + Price = 56545m + }, + new + { + Id = 16, + CategoryId = 4, + CreatedOn = 1307390312448000060L, + Description = "", + Name = "530i", + Price = 55195m + }, + new + { + Id = 17, + CategoryId = 4, + CreatedOn = 1307381465088000060L, + Description = "", + Name = "M850i", + Price = 100045m + }, + new + { + Id = 18, + CategoryId = 4, + CreatedOn = 1307372617728000060L, + Description = "", + Name = "X7", + Price = 77980m + }, + new + { + Id = 19, + CategoryId = 4, + CreatedOn = 1307363770368000060L, + Description = "", + Name = "IX", + Price = 87000m + }, + new + { + Id = 20, + CategoryId = 5, + CreatedOn = 1307416854528000060L, + Description = "rapid acceleration and dynamic handling", + Name = "Model 3", + Price = 61990m + }, + new + { + Id = 21, + CategoryId = 5, + CreatedOn = 1307408007168000060L, + Description = "finishes near the top of our luxury electric car rankings.", + Name = "Model S", + Price = 135000m + }, + new + { + Id = 22, + CategoryId = 5, + CreatedOn = 1307399159808000060L, + Description = "Heart-pumping acceleration, long drive range", + Name = "Model X", + Price = 138890m + }, + new + { + Id = 23, + CategoryId = 5, + CreatedOn = 1307372617728000060L, + Description = "extensive driving range, lots of standard safety features", + Name = "Model Y", + Price = 67790m + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("FriendlyName") + .HasColumnType("TEXT"); + + b.Property("Xml") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Products.Product", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Categories.Category", "Category") + .WithMany("Products") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Categories.Category", b => + { + b.Navigation("Products"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Bit.TemplatePlayground.Server/Data/Migrations/20231214130430_InitialMigration.cs b/src/Bit.TemplatePlayground.Server/Data/Migrations/20231231214231_InitialMigration.cs similarity index 90% rename from src/Bit.TemplatePlayground.Server/Data/Migrations/20231214130430_InitialMigration.cs rename to src/Bit.TemplatePlayground.Server/Data/Migrations/20231231214231_InitialMigration.cs index a4e8fe0..9d15de8 100644 --- a/src/Bit.TemplatePlayground.Server/Data/Migrations/20231214130430_InitialMigration.cs +++ b/src/Bit.TemplatePlayground.Server/Data/Migrations/20231231214231_InitialMigration.cs @@ -1,4 +1,6 @@ -#nullable disable +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional @@ -236,29 +238,29 @@ protected override void Up(MigrationBuilder migrationBuilder) columns: new[] { "Id", "CategoryId", "CreatedOn", "Description", "Name", "Price" }, values: new object[,] { - { 1, 1, 1307386773504000060L, "The Ford Mustang is ranked #1 in Sports Cars", "Mustang", 27155m }, - { 2, 1, 1307377926144000060L, "The Ford GT is a mid-engine two-seater sports car manufactured and marketed by American automobile manufacturer", "GT", 500000m }, - { 3, 1, 1307360231424000060L, "Ford Ranger is a nameplate that has been used on multiple model lines of pickup trucks sold by Ford worldwide.", "Ranger", 25000m }, - { 4, 1, 1307351384064000060L, "Raptor is a SCORE off-road trophy truck living in a asphalt world", "Raptor", 53205m }, - { 5, 1, 1307342536704000060L, "The Ford Maverick is a compact pickup truck produced by Ford Motor Company.", "Maverick", 22470m }, - { 6, 2, 1307386773504000060L, "A powerful convertible sports car", "Roadster", 42800m }, - { 7, 2, 1307377926144000060L, "A perfectly adequate family sedan with sharp looks", "Altima", 24550m }, - { 8, 2, 1307360231424000060L, "Legendary supercar with AWD, 4 seats, a powerful V6 engine and the latest tech", "GT-R", 113540m }, - { 9, 2, 1307342536704000060L, "A new smart SUV", "Juke", 28100m }, - { 10, 3, 1307386773504000060L, "", "H247", 54950m }, - { 11, 3, 1307377926144000060L, "", "V297", 103360m }, - { 12, 3, 1307342536704000060L, "", "R50", 2000000m }, - { 13, 4, 1307386773504000060L, "", "M550i", 77790m }, - { 14, 4, 1307377926144000060L, "", "540i", 60945m }, - { 15, 4, 1307369078784000060L, "", "530e", 56545m }, - { 16, 4, 1307360231424000060L, "", "530i", 55195m }, - { 17, 4, 1307351384064000060L, "", "M850i", 100045m }, - { 18, 4, 1307342536704000060L, "", "X7", 77980m }, - { 19, 4, 1307333689344000060L, "", "IX", 87000m }, - { 20, 5, 1307386773504000060L, "rapid acceleration and dynamic handling", "Model 3", 61990m }, - { 21, 5, 1307377926144000060L, "finishes near the top of our luxury electric car rankings.", "Model S", 135000m }, - { 22, 5, 1307369078784000060L, "Heart-pumping acceleration, long drive range", "Model X", 138890m }, - { 23, 5, 1307342536704000060L, "extensive driving range, lots of standard safety features", "Model Y", 67790m } + { 1, 1, 1307416854528000060L, "The Ford Mustang is ranked #1 in Sports Cars", "Mustang", 27155m }, + { 2, 1, 1307408007168000060L, "The Ford GT is a mid-engine two-seater sports car manufactured and marketed by American automobile manufacturer", "GT", 500000m }, + { 3, 1, 1307390312448000060L, "Ford Ranger is a nameplate that has been used on multiple model lines of pickup trucks sold by Ford worldwide.", "Ranger", 25000m }, + { 4, 1, 1307381465088000060L, "Raptor is a SCORE off-road trophy truck living in a asphalt world", "Raptor", 53205m }, + { 5, 1, 1307372617728000060L, "The Ford Maverick is a compact pickup truck produced by Ford Motor Company.", "Maverick", 22470m }, + { 6, 2, 1307416854528000060L, "A powerful convertible sports car", "Roadster", 42800m }, + { 7, 2, 1307408007168000060L, "A perfectly adequate family sedan with sharp looks", "Altima", 24550m }, + { 8, 2, 1307390312448000060L, "Legendary supercar with AWD, 4 seats, a powerful V6 engine and the latest tech", "GT-R", 113540m }, + { 9, 2, 1307372617728000060L, "A new smart SUV", "Juke", 28100m }, + { 10, 3, 1307416854528000060L, "", "H247", 54950m }, + { 11, 3, 1307408007168000060L, "", "V297", 103360m }, + { 12, 3, 1307372617728000060L, "", "R50", 2000000m }, + { 13, 4, 1307416854528000060L, "", "M550i", 77790m }, + { 14, 4, 1307408007168000060L, "", "540i", 60945m }, + { 15, 4, 1307399159808000060L, "", "530e", 56545m }, + { 16, 4, 1307390312448000060L, "", "530i", 55195m }, + { 17, 4, 1307381465088000060L, "", "M850i", 100045m }, + { 18, 4, 1307372617728000060L, "", "X7", 77980m }, + { 19, 4, 1307363770368000060L, "", "IX", 87000m }, + { 20, 5, 1307416854528000060L, "rapid acceleration and dynamic handling", "Model 3", 61990m }, + { 21, 5, 1307408007168000060L, "finishes near the top of our luxury electric car rankings.", "Model S", 135000m }, + { 22, 5, 1307399159808000060L, "Heart-pumping acceleration, long drive range", "Model X", 138890m }, + { 23, 5, 1307372617728000060L, "extensive driving range, lots of standard safety features", "Model Y", 67790m } }); migrationBuilder.CreateIndex( diff --git a/src/Bit.TemplatePlayground.Server/Data/Migrations/AppDbContextModelSnapshot.cs b/src/Bit.TemplatePlayground.Server/Data/Migrations/AppDbContextModelSnapshot.cs index 9699a32..1f077ac 100644 --- a/src/Bit.TemplatePlayground.Server/Data/Migrations/AppDbContextModelSnapshot.cs +++ b/src/Bit.TemplatePlayground.Server/Data/Migrations/AppDbContextModelSnapshot.cs @@ -1,622 +1,626 @@ // +using Bit.TemplatePlayground.Server.Data; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; #nullable disable -namespace Bit.TemplatePlayground.Server.Data.Migrations; - -[DbContext(typeof(AppDbContext))] -partial class AppDbContextModelSnapshot : ModelSnapshot +namespace Bit.TemplatePlayground.Server.Data.Migrations { - protected override void BuildModel(ModelBuilder modelBuilder) + [DbContext(typeof(AppDbContext))] + partial class AppDbContextModelSnapshot : ModelSnapshot { + protected override void BuildModel(ModelBuilder modelBuilder) + { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.0"); - - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Categories.Category", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Color") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("Categories"); - - b.HasData( - new - { - Id = 1, - Color = "#FFCD56", - Name = "Ford" - }, - new - { - Id = 2, - Color = "#FF6384", - Name = "Nissan" - }, - new - { - Id = 3, - Color = "#4BC0C0", - Name = "Benz" - }, - new - { - Id = 4, - Color = "#FF9124", - Name = "BMW" - }, - new - { - Id = 5, - Color = "#2B88D8", - Name = "Tesla" - }); - }); - - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Identity.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Name") - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex"); - - b.ToTable("Roles", (string)null); - }); - - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Identity.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessFailedCount") - .HasColumnType("INTEGER"); - - b.Property("BirthDate") - .HasColumnType("INTEGER"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("ConfirmationEmailRequestedOn") - .HasColumnType("INTEGER"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("EmailConfirmed") - .HasColumnType("INTEGER"); - - b.Property("FullName") - .HasColumnType("TEXT"); - - b.Property("Gender") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnabled") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnd") - .HasColumnType("INTEGER"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("PasswordHash") - .HasColumnType("TEXT"); - - b.Property("PhoneNumber") - .HasColumnType("TEXT"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("INTEGER"); - - b.Property("ProfileImageName") - .HasColumnType("TEXT"); - - b.Property("ResetPasswordEmailRequestedOn") - .HasColumnType("INTEGER"); - - b.Property("SecurityStamp") - .HasColumnType("TEXT"); - - b.Property("TwoFactorEnabled") - .HasColumnType("INTEGER"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex"); - - b.ToTable("Users", (string)null); - - b.HasData( - new - { - Id = 1, - AccessFailedCount = 0, - BirthDate = 1306790461440000060L, - ConcurrencyStamp = "315e1a26-5b3a-4544-8e91-2760cd28e231", - Email = "test@bitplatform.dev", - EmailConfirmed = true, - FullName = "Bit.TemplatePlayground test account", - Gender = 2, - LockoutEnabled = true, - NormalizedEmail = "TEST@BITPLATFORM.DEV", - NormalizedUserName = "TEST@BITPLATFORM.DEV", - PasswordHash = "AQAAAAIAAYagAAAAEP0v3wxkdWtMkHA3Pp5/JfS+42/Qto9G05p2mta6dncSK37hPxEHa3PGE4aqN30Aag==", - PhoneNumberConfirmed = false, - SecurityStamp = "959ff4a9-4b07-4cc1-8141-c5fc033daf83", - TwoFactorEnabled = false, - UserName = "test@bitplatform.dev" - }); - }); - - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Products.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CategoryId") - .HasColumnType("INTEGER"); - - b.Property("CreatedOn") - .HasColumnType("INTEGER"); - - b.Property("Description") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("Price") - .HasColumnType("money"); - - b.HasKey("Id"); - - b.HasIndex("CategoryId"); - - b.ToTable("Products"); - - b.HasData( - new - { - Id = 1, - CategoryId = 1, - CreatedOn = 1307386773504000060L, - Description = "The Ford Mustang is ranked #1 in Sports Cars", - Name = "Mustang", - Price = 27155m - }, - new - { - Id = 2, - CategoryId = 1, - CreatedOn = 1307377926144000060L, - Description = "The Ford GT is a mid-engine two-seater sports car manufactured and marketed by American automobile manufacturer", - Name = "GT", - Price = 500000m - }, - new - { - Id = 3, - CategoryId = 1, - CreatedOn = 1307360231424000060L, - Description = "Ford Ranger is a nameplate that has been used on multiple model lines of pickup trucks sold by Ford worldwide.", - Name = "Ranger", - Price = 25000m - }, - new - { - Id = 4, - CategoryId = 1, - CreatedOn = 1307351384064000060L, - Description = "Raptor is a SCORE off-road trophy truck living in a asphalt world", - Name = "Raptor", - Price = 53205m - }, - new - { - Id = 5, - CategoryId = 1, - CreatedOn = 1307342536704000060L, - Description = "The Ford Maverick is a compact pickup truck produced by Ford Motor Company.", - Name = "Maverick", - Price = 22470m - }, - new - { - Id = 6, - CategoryId = 2, - CreatedOn = 1307386773504000060L, - Description = "A powerful convertible sports car", - Name = "Roadster", - Price = 42800m - }, - new - { - Id = 7, - CategoryId = 2, - CreatedOn = 1307377926144000060L, - Description = "A perfectly adequate family sedan with sharp looks", - Name = "Altima", - Price = 24550m - }, - new - { - Id = 8, - CategoryId = 2, - CreatedOn = 1307360231424000060L, - Description = "Legendary supercar with AWD, 4 seats, a powerful V6 engine and the latest tech", - Name = "GT-R", - Price = 113540m - }, - new - { - Id = 9, - CategoryId = 2, - CreatedOn = 1307342536704000060L, - Description = "A new smart SUV", - Name = "Juke", - Price = 28100m - }, - new - { - Id = 10, - CategoryId = 3, - CreatedOn = 1307386773504000060L, - Description = "", - Name = "H247", - Price = 54950m - }, - new - { - Id = 11, - CategoryId = 3, - CreatedOn = 1307377926144000060L, - Description = "", - Name = "V297", - Price = 103360m - }, - new - { - Id = 12, - CategoryId = 3, - CreatedOn = 1307342536704000060L, - Description = "", - Name = "R50", - Price = 2000000m - }, - new - { - Id = 13, - CategoryId = 4, - CreatedOn = 1307386773504000060L, - Description = "", - Name = "M550i", - Price = 77790m - }, - new - { - Id = 14, - CategoryId = 4, - CreatedOn = 1307377926144000060L, - Description = "", - Name = "540i", - Price = 60945m - }, - new - { - Id = 15, - CategoryId = 4, - CreatedOn = 1307369078784000060L, - Description = "", - Name = "530e", - Price = 56545m - }, - new - { - Id = 16, - CategoryId = 4, - CreatedOn = 1307360231424000060L, - Description = "", - Name = "530i", - Price = 55195m - }, - new - { - Id = 17, - CategoryId = 4, - CreatedOn = 1307351384064000060L, - Description = "", - Name = "M850i", - Price = 100045m - }, - new - { - Id = 18, - CategoryId = 4, - CreatedOn = 1307342536704000060L, - Description = "", - Name = "X7", - Price = 77980m - }, - new - { - Id = 19, - CategoryId = 4, - CreatedOn = 1307333689344000060L, - Description = "", - Name = "IX", - Price = 87000m - }, - new - { - Id = 20, - CategoryId = 5, - CreatedOn = 1307386773504000060L, - Description = "rapid acceleration and dynamic handling", - Name = "Model 3", - Price = 61990m - }, - new - { - Id = 21, - CategoryId = 5, - CreatedOn = 1307377926144000060L, - Description = "finishes near the top of our luxury electric car rankings.", - Name = "Model S", - Price = 135000m - }, - new - { - Id = 22, - CategoryId = 5, - CreatedOn = 1307369078784000060L, - Description = "Heart-pumping acceleration, long drive range", - Name = "Model X", - Price = 138890m - }, - new - { - Id = 23, - CategoryId = 5, - CreatedOn = 1307342536704000060L, - Description = "extensive driving range, lots of standard safety features", - Name = "Model Y", - Price = 67790m - }); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("FriendlyName") - .HasColumnType("TEXT"); - - b.Property("Xml") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("DataProtectionKeys"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("RoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("UserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("TEXT"); - - b.Property("ProviderKey") - .HasColumnType("TEXT"); - - b.Property("ProviderDisplayName") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("INTEGER"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("UserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("INTEGER"); - - b.Property("RoleId") - .HasColumnType("INTEGER"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("UserRoles", (string)null); - }); + modelBuilder.HasAnnotation("ProductVersion", "8.0.0"); + + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Categories.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Color") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = 1, + Color = "#FFCD56", + Name = "Ford" + }, + new + { + Id = 2, + Color = "#FF6384", + Name = "Nissan" + }, + new + { + Id = 3, + Color = "#4BC0C0", + Name = "Benz" + }, + new + { + Id = 4, + Color = "#FF9124", + Name = "BMW" + }, + new + { + Id = 5, + Color = "#2B88D8", + Name = "Tesla" + }); + }); + + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Identity.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Identity.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("BirthDate") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("ConfirmationEmailRequestedOn") + .HasColumnType("INTEGER"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("FullName") + .HasColumnType("TEXT"); + + b.Property("Gender") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProfileImageName") + .HasColumnType("TEXT"); + + b.Property("ResetPasswordEmailRequestedOn") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("Users", (string)null); + + b.HasData( + new + { + Id = 1, + AccessFailedCount = 0, + BirthDate = 1306790461440000060L, + ConcurrencyStamp = "315e1a26-5b3a-4544-8e91-2760cd28e231", + Email = "test@bitplatform.dev", + EmailConfirmed = true, + FullName = "Bit.TemplatePlayground test account", + Gender = 2, + LockoutEnabled = true, + NormalizedEmail = "TEST@BITPLATFORM.DEV", + NormalizedUserName = "TEST@BITPLATFORM.DEV", + PasswordHash = "AQAAAAIAAYagAAAAEP0v3wxkdWtMkHA3Pp5/JfS+42/Qto9G05p2mta6dncSK37hPxEHa3PGE4aqN30Aag==", + PhoneNumberConfirmed = false, + SecurityStamp = "959ff4a9-4b07-4cc1-8141-c5fc033daf83", + TwoFactorEnabled = false, + UserName = "test@bitplatform.dev" + }); + }); + + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Products.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CategoryId") + .HasColumnType("INTEGER"); + + b.Property("CreatedOn") + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("money"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.ToTable("Products"); + + b.HasData( + new + { + Id = 1, + CategoryId = 1, + CreatedOn = 1307416854528000060L, + Description = "The Ford Mustang is ranked #1 in Sports Cars", + Name = "Mustang", + Price = 27155m + }, + new + { + Id = 2, + CategoryId = 1, + CreatedOn = 1307408007168000060L, + Description = "The Ford GT is a mid-engine two-seater sports car manufactured and marketed by American automobile manufacturer", + Name = "GT", + Price = 500000m + }, + new + { + Id = 3, + CategoryId = 1, + CreatedOn = 1307390312448000060L, + Description = "Ford Ranger is a nameplate that has been used on multiple model lines of pickup trucks sold by Ford worldwide.", + Name = "Ranger", + Price = 25000m + }, + new + { + Id = 4, + CategoryId = 1, + CreatedOn = 1307381465088000060L, + Description = "Raptor is a SCORE off-road trophy truck living in a asphalt world", + Name = "Raptor", + Price = 53205m + }, + new + { + Id = 5, + CategoryId = 1, + CreatedOn = 1307372617728000060L, + Description = "The Ford Maverick is a compact pickup truck produced by Ford Motor Company.", + Name = "Maverick", + Price = 22470m + }, + new + { + Id = 6, + CategoryId = 2, + CreatedOn = 1307416854528000060L, + Description = "A powerful convertible sports car", + Name = "Roadster", + Price = 42800m + }, + new + { + Id = 7, + CategoryId = 2, + CreatedOn = 1307408007168000060L, + Description = "A perfectly adequate family sedan with sharp looks", + Name = "Altima", + Price = 24550m + }, + new + { + Id = 8, + CategoryId = 2, + CreatedOn = 1307390312448000060L, + Description = "Legendary supercar with AWD, 4 seats, a powerful V6 engine and the latest tech", + Name = "GT-R", + Price = 113540m + }, + new + { + Id = 9, + CategoryId = 2, + CreatedOn = 1307372617728000060L, + Description = "A new smart SUV", + Name = "Juke", + Price = 28100m + }, + new + { + Id = 10, + CategoryId = 3, + CreatedOn = 1307416854528000060L, + Description = "", + Name = "H247", + Price = 54950m + }, + new + { + Id = 11, + CategoryId = 3, + CreatedOn = 1307408007168000060L, + Description = "", + Name = "V297", + Price = 103360m + }, + new + { + Id = 12, + CategoryId = 3, + CreatedOn = 1307372617728000060L, + Description = "", + Name = "R50", + Price = 2000000m + }, + new + { + Id = 13, + CategoryId = 4, + CreatedOn = 1307416854528000060L, + Description = "", + Name = "M550i", + Price = 77790m + }, + new + { + Id = 14, + CategoryId = 4, + CreatedOn = 1307408007168000060L, + Description = "", + Name = "540i", + Price = 60945m + }, + new + { + Id = 15, + CategoryId = 4, + CreatedOn = 1307399159808000060L, + Description = "", + Name = "530e", + Price = 56545m + }, + new + { + Id = 16, + CategoryId = 4, + CreatedOn = 1307390312448000060L, + Description = "", + Name = "530i", + Price = 55195m + }, + new + { + Id = 17, + CategoryId = 4, + CreatedOn = 1307381465088000060L, + Description = "", + Name = "M850i", + Price = 100045m + }, + new + { + Id = 18, + CategoryId = 4, + CreatedOn = 1307372617728000060L, + Description = "", + Name = "X7", + Price = 77980m + }, + new + { + Id = 19, + CategoryId = 4, + CreatedOn = 1307363770368000060L, + Description = "", + Name = "IX", + Price = 87000m + }, + new + { + Id = 20, + CategoryId = 5, + CreatedOn = 1307416854528000060L, + Description = "rapid acceleration and dynamic handling", + Name = "Model 3", + Price = 61990m + }, + new + { + Id = 21, + CategoryId = 5, + CreatedOn = 1307408007168000060L, + Description = "finishes near the top of our luxury electric car rankings.", + Name = "Model S", + Price = 135000m + }, + new + { + Id = 22, + CategoryId = 5, + CreatedOn = 1307399159808000060L, + Description = "Heart-pumping acceleration, long drive range", + Name = "Model X", + Price = 138890m + }, + new + { + Id = 23, + CategoryId = 5, + CreatedOn = 1307372617728000060L, + Description = "extensive driving range, lots of standard safety features", + Name = "Model Y", + Price = 67790m + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("FriendlyName") + .HasColumnType("TEXT"); + + b.Property("Xml") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("INTEGER"); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("INTEGER"); - b.Property("LoginProvider") - .HasColumnType("TEXT"); + b.Property("LoginProvider") + .HasColumnType("TEXT"); - b.Property("Name") - .HasColumnType("TEXT"); + b.Property("Name") + .HasColumnType("TEXT"); - b.Property("Value") - .HasColumnType("TEXT"); + b.Property("Value") + .HasColumnType("TEXT"); - b.HasKey("UserId", "LoginProvider", "Name"); + b.HasKey("UserId", "LoginProvider", "Name"); - b.ToTable("UserTokens", (string)null); - }); + b.ToTable("UserTokens", (string)null); + }); - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Products.Product", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Categories.Category", "Category") - .WithMany("Products") - .HasForeignKey("CategoryId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Products.Product", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Categories.Category", "Category") + .WithMany("Products") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.Navigation("Category"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.Role", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.Role", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Categories.Category", b => - { - b.Navigation("Products"); - }); + b.Navigation("Category"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Bit.TemplatePlayground.Server.Models.Identity.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.TemplatePlayground.Server.Models.Categories.Category", b => + { + b.Navigation("Products"); + }); #pragma warning restore 612, 618 + } } } diff --git a/src/Bit.TemplatePlayground.Server/Models/Emailing/EmailConfirmationModel.cs b/src/Bit.TemplatePlayground.Server/Models/Emailing/EmailConfirmationModel.cs index 1622710..bcecabf 100644 --- a/src/Bit.TemplatePlayground.Server/Models/Emailing/EmailConfirmationModel.cs +++ b/src/Bit.TemplatePlayground.Server/Models/Emailing/EmailConfirmationModel.cs @@ -2,5 +2,5 @@ public class EmailConfirmationModel { - public string? ConfirmationLink { get; set; } + public Uri? ConfirmationLink { get; set; } } diff --git a/src/Bit.TemplatePlayground.Server/Startup/Middlewares.cs b/src/Bit.TemplatePlayground.Server/Startup/Middlewares.cs index 38acd2e..1169c1d 100644 --- a/src/Bit.TemplatePlayground.Server/Startup/Middlewares.cs +++ b/src/Bit.TemplatePlayground.Server/Startup/Middlewares.cs @@ -85,6 +85,14 @@ public static void Use(WebApplication app, IHostEnvironment env, IConfiguration QueryStringParameter = queryStringParameter }).WithTags("Test"); + app.MapGet("/.well-known/apple-app-site-association", async () => + { + // https://branch.io/resources/aasa-validator/ + var contentType = "application/json; charset=utf-8"; + var path = Path.Combine("wwwroot/.well-known", "apple-app-site-association"); + return Results.Stream(File.OpenRead(path), contentType, "apple-app-site-association"); + }).ExcludeFromDescription(); + app.MapControllers().RequireAuthorization(); var appSettings = configuration.GetSection(nameof(AppSettings)).Get()!; diff --git a/src/Bit.TemplatePlayground.Server/wwwroot/.well-known/apple-app-site-association b/src/Bit.TemplatePlayground.Server/wwwroot/.well-known/apple-app-site-association new file mode 100644 index 0000000..c1673e5 --- /dev/null +++ b/src/Bit.TemplatePlayground.Server/wwwroot/.well-known/apple-app-site-association @@ -0,0 +1,30 @@ +{ + "activitycontinuation": { + "apps": [ "76WD644YU8.com.bitplatform.AdminPanel.Template", "76WD644YU8.com.bitplatform.Todo.Template" ] + }, + "applinks": { + "apps": [], + "details": [ + { + "appID": "76WD644YU8.com.bitplatform.AdminPanel.Template", + "paths": [ "*", "/*" ], + "components": [ + { + "/": "/*", + "comment": "Matches any URL with a path that starts with /" + } + ] + }, + { + "appID": "76WD644YU8.com.bitplatform.Todo.Template", + "paths": [ "*", "/*" ], + "components": [ + { + "/": "/*", + "comment": "Matches any URL with a path that starts with /" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/src/Bit.TemplatePlayground.Server/wwwroot/.well-known/assetlinks.json b/src/Bit.TemplatePlayground.Server/wwwroot/.well-known/assetlinks.json new file mode 100644 index 0000000..3994691 --- /dev/null +++ b/src/Bit.TemplatePlayground.Server/wwwroot/.well-known/assetlinks.json @@ -0,0 +1,26 @@ +[ + { + "relation": [ + "delegate_permission/common.handle_all_urls" + ], + "target": { + "namespace": "android_app", + "package_name": "com.bitplatform.AdminPanel.Template", + "sha256_cert_fingerprints": [ + "7E:F0:3C:AE:55:06:1D:9F:A1:0C:96:86:C0:C3:64:84:23:C0:9F:AE:17:45:FF:0E:76:34:99:5C:8E:74:40:65" + ] + } + }, + { + "relation": [ + "delegate_permission/common.handle_all_urls" + ], + "target": { + "namespace": "android_app", + "package_name": "com.bitplatform.Todo.Template", + "sha256_cert_fingerprints": [ + "7E:F0:3C:AE:55:06:1D:9F:A1:0C:96:86:C0:C3:64:84:23:C0:9F:AE:17:45:FF:0E:76:34:99:5C:8E:74:40:65" + ] + } + } +] \ No newline at end of file diff --git a/src/Bit.TemplatePlayground.Shared/Bit.TemplatePlayground.Shared.csproj b/src/Bit.TemplatePlayground.Shared/Bit.TemplatePlayground.Shared.csproj index 735acc5..d8cee8c 100644 --- a/src/Bit.TemplatePlayground.Shared/Bit.TemplatePlayground.Shared.csproj +++ b/src/Bit.TemplatePlayground.Shared/Bit.TemplatePlayground.Shared.csproj @@ -5,11 +5,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Bit.TemplatePlayground.Shared/Dtos/AppJsonContext.cs b/src/Bit.TemplatePlayground.Shared/Dtos/AppJsonContext.cs index 1009ea7..3173ccc 100644 --- a/src/Bit.TemplatePlayground.Shared/Dtos/AppJsonContext.cs +++ b/src/Bit.TemplatePlayground.Shared/Dtos/AppJsonContext.cs @@ -11,16 +11,13 @@ namespace Bit.TemplatePlayground.Shared.Dtos; [JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] [JsonSerializable(typeof(Dictionary))] [JsonSerializable(typeof(UserDto))] -[JsonSerializable(typeof(List))] +[JsonSerializable(typeof(ProductsCountPerCategoryResponseDto))] [JsonSerializable(typeof(OverallAnalyticsStatsDataResponseDto))] -[JsonSerializable(typeof(List))] -[JsonSerializable(typeof(List))] -[JsonSerializable(typeof(List))] +[JsonSerializable(typeof(ProductSaleStatResponseDto))] +[JsonSerializable(typeof(ProductPercentagePerCategoryResponseDto))] [JsonSerializable(typeof(ProductDto))] -[JsonSerializable(typeof(List))] [JsonSerializable(typeof(PagedResult))] [JsonSerializable(typeof(CategoryDto))] -[JsonSerializable(typeof(List))] [JsonSerializable(typeof(PagedResult))] [JsonSerializable(typeof(SignInRequestDto))] [JsonSerializable(typeof(TokenResponseDto))] @@ -28,8 +25,8 @@ namespace Bit.TemplatePlayground.Shared.Dtos; [JsonSerializable(typeof(SignUpRequestDto))] [JsonSerializable(typeof(EditUserDto))] [JsonSerializable(typeof(RestErrorInfo))] -[JsonSerializable(typeof(EmailConfirmedRequestDto))] [JsonSerializable(typeof(SendConfirmationEmailRequestDto))] +[JsonSerializable(typeof(ConfirmEmailRequestDto))] [JsonSerializable(typeof(SendResetPasswordEmailRequestDto))] [JsonSerializable(typeof(ResetPasswordRequestDto))] public partial class AppJsonContext : JsonSerializerContext diff --git a/src/Bit.TemplatePlayground.Shared/Dtos/Identity/EmailConfirmedRequestDto.cs b/src/Bit.TemplatePlayground.Shared/Dtos/Identity/ConfirmEmailRequestDto.cs similarity index 69% rename from src/Bit.TemplatePlayground.Shared/Dtos/Identity/EmailConfirmedRequestDto.cs rename to src/Bit.TemplatePlayground.Shared/Dtos/Identity/ConfirmEmailRequestDto.cs index 3985f9d..28f5552 100644 --- a/src/Bit.TemplatePlayground.Shared/Dtos/Identity/EmailConfirmedRequestDto.cs +++ b/src/Bit.TemplatePlayground.Shared/Dtos/Identity/ConfirmEmailRequestDto.cs @@ -2,10 +2,13 @@ namespace Bit.TemplatePlayground.Shared.Dtos.Identity; [DtoResourceType(typeof(AppStrings))] -public class EmailConfirmedRequestDto +public class ConfirmEmailRequestDto { [Required(ErrorMessage = nameof(AppStrings.RequiredAttribute_ValidationError))] [EmailAddress(ErrorMessage = nameof(AppStrings.EmailAddressAttribute_ValidationError))] [Display(Name = nameof(AppStrings.Email))] public string? Email { get; set; } + + [Required(ErrorMessage = nameof(AppStrings.RequiredAttribute_ValidationError))] + public string? Token { get; set; } } diff --git a/src/Bit.TemplatePlayground.Shared/Dtos/PagedResultDto.cs b/src/Bit.TemplatePlayground.Shared/Dtos/PagedResultDto.cs index 2d486ca..6509262 100644 --- a/src/Bit.TemplatePlayground.Shared/Dtos/PagedResultDto.cs +++ b/src/Bit.TemplatePlayground.Shared/Dtos/PagedResultDto.cs @@ -2,18 +2,14 @@ public class PagedResult { - public IAsyncEnumerable? Items { get; set; } + public T[] Items { get; set; } = []; public long TotalCount { get; set; } - public PagedResult(IAsyncEnumerable items, long totalCount) + [JsonConstructor] + public PagedResult(T[] items, long totalCount) { Items = items; TotalCount = totalCount; } - - public PagedResult() - { - - } } diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Bit.TemplatePlayground.Client.Core.csproj b/src/Client/Bit.TemplatePlayground.Client.Core/Bit.TemplatePlayground.Client.Core.csproj index 638750f..70282b4 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Bit.TemplatePlayground.Client.Core.csproj +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Bit.TemplatePlayground.Client.Core.csproj @@ -16,15 +16,16 @@ - - - - - + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -38,6 +39,7 @@ + diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/AppComponentBase.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Components/AppComponentBase.cs index 8f72aed..72e8653 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/AppComponentBase.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/AppComponentBase.cs @@ -1,4 +1,6 @@ -namespace Bit.TemplatePlayground.Client.Core.Components; +using System.Text.Json; + +namespace Bit.TemplatePlayground.Client.Core.Components; public partial class AppComponentBase : ComponentBase, IDisposable { @@ -8,6 +10,8 @@ public partial class AppComponentBase : ComponentBase, IDisposable [AutoInject] protected HttpClient HttpClient = default!; + [AutoInject] protected JsonSerializerOptions JsonSerializerOptions = default!; + /// /// /// diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/ConfirmMessageBox.razor b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/ConfirmMessageBox.razor index 53eae50..578813b 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/ConfirmMessageBox.razor +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/ConfirmMessageBox.razor @@ -1,6 +1,6 @@ @inherits AppComponentBase; - +
@title diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/ConfirmMessageBox.razor.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/ConfirmMessageBox.razor.cs index 9409862..a64eb9a 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/ConfirmMessageBox.razor.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/ConfirmMessageBox.razor.cs @@ -15,8 +15,6 @@ public async Task Show(string message, string title) await InvokeAsync(() => { - _ = JSRuntime.SetBodyOverflow(true); - isOpen = true; this.title = title; this.message = message; @@ -32,7 +30,6 @@ await InvokeAsync(() => public async Task Confirm(bool value) { isOpen = false; - await JSRuntime.SetBodyOverflow(false); tcs?.SetResult(value); } } diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/Footer.razor.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/Footer.razor.cs index 8da9c4f..fb92e35 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/Footer.razor.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/Footer.razor.cs @@ -2,6 +2,7 @@ public partial class Footer { + [AutoInject] private Cookie cookie = default!; [AutoInject] private BitThemeManager bitThemeManager = default!; [AutoInject] private IBitDeviceCoordinator bitDeviceCoordinator { get; set; } = default!; @@ -22,7 +23,13 @@ protected override Task OnInitAsync() private async Task OnCultureChanged() { - await JSRuntime.SetCookie(".AspNetCore.Culture", $"c={SelectedCulture}|uic={SelectedCulture}", expiresIn: 30 * 24 * 3600, rememberMe: true); + await cookie.Set(new ButilCookie + { + Name = ".AspNetCore.Culture", + Value = $"c={SelectedCulture}|uic={SelectedCulture}", + MaxAge = 30 * 24 * 3600, + Secure = BuildConfiguration.IsRelease() + }); await StorageService.SetItem("Culture", SelectedCulture, persistent: true); diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/Footer.razor.scss b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/Footer.razor.scss index 37e2be5..66ea92a 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/Footer.razor.scss +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/Footer.razor.scss @@ -24,20 +24,24 @@ min-height: rem2(54px); justify-content: center; flex-flow: column nowrap; - - @include lt-xl { - min-height: rem2(50px); - } } .footer-contact { font-size: rem2(14px); line-height: rem2(20px); + + @include sm { + font-size: rem2(12px); + } } .footer-copyright { font-size: rem2(12px); line-height: rem2(20px); + + @include sm { + font-size: rem2(10px); + } } .footer-social-lnk-grp { @@ -54,6 +58,11 @@ background-position: center; background-repeat: no-repeat; + @include sm { + width: rem2(30px); + height: rem2(30px); + } + svg path { fill: $bit-color-foreground-secondary; } @@ -65,14 +74,9 @@ ::deep { .culture-drp { - left: rem2(5px); - width: rem2(105px); + left: rem2(8px); + width: rem2(104px); position: absolute; - background-color: white; - - @include sm { - position: static; - } } } diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MainLayout.razor.scss b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MainLayout.razor.scss index 71491c4..1855711 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MainLayout.razor.scss +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MainLayout.razor.scss @@ -45,25 +45,13 @@ position: relative; text-align: center; align-items: center; - max-width: rem2(608px); + max-width: rem2(504px); border-radius: rem2(4px); justify-content: center; flex-flow: column nowrap; - padding: rem2(48px) rem2(5px); + padding: rem2(48px) rem2(16px); box-shadow: $bit-box-shadow-callout; background-color: $bit-color-background-primary; - - @include lg { - padding: rem2(48px) rem2(5px); - } - - @include md { - padding: rem2(48px) rem2(5px); - } - - @include sm { - padding: rem2(32px) rem2(14px); - } } .form-title { @@ -92,17 +80,9 @@ width: 100%; display: flex; text-align: start; - max-width: rem2(340px); + max-width: rem2(300px); flex-flow: column nowrap; margin-bottom: rem2(21px); - - @include lt-xl { - max-width: rem2(300px); - } - - @include sm { - max-width: 100%; - } } .form-input-error, diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MessageBox.razor b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MessageBox.razor index 2630a8b..fa38b9f 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MessageBox.razor +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MessageBox.razor @@ -1,6 +1,6 @@ @inherits AppComponentBase - +
@title diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MessageBox.razor.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MessageBox.razor.cs index 6df17c1..dc074e6 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MessageBox.razor.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/MessageBox.razor.cs @@ -11,7 +11,6 @@ public partial class MessageBox : IDisposable private async Task OnCloseClick() { isOpen = false; - await JSRuntime.SetBodyOverflow(false); tcs?.SetResult(null); tcs = null; } @@ -19,7 +18,6 @@ private async Task OnCloseClick() private async Task OnOkClick() { isOpen = false; - await JSRuntime.SetBodyOverflow(false); tcs?.SetResult(null); tcs = null; } @@ -44,8 +42,6 @@ private async Task ShowMessageBox(string message, string title = "") { await InvokeAsync(() => { - _ = JSRuntime.SetBodyOverflow(true); - isOpen = true; this.title = title; body = message; diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor index 51350d8..8d7212d 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor @@ -26,7 +26,7 @@ + OnItemClick="(BitNavItem item) => HandleNavItemClick(item)"> diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor.cs index 99a0f4a..6cb86cd 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor.cs @@ -103,6 +103,13 @@ private async Task GoToEditProfile() navManager.NavigateTo("edit-profile"); } + private async Task HandleNavItemClick(BitNavItem item) + { + if (string.IsNullOrEmpty(item.Url)) return; + + await CloseMenu(); + } + private async Task CloseMenu() { IsMenuOpen = false; diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor.scss b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor.scss index 234a0f2..dc7eac7 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor.scss +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/NavMenu.razor.scss @@ -6,9 +6,12 @@ .main-container { left: 0; z-index: 16; + height: 100%; display: flex; position: fixed; min-height: 100%; + max-height: 100vh; + overflow: hidden auto; flex-flow: column nowrap; width: rem2($navMenuWidth); justify-content: flex-start; @@ -31,7 +34,7 @@ .top-container { width: 100%; display: flex; - padding: rem2(18px) 0; + padding: rem2(16px); flex-flow: column nowrap; margin-bottom: rem2(20px); justify-content: flex-start; diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/SignOutConfirmModal.razor b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/SignOutConfirmModal.razor index 206748c..44fce6c 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/SignOutConfirmModal.razor +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Layout/SignOutConfirmModal.razor @@ -1,6 +1,6 @@ @inherits AppComponentBase - + diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Categories/CategoriesPage.razor.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Categories/CategoriesPage.razor.cs index 39942b6..70cd8ae 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Categories/CategoriesPage.razor.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Categories/CategoriesPage.razor.cs @@ -61,7 +61,7 @@ private void PrepareGridDataProvider() var data = await categoryController.GetCategories(CurrentCancellationToken); - return BitDataGridItemsProviderResult.From(await data.Items!.ToListAsync(CurrentCancellationToken)!, (int)data.TotalCount); + return BitDataGridItemsProviderResult.From(data.Items!, (int)data.TotalCount); } catch (Exception exp) { diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Categories/CategoriesPage.razor.scss b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Categories/CategoriesPage.razor.scss index 9466d0a..a7af112 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Categories/CategoriesPage.razor.scss +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Categories/CategoriesPage.razor.scss @@ -41,9 +41,12 @@ } } +.grid-container { + overflow: auto; +} + .grid { width: 100%; - overflow: auto; display: inline-flex; flex-direction: column; border-radius: rem2(2px); @@ -83,6 +86,7 @@ ::deep td { font-weight: 400; + white-space: nowrap; font-size: rem2(12px); line-height: rem2(16px); border-top: rem2(1px) solid $bit-color-border-secondary; @@ -127,9 +131,10 @@ ::deep .bitdatagrid-paginator { margin-top: 0; - height: rem2(43px); + overflow: auto; padding: 0 rem2(12px); font-size: rem2(14px); + min-height: rem2(43px); border-top: rem2(1px) solid $bit-color-border-secondary; } diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/DeleteAccountConfirmModal.razor b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/DeleteAccountConfirmModal.razor index 82d83f6..1328ef1 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/DeleteAccountConfirmModal.razor +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/DeleteAccountConfirmModal.razor @@ -1,6 +1,6 @@ @inherits AppComponentBase - + -
+
@Localizer[nameof(AppStrings.TermsMessage)] @Localizer[nameof(AppStrings.TermsTitle)] diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/SignUpPage.razor.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/SignUpPage.razor.cs index 5144961..34fc5be 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/SignUpPage.razor.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/SignUpPage.razor.cs @@ -13,16 +13,6 @@ public partial class SignUpPage private BitMessageBarType signUpMessageType; private SignUpRequestDto signUpModel = new(); - protected override async Task OnAfterFirstRenderAsync() - { - await base.OnAfterFirstRenderAsync(); - - if ((await AuthenticationStateTask).User.IsAuthenticated()) - { - NavigationManager.NavigateTo("/"); - } - } - private async Task DoSignUp() { if (isLoading) return; diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/SignUpPage.razor.scss b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/SignUpPage.razor.scss index 5167bad..d1fd11d 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/SignUpPage.razor.scss +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Identity/SignUpPage.razor.scss @@ -8,15 +8,6 @@ align-items: center; justify-content: center; flex-flow: column nowrap; - padding: rem2(56px) rem2(16px); - - @include lg { - padding: rem2(48px) rem2(16px); - } - - @include sm { - padding: rem2(40px) rem2(16px); - } } .form-description { @@ -25,27 +16,3 @@ font-size: rem2(14px); max-width: rem2(432px); } - -::deep { - .form-checkbox { - width: 100%; - max-width: rem2(340px); - - .label { - text-align: start; - align-items: start; - } - - @include lt-xl { - max-width: rem2(300px); - } - - @include sm { - max-width: 100%; - } - } - - .form-input-container--no-margin { - margin-bottom: 0; - } -} diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/AddOrEditProductModal.razor b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/AddOrEditProductModal.razor index b75d167..6425d35 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/AddOrEditProductModal.razor +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/AddOrEditProductModal.razor @@ -1,6 +1,6 @@ @inherits AppComponentBase - +
diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/AddOrEditProductModal.razor.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/AddOrEditProductModal.razor.cs index b74e270..5e231e2 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/AddOrEditProductModal.razor.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/AddOrEditProductModal.razor.cs @@ -27,8 +27,6 @@ public async Task ShowModal(ProductDto productToShow) { await InvokeAsync(() => { - _ = JSRuntime.SetBodyOverflow(true); - isOpen = true; product = productToShow; selectedCategoyId = (product.CategoryId ?? 0).ToString(); @@ -76,8 +74,6 @@ private async Task Save() } isOpen = false; - - await JSRuntime.SetBodyOverflow(false); } finally { @@ -90,7 +86,5 @@ private async Task Save() private async Task OnCloseClick() { isOpen = false; - - await JSRuntime.SetBodyOverflow(false); } } diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor index 3adda7e..82c54bb 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor @@ -18,23 +18,25 @@
- - - - - - - - - - - - - - +
+ + + + + + + + + + + + + + +
diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor.cs index 4b364a9..3677397 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor.cs @@ -61,7 +61,7 @@ private void PrepareGridDataProvider() var data = await productController.GetProducts(CurrentCancellationToken); - return BitDataGridItemsProviderResult.From(await data!.Items!.ToListAsync(), (int)data!.TotalCount); + return BitDataGridItemsProviderResult.From(data!.Items!, (int)data!.TotalCount); } catch (Exception exp) { diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor.scss b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor.scss index 24479a9..ee65eb6 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor.scss +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Components/Pages/Products/ProductsPage.razor.scss @@ -41,9 +41,12 @@ } } +.grid-container { + overflow: auto; +} + .grid { width: 100%; - overflow: auto; display: inline-flex; flex-direction: column; border-radius: rem2(2px); @@ -83,6 +86,7 @@ ::deep td { font-weight: 400; + white-space: nowrap; font-size: rem2(12px); line-height: rem2(16px); border-top: rem2(1px) solid $bit-color-border-secondary; @@ -127,8 +131,9 @@ ::deep .bitdatagrid-paginator { margin-top: 0; - height: rem2(43px); + overflow: auto; padding: 0 rem2(12px); font-size: rem2(14px); + min-height: rem2(43px); border-top: rem2(1px) solid $bit-color-border-secondary; } diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Controllers/Identity/IIdentityController.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Controllers/Identity/IIdentityController.cs index 879de11..733b635 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Controllers/Identity/IIdentityController.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Controllers/Identity/IIdentityController.cs @@ -14,6 +14,9 @@ public interface IIdentityController : IAppController [HttpPost] Task SendResetPasswordEmail(SendResetPasswordEmailRequestDto body, CancellationToken cancellationToken = default); + [HttpPost] + Task ConfirmEmail(ConfirmEmailRequestDto body); + [HttpPost] Task ResetPassword(ResetPasswordRequestDto body, CancellationToken cancellationToken = default); diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Extensions/IJSRuntimeExtensions.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Extensions/IJSRuntimeExtensions.cs index a7b92f7..49c6aa4 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Extensions/IJSRuntimeExtensions.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Extensions/IJSRuntimeExtensions.cs @@ -2,33 +2,8 @@ public static class IJSRuntimeExtensions { - /// - /// To disable the scrollbar of the body when showing the modal, so the modal can be always shown in the viewport without being scrolled out. - /// - public static async Task SetBodyOverflow(this IJSRuntime jsRuntime, bool hidden) - { - await jsRuntime.InvokeVoidAsync("App.setBodyOverflow", hidden); - } - - public static async Task GoBack(this IJSRuntime jsRuntime) - { - await jsRuntime.InvokeVoidAsync("App.goBack"); - } - public static async Task ApplyBodyElementClasses(this IJSRuntime jsRuntime, List cssClasses, Dictionary cssVariables) { await jsRuntime.InvokeVoidAsync("App.applyBodyElementClasses", cssClasses, cssVariables); } - - public static async Task SetCookie(this IJSRuntime jsRuntime, string key, string value, long expiresIn, bool rememberMe) - { - bool secure = BuildConfiguration.IsRelease(); - - await jsRuntime.InvokeVoidAsync("App.setCookie", key, value, expiresIn, rememberMe, secure); - } - - public static async Task RemoveCookie(this IJSRuntime jsRuntime, string key) - { - await jsRuntime.InvokeVoidAsync("App.removeCookie", key); - } } diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Extensions/IServiceCollectionExtensions.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Extensions/IServiceCollectionExtensions.cs index 9e66a74..5ae1331 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Extensions/IServiceCollectionExtensions.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Extensions/IServiceCollectionExtensions.cs @@ -30,6 +30,7 @@ public static IServiceCollection AddClientSharedServices(this IServiceCollection services.TryAddTransient(sp => AppJsonContext.Default.Options); services.AddTypedHttpClients(); + services.AddBitButilServices(); services.AddBitBlazorUIServices(); services.AddSharedServices(); diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Routes.razor.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Routes.razor.cs index 5e98773..73744ba 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Routes.razor.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Routes.razor.cs @@ -56,4 +56,20 @@ private async Task SetupBodyClasses() cssVariables.Add("--bit-status-bar-height", $"{statusBarHeight.ToString("F3", CultureInfo.InvariantCulture)}px"); await jsRuntime.ApplyBodyElementClasses(cssClasses, cssVariables); } + + [AutoInject] NavigationManager? navigationManager { set => universalLinksNavigationManager = value; get => universalLinksNavigationManager; } + public static NavigationManager? universalLinksNavigationManager; + + public static async Task OpenUniversalLink(string url) + { + await Task.Run(async () => + { + while (universalLinksNavigationManager is null) + { + await Task.Yield(); + } + + universalLinksNavigationManager.NavigateTo(url); + }); + } } diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Scripts/app.ts b/src/Client/Bit.TemplatePlayground.Client.Core/Scripts/app.ts index b03d3ba..3061e1b 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Scripts/app.ts +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Scripts/app.ts @@ -1,32 +1,4 @@ class App { - public static setCookie(name: string, value: string, seconds: number, remeber: boolean, secure: boolean) { - const date = new Date(); - date.setSeconds(date.getSeconds() + seconds); - let cookie = `${name}=${value};path=/;samesite=strict;`; - if (remeber == true) { - cookie = cookie += `expires=${date.toUTCString()};`; - } - if (secure == true) { - cookie = `${cookie};secure`; - } - document.cookie = cookie; - } - - public static removeCookie(name: string): void { - document.cookie = `${name}=; Max-Age=0`; - } - - public static goBack(): void { - window.history.back(); - } - - /** - * To disable the scrollbar of the body when showing the modal, so the modal can be always shown in the viewport without being scrolled out. - **/ - public static setBodyOverflow(hidden: boolean) { - document.body.style.overflow = hidden ? "hidden" : "auto"; - } - public static applyBodyElementClasses(cssClasses: string[], cssVariables: any): void { cssClasses?.forEach(c => document.body.classList.add(c)); Object.keys(cssVariables).forEach(key => document.body.style.setProperty(key, cssVariables[key])); diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Services/AppRenderMode.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Services/AppRenderMode.cs index 6567376..53fba8c 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Services/AppRenderMode.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Services/AppRenderMode.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Components.Web; +using Microsoft.AspNetCore.Components.Web; namespace Bit.TemplatePlayground.Client.Core.Services; @@ -15,10 +15,18 @@ public static class AppRenderMode BuildConfiguration.IsDebug() ? BlazorServer /*For better development experience*/ : Auto; public static bool PwaEnabled { get; } = +#if PwaEnabled + true; +#else false; +#endif public static bool MultilingualEnabled { get; } = +#if MultilingualEnabled + true; +#else false; +#endif /// /// Is running under .NET MAUI? diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Services/AuthenticationManager.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Services/AuthenticationManager.cs index de88822..b1c1a83 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Services/AuthenticationManager.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Services/AuthenticationManager.cs @@ -7,9 +7,9 @@ namespace Bit.TemplatePlayground.Client.Core.Services; public partial class AuthenticationManager : AuthenticationStateProvider { + [AutoInject] private Cookie cookie = default!; [AutoInject] private IAuthTokenProvider tokenProvider = default!; [AutoInject] private IStorageService storageService = default!; - [AutoInject] private IJSRuntime jsRuntime = default!; [AutoInject] private IIdentityController identityController = default; [AutoInject] private IStringLocalizer localizer = default!; [AutoInject] private JsonSerializerOptions jsonSerializerOptions = default!; @@ -29,7 +29,7 @@ public async Task SignOut() await storageService.RemoveItem("refresh_token"); if (AppRenderMode.PrerenderEnabled && AppRenderMode.IsBlazorHybrid is false) { - await jsRuntime.RemoveCookie("access_token"); + await cookie.Remove("access_token"); } NotifyAuthenticationStateChanged(Task.FromResult(await GetAuthenticationStateAsync())); } @@ -38,7 +38,7 @@ public async Task RefreshToken() { if (AppRenderMode.PrerenderEnabled && AppRenderMode.IsBlazorHybrid is false) { - await jsRuntime.RemoveCookie("access_token"); + await cookie.Remove("access_token"); } await storageService.RemoveItem("access_token"); NotifyAuthenticationStateChanged(Task.FromResult(await GetAuthenticationStateAsync())); @@ -92,7 +92,12 @@ private async Task StoreToken(TokenResponseDto tokenResponseDto, bool? rememberM await storageService.SetItem("refresh_token", tokenResponseDto!.RefreshToken, rememberMe is true); if (AppRenderMode.PrerenderEnabled && AppRenderMode.IsBlazorHybrid is false) { - await jsRuntime.SetCookie("access_token", tokenResponseDto.AccessToken!, tokenResponseDto.ExpiresIn, rememberMe is true); + await cookie.Set(new ButilCookie + { + Name = "access_token", + Value = tokenResponseDto.AccessToken, + MaxAge = tokenResponseDto.ExpiresIn + }); } } diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Services/ExceptionHandlerBase.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Services/ExceptionHandlerBase.cs index 83afabd..39af190 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Services/ExceptionHandlerBase.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Services/ExceptionHandlerBase.cs @@ -16,7 +16,7 @@ public virtual void Handle(Exception exception, IDictionary? pa if (isDebug) { - _ = Console.Out.WriteLineAsync(exceptionMessage); + _ = System.Console.Out.WriteLineAsync(exceptionMessage); Debugger.Break(); } diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Services/PrerenderStateService.cs b/src/Client/Bit.TemplatePlayground.Client.Core/Services/PrerenderStateService.cs index b8afd9e..047e31d 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Services/PrerenderStateService.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Services/PrerenderStateService.cs @@ -23,7 +23,7 @@ public PrerenderStateService(PersistentComponentState? persistentComponentState [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "") { - if (AppRenderMode.PrerenderEnabled is false) + if (AppRenderMode.PrerenderEnabled is false || AppRenderMode.IsBlazorHybrid) return await factory(); string key = $"{filePath.Split('\\').LastOrDefault()} {memberName} {lineNumber}"; @@ -33,7 +33,7 @@ public PrerenderStateService(PersistentComponentState? persistentComponentState public async Task GetValue(string key, Func> factory) { - if (AppRenderMode.PrerenderEnabled is false) + if (AppRenderMode.PrerenderEnabled is false || AppRenderMode.IsBlazorHybrid) return await factory(); if (persistentComponentState!.TryTakeFromJson(key, out T? value)) return value; @@ -45,7 +45,7 @@ public PrerenderStateService(PersistentComponentState? persistentComponentState void Persist(string key, T value) { - if (AppRenderMode.PrerenderEnabled is false) + if (AppRenderMode.PrerenderEnabled is false || AppRenderMode.IsBlazorHybrid) return; values.TryRemove(key, out object? _); @@ -62,7 +62,7 @@ async Task PersistAsJson() public async ValueTask DisposeAsync() { - if (AppRenderMode.PrerenderEnabled is false) + if (AppRenderMode.PrerenderEnabled is false || AppRenderMode.IsBlazorHybrid) return; subscription?.Dispose(); diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Styles/abstracts/_media-queries.scss b/src/Client/Bit.TemplatePlayground.Client.Core/Styles/abstracts/_media-queries.scss index 9662a3b..7abd9a8 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Styles/abstracts/_media-queries.scss +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Styles/abstracts/_media-queries.scss @@ -3,16 +3,16 @@ /// https://github.com/Necromancerx/media-queries-scss-mixins // media aliases and breakpoints -$screen-xl-min: rem2(1441px); +$screen-xl-min: rem2(1920px); $screen-xl-max: rem2(5000px); -$screen-lg-min: rem2(835px); -$screen-lg-max: rem2(1440px); +$screen-lg-min: rem2(1280px); +$screen-lg-max: rem2(1919px); -$screen-md-min: rem2(361px); -$screen-md-max: rem2(834px); +$screen-md-min: rem2(769px); +$screen-md-max: rem2(1279px); -$screen-sm-max: rem2(360px); +$screen-sm-max: rem2(768px); // media devices @mixin sm { diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/Styles/app.scss b/src/Client/Bit.TemplatePlayground.Client.Core/Styles/app.scss index f45a2ac..ad16ef7 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/Styles/app.scss +++ b/src/Client/Bit.TemplatePlayground.Client.Core/Styles/app.scss @@ -4,22 +4,18 @@ * { box-sizing: border-box; + font-family: "Segoe UI"; -webkit-text-size-adjust: none; + -webkit-font-smoothing: antialiased; -webkit-tap-highlight-color: transparent; - font-family: "Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif; -} - -.bit-blazor-hybrid { - *:not(input) { - -webkit-user-select: none; - user-select: none; - } } -.bit-blazor-hybrid { - &.bit-windows * { - -webkit-user-drag: none; - } +html, body, #app-container { + margin: 0; + padding: 0; + width: 100%; + height: 100%; + scroll-behavior: smooth; } h1, h2, h3, h4, h5 { @@ -30,10 +26,13 @@ p { margin: 0; } -html, body, #app-container { - margin: 0; - padding: 0; - width: 100%; - height: 100%; - -webkit-font-smoothing: antialiased; +.bit-blazor-hybrid { + *:not(input) { + -webkit-user-select: none; + user-select: none; + } + + &.bit-windows * { + -webkit-user-drag: none; + } } diff --git a/src/Client/Bit.TemplatePlayground.Client.Core/_Imports.razor b/src/Client/Bit.TemplatePlayground.Client.Core/_Imports.razor index be7e16d..02709ed 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Core/_Imports.razor +++ b/src/Client/Bit.TemplatePlayground.Client.Core/_Imports.razor @@ -11,6 +11,7 @@ @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Web.Virtualization +@using Bit.Butil @using Bit.BlazorUI @using Bit.TemplatePlayground @using Bit.TemplatePlayground.Shared.Enums diff --git a/src/Client/Bit.TemplatePlayground.Client.Maui/Bit.TemplatePlayground.Client.Maui.csproj b/src/Client/Bit.TemplatePlayground.Client.Maui/Bit.TemplatePlayground.Client.Maui.csproj index f3d9c8c..b7c7c2d 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Maui/Bit.TemplatePlayground.Client.Maui.csproj +++ b/src/Client/Bit.TemplatePlayground.Client.Maui/Bit.TemplatePlayground.Client.Maui.csproj @@ -16,7 +16,7 @@ com.bitplatform.BP.Template - 032F62D0-988C-4308-80C1-FC0D44F96B79 + 288A1F2E-962A-4822-979A-49BBCD49BDEF 1.0 @@ -39,8 +39,8 @@ true True - all - + all + @@ -64,7 +64,7 @@ - + @@ -82,11 +82,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Client/Bit.TemplatePlayground.Client.Maui/MauiProgram.cs b/src/Client/Bit.TemplatePlayground.Client.Maui/MauiProgram.cs index 5d662bc..ee8eb2a 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Maui/MauiProgram.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Maui/MauiProgram.cs @@ -1,6 +1,5 @@ - -using System.Reflection; -using Bit.TemplatePlayground.Client.Maui.Services; +using Bit.TemplatePlayground.Client.Core; +using Microsoft.Maui.LifecycleEvents; namespace Bit.TemplatePlayground.Client.Maui; @@ -39,6 +38,44 @@ public static MauiApp CreateMauiApp() services.AddClientMauiServices(); + builder.ConfigureLifecycleEvents(lifecycle => + { +#if iOS || Mac + lifecycle.AddiOS(ios => + { + bool HandleAppLink(Foundation.NSUserActivity? userActivity) + { + if (userActivity is not null && userActivity.ActivityType == Foundation.NSUserActivityType.BrowsingWeb && userActivity.WebPageUrl is not null) + { + var url = $"{userActivity.WebPageUrl.Path}?{userActivity.WebPageUrl.Query}"; + + var _ = Routes.OpenUniversalLink(url); + + return true; + } + + return false; + } + + ios.FinishedLaunching((app, data) + => HandleAppLink(app.UserActivity)); + + ios.ContinueUserActivity((app, userActivity, handler) + => HandleAppLink(userActivity)); + + if (OperatingSystem.IsIOSVersionAtLeast(13) || OperatingSystem.IsMacCatalystVersionAtLeast(13)) + { + ios.SceneWillConnect((scene, sceneSession, sceneConnectionOptions) + => HandleAppLink(sceneConnectionOptions.UserActivities.ToArray() + .FirstOrDefault(a => a.ActivityType == Foundation.NSUserActivityType.BrowsingWeb))); + + ios.SceneContinueUserActivity((scene, userActivity) + => HandleAppLink(userActivity)); + } + }); +#endif + }); + var mauiApp = builder.Build(); return mauiApp; diff --git a/src/Client/Bit.TemplatePlayground.Client.Maui/Platforms/Android/MainActivity.cs b/src/Client/Bit.TemplatePlayground.Client.Maui/Platforms/Android/MainActivity.cs index 68f7b96..ed2d636 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Maui/Platforms/Android/MainActivity.cs +++ b/src/Client/Bit.TemplatePlayground.Client.Maui/Platforms/Android/MainActivity.cs @@ -1,10 +1,43 @@ using Android.App; +using Android.Content; using Android.Content.PM; +using Android.OS; +using Bit.TemplatePlayground.Client.Core; +using Java.Net; namespace Bit.TemplatePlayground.Client.Maui.Platforms.Android; -[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, +[IntentFilter([Intent.ActionView], + DataScheme = "https", + DataHost = "bp.bitplatform.dev", + DataPathPrefix = "/", + AutoVerify = true, + Categories = [Intent.ActionView, Intent.CategoryDefault, Intent.CategoryBrowsable])] + +[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleInstance, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] public class MainActivity : MauiAppCompatActivity { + protected override void OnCreate(Bundle? savedInstanceState) + { + base.OnCreate(savedInstanceState); + + var url = Intent?.DataString; + if (string.IsNullOrWhiteSpace(url) is false) + { + var _ = Routes.OpenUniversalLink(new URL(url).File ?? "/"); + } + } + + protected override void OnNewIntent(Intent? intent) + { + base.OnNewIntent(intent); + + var action = intent!.Action; + var url = intent.DataString; + if (action is Intent.ActionView && string.IsNullOrWhiteSpace(url) is false) + { + var _ = Routes.OpenUniversalLink(new URL(url).File ?? "/"); + } + } } diff --git a/src/Client/Bit.TemplatePlayground.Client.Maui/Platforms/iOS/Entitlements.plist b/src/Client/Bit.TemplatePlayground.Client.Maui/Platforms/iOS/Entitlements.plist new file mode 100644 index 0000000..f0ee3ac --- /dev/null +++ b/src/Client/Bit.TemplatePlayground.Client.Maui/Platforms/iOS/Entitlements.plist @@ -0,0 +1,10 @@ + + + + + com.apple.developer.associated-domains + + applinks:bp.bitplatform.dev + + + diff --git a/src/Client/Bit.TemplatePlayground.Client.Maui/wwwroot/index.html b/src/Client/Bit.TemplatePlayground.Client.Maui/wwwroot/index.html index 9ea6bbb..f184474 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Maui/wwwroot/index.html +++ b/src/Client/Bit.TemplatePlayground.Client.Maui/wwwroot/index.html @@ -122,7 +122,8 @@
- + + diff --git a/src/Client/Bit.TemplatePlayground.Client.Web/Bit.TemplatePlayground.Client.Web.csproj b/src/Client/Bit.TemplatePlayground.Client.Web/Bit.TemplatePlayground.Client.Web.csproj index 8a5a24f..64812e0 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Web/Bit.TemplatePlayground.Client.Web.csproj +++ b/src/Client/Bit.TemplatePlayground.Client.Web/Bit.TemplatePlayground.Client.Web.csproj @@ -8,13 +8,13 @@ true true - true false service-worker-assets.js false true Default + true @@ -22,12 +22,12 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Client/Bit.TemplatePlayground.Client.Web/wwwroot/service-worker.published.js b/src/Client/Bit.TemplatePlayground.Client.Web/wwwroot/service-worker.published.js index d1a2446..cdec640 100644 --- a/src/Client/Bit.TemplatePlayground.Client.Web/wwwroot/service-worker.published.js +++ b/src/Client/Bit.TemplatePlayground.Client.Web/wwwroot/service-worker.published.js @@ -1,4 +1,4 @@ -// bit version: 8.5.0 +// bit version: 8.6.0 // https://github.com/bitfoundation/bitplatform/tree/develop/src/Bswup self.assetsInclude = []; diff --git a/src/Directory.Build.props b/src/Directory.Build.props index efbb93a..6d07a14 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,4 +1,4 @@ - + 12.0