diff --git a/src/Templates/BlazorWeb/Bit.BlazorWeb/.azure-devops/workflows/cd.yml b/src/Templates/BlazorWeb/Bit.BlazorWeb/.azure-devops/workflows/cd.yml index 469e56b680..acf0b68361 100644 --- a/src/Templates/BlazorWeb/Bit.BlazorWeb/.azure-devops/workflows/cd.yml +++ b/src/Templates/BlazorWeb/Bit.BlazorWeb/.azure-devops/workflows/cd.yml @@ -7,8 +7,8 @@ variables: APP_SERVICE_NAME: 'app-service-td-test' AZURE_SERVICE_CONNECTION: 'td-test-service-connection' # https://learn.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#azure-resource-manager-service-connection ConnectionStrings.SqlServerConnectionString: $(DB_CONNECTION_STRING) - AppSettings.JwtSettings.IdentityCertificatePassword: $(API_IDENTITY_CERTIFICATE_PASSWORD) - # ApiServerAddress: 'api/' + AppSettings.IdentitySettings.IdentityCertificatePassword: $(API_IDENTITY_CERTIFICATE_PASSWORD) + ApiServerAddress: 'api/' # // You can also use absolute urls such as https://todob.bitplatform.dev/api/ jobs: diff --git a/src/Templates/BlazorWeb/Bit.BlazorWeb/.github/workflows/cd.yml b/src/Templates/BlazorWeb/Bit.BlazorWeb/.github/workflows/cd.yml index f9b3680db7..47c4e6ed8e 100644 --- a/src/Templates/BlazorWeb/Bit.BlazorWeb/.github/workflows/cd.yml +++ b/src/Templates/BlazorWeb/Bit.BlazorWeb/.github/workflows/cd.yml @@ -33,6 +33,13 @@ jobs: with: node-version: 18 + - name: Update appsettings.json api server address + uses: microsoft/variable-substitution@v1 + with: + files: 'src/BlazorWeb.Client/appsettings.json' + env: + ApiServerAddress: ${{ env.API_SERVER_ADDRESS }} + - name: Install wasm run: cd src && dotnet workload install wasm-tools wasm-experimental @@ -84,7 +91,7 @@ jobs: files: 'appsettings.json' env: ConnectionStrings.SqlServerConnectionString: ${{ secrets.DB_CONNECTION_STRING }} - AppSettings.JwtSettings.IdentityCertificatePassword: ${{ secrets.API_IDENTITY_CERTIFICATE_PASSWORD }} + AppSettings.IdentitySettings.IdentityCertificatePassword: ${{ secrets.API_IDENTITY_CERTIFICATE_PASSWORD }} - name: Delete IdentityCertificate.pfx run: | diff --git a/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/BlazorWeb.Client.csproj b/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/BlazorWeb.Client.csproj index b2c860cfa6..62c1a63c0d 100644 --- a/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/BlazorWeb.Client.csproj +++ b/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/BlazorWeb.Client.csproj @@ -4,8 +4,6 @@ net8.0 - enable - enable true Default true diff --git a/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/IListExtensions.cs b/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/ICollectionExtensions.cs similarity index 59% rename from src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/IListExtensions.cs rename to src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/ICollectionExtensions.cs index 8f50eb4679..399d6b295f 100644 --- a/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/IListExtensions.cs +++ b/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/ICollectionExtensions.cs @@ -1,6 +1,6 @@ namespace System.Collections.Generic; -public static class IListExtensions +public static class ICollectionExtensions { // Basically a Polyfill since we now expose IList instead of List // which is better but IList doesn't have AddRange @@ -20,4 +20,14 @@ public static void AddRange(this IList list, IEnumerable items) list.Add(item); } } + + public static async Task> ToListAsync(this IAsyncEnumerable items, CancellationToken cancellationToken = default) + { + var results = new List(); + await foreach (var item in items.WithCancellation(cancellationToken)) + { + results.Add(item); + } + return results; + } } diff --git a/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/IJSRuntimeExtension.cs b/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/IJSRuntimeExtension.cs new file mode 100644 index 0000000000..1c78908da8 --- /dev/null +++ b/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/IJSRuntimeExtension.cs @@ -0,0 +1,73 @@ +using BlazorWeb.Shared.Dtos.Identity; + +namespace Microsoft.JSInterop; + +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) + { + await jsRuntime.InvokeVoidAsync("App.setCookie", key, value, expiresIn, rememberMe); + } + + public static async Task RemoveCookie(this IJSRuntime jsRuntime, string key) + { + await jsRuntime.InvokeVoidAsync("App.removeCookie", key); + } + + public static async Task GetCookie(this IJSRuntime jsRuntime, string key) + { + return await jsRuntime.InvokeAsync("App.getCookie", key); + } + + public static async Task SetLocalStorage(this IJSRuntime jsRuntime, string key, string value, bool rememberMe) + { + await jsRuntime.InvokeVoidAsync($"window.{(rememberMe ? "localStorage" : "sessionStorage")}.setItem", key, value); + } + + public static async Task RemoveLocalStorage(this IJSRuntime jsRuntime, string key) + { + await jsRuntime.InvokeVoidAsync("window.sessionStorage.removeItem", key); + await jsRuntime.InvokeVoidAsync("window.localStorage.removeItem", key); + } + + public static async Task GetLocalStorage(this IJSRuntime jsRuntime, string key) + { + return (await jsRuntime.InvokeAsync("window.localStorage.getItem", key)) ?? + (await jsRuntime.InvokeAsync("window.sessionStorage.getItem", key)); + } + + public static async Task StoreAuthToken(this IJSRuntime jsRuntime, TokenResponseDto tokenResponse, bool? rememberMe = null) + { + if (rememberMe is null) + { + rememberMe = string.IsNullOrEmpty(await jsRuntime.InvokeAsync("window.localStorage.getItem", "refresh_token")) is false; + } + + await jsRuntime.SetCookie("access_token", tokenResponse.AccessToken!, tokenResponse.ExpiresIn, rememberMe is true); + await jsRuntime.SetLocalStorage("refresh_token", tokenResponse.RefreshToken!, rememberMe is true); + } + + public static async Task RemoveAuthTokens(this IJSRuntime jsRuntime) + { + await jsRuntime.RemoveCookie("access_token"); + await jsRuntime.RemoveLocalStorage("refresh_token"); + } +} diff --git a/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/IServiceCollectionExtensions.cs b/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/IServiceCollectionExtensions.cs index 1ccfa701d8..db230b04e9 100644 --- a/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/IServiceCollectionExtensions.cs +++ b/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/IServiceCollectionExtensions.cs @@ -1,5 +1,6 @@ //-:cnd:noEmit using BlazorWeb.Client.Services.HttpMessageHandlers; +using Microsoft.AspNetCore.Components.WebAssembly.Services; namespace Microsoft.Extensions.DependencyInjection; @@ -9,23 +10,23 @@ public static IServiceCollection AddClientSharedServices(this IServiceCollection { services.AddSharedServices(); - services.AddCascadingAuthenticationState(); - services.AddScoped(); - services.AddScoped(); + services.AddTransient(); + services.AddTransient(); services.AddScoped(); services.AddBitBlazorUIServices(); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddScoped(); - services.AddScoped(); services.AddScoped(sp => (AppAuthenticationStateProvider)sp.GetRequiredService()); - services.AddScoped(); + services.AddTransient(); + + services.AddTransient(); return services; } diff --git a/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/JsRuntimeExtension.cs b/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/JsRuntimeExtension.cs deleted file mode 100644 index a279c37811..0000000000 --- a/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Extensions/JsRuntimeExtension.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Microsoft.JSInterop; - -public static class JSRuntimeExtension -{ - /// - /// 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); - } -} diff --git a/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Pages/Categories/AddOrEditCategoryPage.razor b/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Pages/Categories/AddOrEditCategoryPage.razor index 7f950be30a..741e223d42 100644 --- a/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Pages/Categories/AddOrEditCategoryPage.razor +++ b/src/Templates/BlazorWeb/Bit.BlazorWeb/src/BlazorWeb.Client/Pages/Categories/AddOrEditCategoryPage.razor @@ -54,8 +54,8 @@
@Localizer[nameof(AppStrings.Color)] -
- @foreach (var color in new[] { "#FFCD56", "#FF6384", "#4BC0C0", "#FF9124", "#2B88D8", "#C7E0F4" }) +
+ @foreach (var color in new[] { "#FFCD56", "#FF6384", "#4BC0C0", "#FF9124", "#2B88D8", "#C7E0F4" }) {