diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 8253b732df..8ca147a3db 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -1430,6 +1430,10 @@ "text": "LeptonX Lite", "path": "ui-themes/lepton-x-lite/blazor.md" }, + { + "text": "LeptonX", + "path": "ui-themes/lepton-x/blazor.md" + }, { "text": "Branding", "path": "framework/ui/blazor/branding.md" @@ -1751,6 +1755,10 @@ { "text": "LeptonX Lite", "path": "ui-themes/lepton-x-lite/angular.md" + }, + { + "text": "LeptonX", + "path": "ui-themes/lepton-x/angular.md" } ] }, diff --git a/docs/en/framework/ui/blazor/overall.md b/docs/en/framework/ui/blazor/overall.md index 12cef14552..54a545759e 100644 --- a/docs/en/framework/ui/blazor/overall.md +++ b/docs/en/framework/ui/blazor/overall.md @@ -1,14 +1,17 @@ # Blazor UI: Overall -## Introduction +[Blazor](https://docs.microsoft.com/en-us/aspnet/core/blazor/) is a framework for building interactive client-side web UI with .NET. It enables .NET developers to create Single-Page Web Applications using C# and the Razor syntax. -[Blazor](https://docs.microsoft.com/en-us/aspnet/core/blazor/) is a framework for building interactive client-side web UI with .NET. It is promising for a .NET developer that you can create Single-Page Web Applications using C# and the Razor syntax. +ABP provides comprehensive infrastructure and integrations that make your Blazor development easier, comfortable and enjoyable. ABP supports multiple Blazor hosting models: -ABP provides infrastructure and integrations that make your Blazor development even easier, comfortable and enjoyable. +* **Blazor WebAssembly (WASM)**: Client-side hosting model where the entire application runs in the browser using WebAssembly +* **Blazor Server**: Server-side hosting model with a real-time SignalR connection +* **Blazor WebApp**: The new hybrid/united model introduced in .NET 8 combining the benefits of Server and WebAssembly approaches +* **MAUI Blazor**: For building cross-platform native applications using Blazor & MAUI -This document provides an overview for the ABP Blazor UI integration and highlights some major features. +This document provides an overview of the ABP Blazor UI integration and highlights some major features. -### Getting Started +## Getting Started You can follow the documents below to start with the ABP and the Blazor UI now: @@ -94,7 +97,7 @@ These libraries are selected as the base libraries and available to the applicat > Bootstrap's JavaScript part is not used since the Blazorise library already provides the necessary functionalities to the Bootstrap components in a native way. -> Beginning from June, 2021, the Blazorise library has dual licenses; open source & commercial. Based on your yearly revenue, you may need to buy a commercial license. See [this post](https://blazorise.com/news/announcing-2022-blazorise-plans-and-pricing-updates) to learn more. The Blazorise license is bundled with ABP and commercial customers doesn’t need to buy an extra Blazorise license. +> Beginning from June, 2021, the Blazorise library has dual licenses; open source & commercial. Based on your yearly revenue, you may need to buy a commercial license. See [this post](https://blazorise.com/news/announcing-2022-blazorise-plans-and-pricing-updates) to learn more. The Blazorise license is bundled with ABP and commercial customers doesn't need to buy an extra Blazorise license. ### The Layout diff --git a/docs/en/framework/ui/blazor/theming.md b/docs/en/framework/ui/blazor/theming.md index 0c7d6f8406..9a056580bb 100644 --- a/docs/en/framework/ui/blazor/theming.md +++ b/docs/en/framework/ui/blazor/theming.md @@ -27,7 +27,7 @@ Currently, three themes are **officially provided**: * The [Basic Theme](basic-theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**. * The [Lepton Theme](https://abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP](https://abp.io/) license. -* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has a [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/blazor) and a [lite](../../../ui-themes/lepton-x-lite/blazor.md) version. +* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has a [commercial](../../../ui-themes/lepton-x/blazor.md) and a [lite](../../../ui-themes/lepton-x-lite/blazor.md) version. ## Overall diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs index f17f74b602..8da3237f83 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs @@ -69,6 +69,7 @@ public interface IIdentityUserRepository : IBasicRepository bool includeDetails = false, Guid? roleId = null, Guid? organizationUnitId = null, + Guid? id = null, string userName = null, string phoneNumber = null, string emailAddress = null, @@ -114,6 +115,7 @@ public interface IIdentityUserRepository : IBasicRepository string filter = null, Guid? roleId = null, Guid? organizationUnitId = null, + Guid? id = null, string userName = null, string phoneNumber = null, string emailAddress = null, diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs index 86682b85db..a623894625 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs @@ -62,35 +62,35 @@ public class EfCoreIdentityUserRepository : EfCoreRepository() - join role in dbContext.Roles on userRole.RoleId equals role.Id - where userIds.Contains(userRole.UserId) - group new - { - userRole.UserId, - role.Name - } by userRole.UserId + join role in dbContext.Roles on userRole.RoleId equals role.Id + where userIds.Contains(userRole.UserId) + group new { + userRole.UserId, + role.Name + } by userRole.UserId into gp - select new IdentityUserIdWithRoleNames - { - Id = gp.Key, RoleNames = gp.Select(x => x.Name).ToArray() - }).ToListAsync(cancellationToken: cancellationToken); + select new IdentityUserIdWithRoleNames + { + Id = gp.Key, + RoleNames = gp.Select(x => x.Name).ToArray() + }).ToListAsync(cancellationToken: cancellationToken); var orgUnitRoles = await (from userOu in dbContext.Set() - join roleOu in dbContext.Set() on userOu.OrganizationUnitId equals roleOu.OrganizationUnitId - join role in dbContext.Roles on roleOu.RoleId equals role.Id - where userIds.Contains(userOu.UserId) - group new - { - userOu.UserId, - role.Name - } by userOu.UserId + join roleOu in dbContext.Set() on userOu.OrganizationUnitId equals roleOu.OrganizationUnitId + join role in dbContext.Roles on roleOu.RoleId equals role.Id + where userIds.Contains(userOu.UserId) + group new { + userOu.UserId, + role.Name + } by userOu.UserId into gp - select new IdentityUserIdWithRoleNames - { - Id = gp.Key, RoleNames = gp.Select(x => x.Name).ToArray() - }).ToListAsync(cancellationToken: cancellationToken); + select new IdentityUserIdWithRoleNames + { + Id = gp.Key, + RoleNames = gp.Select(x => x.Name).ToArray() + }).ToListAsync(cancellationToken: cancellationToken); - return userRoles.Concat(orgUnitRoles).GroupBy(x => x.Id).Select(x => new IdentityUserIdWithRoleNames {Id = x.Key, RoleNames = x.SelectMany(y => y.RoleNames).Distinct().ToArray()}).ToList(); + return userRoles.Concat(orgUnitRoles).GroupBy(x => x.Id).Select(x => new IdentityUserIdWithRoleNames { Id = x.Key, RoleNames = x.SelectMany(y => y.RoleNames).Distinct().ToArray() }).ToList(); } public virtual async Task> GetRoleNamesInOrganizationUnitAsync( @@ -196,6 +196,7 @@ public class EfCoreIdentityUserRepository : EfCoreRepository x.Id == id); + } if (roleId.HasValue) { diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs index c93a41e21d..64c47f8d2c 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs @@ -164,6 +164,7 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Roles.Select(r => r.RoleId)).ToList(); var allRoleIds = roleIds.Union(allOrganizationUnitRoleIds); + var roles = await (await GetQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).Select(r => new{ r.Id, r.Name }).ToListAsync(cancellationToken); var userRoles = userAndRoleIds.ToDictionary(x => x.Key, x => roles.Where(r => x.Value.Contains(r.Id)).Select(r => r.Name).ToArray()); @@ -412,9 +417,9 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Id == id); + } + if (roleId.HasValue) { var organizationUnitIds = (await GetQueryableAsync(cancellationToken)) diff --git a/npm/ng-packs/packages/schematics/src/utils/service.ts b/npm/ng-packs/packages/schematics/src/utils/service.ts index b32dd5fba5..8f48ed3693 100644 --- a/npm/ng-packs/packages/schematics/src/utils/service.ts +++ b/npm/ng-packs/packages/schematics/src/utils/service.ts @@ -18,6 +18,7 @@ import { createTypeAdapter, createTypeParser, createTypesToImportsReducer, + getTypeForEnumList, removeTypeModifiers, } from './type'; import { eBindingSourceId } from '../enums'; @@ -80,7 +81,19 @@ export function createActionToBodyMapper() { const adaptType = createTypeAdapter(); return ({ httpMethod, parameters, returnValue, url }: Action) => { - const responseType = adaptType(returnValue.typeSimple); + let responseType = adaptType(returnValue.typeSimple); + if (responseType.includes('enum')) { + const type = returnValue.typeSimple.replace('enum', returnValue.type); + + if (responseType === 'enum') { + responseType = adaptType(type); + } + + if (responseType === 'enum[]') { + const normalizedType = getTypeForEnumList(type); + responseType = adaptType(normalizedType); + } + } const responseTypeWithNamespace = returnValue.typeSimple; const body = new Body({ method: httpMethod, responseType, url, responseTypeWithNamespace }); @@ -109,7 +122,12 @@ export function createActionToSignatureMapper() { if (isFormData || isFormArray) { return new Property({ name: p.name, type: 'FormData' }); } - const type = adaptType(p.typeSimple); + + let type = adaptType(p.typeSimple); + if (p.typeSimple === 'enum' || p.typeSimple === '[enum]') { + type = adaptType(p.type); + } + const parameter = new Property({ name: p.name, type }); parameter.setDefault(p.defaultValue); parameter.setOptional(p.isOptional); @@ -183,7 +201,9 @@ function createActionToImportsReducer( parseGenerics(paramType) .toGenerics() .forEach(type => { - if (types[type]) acc.push({ type, isEnum: types[type].isEnum }); + if (types[type]) { + acc.push({ type, isEnum: types[type].isEnum }); + } }), ); diff --git a/npm/ng-packs/packages/schematics/src/utils/type.ts b/npm/ng-packs/packages/schematics/src/utils/type.ts index 63c69c7aec..f6d16b39df 100644 --- a/npm/ng-packs/packages/schematics/src/utils/type.ts +++ b/npm/ng-packs/packages/schematics/src/utils/type.ts @@ -58,6 +58,10 @@ export function removeTypeModifiers(type: string) { return type.replace(/\[\]/g, ''); } +export function getTypeForEnumList(type: string) { + return type.replace(/^.*<([^>]+)>.*$/, '[$1]'); +} + export function createTypesToImportsReducer(solution: string, namespace: string) { const mapTypeToImport = createTypeToImportMapper(solution, namespace); @@ -68,7 +72,7 @@ export function createTypesToImportsReducer(solution: string, namespace: string) return; } - if(newImport.specifiers.some(f => f.toLocaleLowerCase() === type.toLocaleLowerCase())){ + if (newImport.specifiers.some(f => f.toLocaleLowerCase() === type.toLocaleLowerCase())) { return; } @@ -76,7 +80,7 @@ export function createTypesToImportsReducer(solution: string, namespace: string) ({ keyword, path }) => keyword === newImport.keyword && path === newImport.path, ); - if (!existingImport){ + if (!existingImport) { return imports.push(newImport); } @@ -101,7 +105,7 @@ export function createTypeToImportMapper(solution: string, namespace: string) { const refs = [removeTypeModifiers(type)]; const specifiers = [adaptType(simplifyType(refs[0]).split('<')[0])]; let path = relativePathToModel(namespace, modelNamespace); - + if (VOLO_REGEX.test(type)) { path = '@abp/ng.core'; }