Skip to content

Commit

Permalink
Merge branch 'dev' into RequireEmailVerificationToRegister
Browse files Browse the repository at this point in the history
  • Loading branch information
oykuermann committed Jan 29, 2025
2 parents 54febaf + 74d5168 commit fad8c4c
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 39 deletions.
8 changes: 8 additions & 0 deletions docs/en/docs-nav.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1751,6 +1755,10 @@
{
"text": "LeptonX Lite",
"path": "ui-themes/lepton-x-lite/angular.md"
},
{
"text": "LeptonX",
"path": "ui-themes/lepton-x/angular.md"
}
]
},
Expand Down
15 changes: 9 additions & 6 deletions docs/en/framework/ui/blazor/overall.md
Original file line number Diff line number Diff line change
@@ -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:

Expand Down Expand Up @@ -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 doesnt 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

Expand Down
2 changes: 1 addition & 1 deletion docs/en/framework/ui/blazor/theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Task<List<IdentityUser>> GetListAsync(
bool includeDetails = false,
Guid? roleId = null,
Guid? organizationUnitId = null,
Guid? id = null,
string userName = null,
string phoneNumber = null,
string emailAddress = null,
Expand Down Expand Up @@ -114,6 +115,7 @@ Task<long> GetCountAsync(
string filter = null,
Guid? roleId = null,
Guid? organizationUnitId = null,
Guid? id = null,
string userName = null,
string phoneNumber = null,
string emailAddress = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,35 +62,35 @@ public virtual async Task<List<IdentityUserIdWithRoleNames>> GetRoleNamesAsync(
{
var dbContext = await GetDbContextAsync();
var userRoles = await (from userRole in dbContext.Set<IdentityUserRole>()
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<IdentityUserOrganizationUnit>()
join roleOu in dbContext.Set<OrganizationUnitRole>() 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<OrganizationUnitRole>() 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<List<string>> GetRoleNamesInOrganizationUnitAsync(
Expand Down Expand Up @@ -196,6 +196,7 @@ public virtual async Task<List<IdentityUser>> GetListAsync(
bool includeDetails = false,
Guid? roleId = null,
Guid? organizationUnitId = null,
Guid? id = null,
string userName = null,
string phoneNumber = null,
string emailAddress = null,
Expand All @@ -215,6 +216,7 @@ public virtual async Task<List<IdentityUser>> GetListAsync(
filter,
roleId,
organizationUnitId,
id,
userName,
phoneNumber,
emailAddress,
Expand Down Expand Up @@ -272,6 +274,7 @@ public virtual async Task<long> GetCountAsync(
string filter = null,
Guid? roleId = null,
Guid? organizationUnitId = null,
Guid? id = null,
string userName = null,
string phoneNumber = null,
string emailAddress = null,
Expand All @@ -291,6 +294,7 @@ public virtual async Task<long> GetCountAsync(
filter,
roleId,
organizationUnitId,
id,
userName,
phoneNumber,
emailAddress,
Expand Down Expand Up @@ -434,6 +438,7 @@ protected virtual async Task<IQueryable<IdentityUser>> GetFilteredQueryableAsync
string filter = null,
Guid? roleId = null,
Guid? organizationUnitId = null,
Guid? id = null,
string userName = null,
string phoneNumber = null,
string emailAddress = null,
Expand All @@ -451,6 +456,11 @@ protected virtual async Task<IQueryable<IdentityUser>> GetFilteredQueryableAsync
{
var upperFilter = filter?.ToUpperInvariant();
var query = await GetQueryableAsync();

if (id.HasValue)
{
return query.Where(x => x.Id == id);
}

if (roleId.HasValue)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ public virtual async Task<List<IdentityUser>> GetListAsync(
bool includeDetails = false,
Guid? roleId = null,
Guid? organizationUnitId = null,
Guid? id = null,
string userName = null,
string phoneNumber = null,
string emailAddress = null,
Expand All @@ -183,6 +184,7 @@ public virtual async Task<List<IdentityUser>> GetListAsync(
filter,
roleId,
organizationUnitId,
id,
userName,
phoneNumber,
emailAddress,
Expand Down Expand Up @@ -243,6 +245,7 @@ public virtual async Task<long> GetCountAsync(
string filter = null,
Guid? roleId = null,
Guid? organizationUnitId = null,
Guid? id = null,
string userName = null,
string phoneNumber = null,
string emailAddress = null,
Expand All @@ -262,6 +265,7 @@ public virtual async Task<long> GetCountAsync(
filter,
roleId,
organizationUnitId,
id,
userName,
phoneNumber,
emailAddress,
Expand Down Expand Up @@ -398,6 +402,7 @@ public virtual async Task<List<IdentityUserIdWithRoleNames>> GetRoleNamesAsync(
var allOrganizationUnitRoleIds = organizationUnitAndRoleIds.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToList();
var allRoleIds = roleIds.Union(allOrganizationUnitRoleIds);


var roles = await (await GetQueryableAsync<IdentityRole>(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());

Expand All @@ -412,9 +417,9 @@ public virtual async Task<List<IdentityUserIdWithRoleNames>> GetRoleNamesAsync(
{
user.RoleNames = user.RoleNames.Union(roleNames).ToArray();
}
else if(roleNames.Any())
else if (roleNames.Any())
{
result.Add(new IdentityUserIdWithRoleNames { Id = userAndOrganizationUnitId.Key, RoleNames = roleNames});
result.Add(new IdentityUserIdWithRoleNames { Id = userAndOrganizationUnitId.Key, RoleNames = roleNames });
}
}

Expand All @@ -425,6 +430,7 @@ protected virtual async Task<IQueryable<IdentityUser>> GetFilteredQueryableAsync
string filter = null,
Guid? roleId = null,
Guid? organizationUnitId = null,
Guid? id = null,
string userName = null,
string phoneNumber = null,
string emailAddress = null,
Expand All @@ -443,6 +449,11 @@ protected virtual async Task<IQueryable<IdentityUser>> GetFilteredQueryableAsync
var upperFilter = filter?.ToUpperInvariant();
var query = await GetQueryableAsync(cancellationToken);

if (id.HasValue)
{
return query.Where(x => x.Id == id);
}

if (roleId.HasValue)
{
var organizationUnitIds = (await GetQueryableAsync<OrganizationUnit>(cancellationToken))
Expand Down
26 changes: 23 additions & 3 deletions npm/ng-packs/packages/schematics/src/utils/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
createTypeAdapter,
createTypeParser,
createTypesToImportsReducer,
getTypeForEnumList,
removeTypeModifiers,
} from './type';
import { eBindingSourceId } from '../enums';
Expand Down Expand Up @@ -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 });

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 });
}
}),
);

Expand Down
10 changes: 7 additions & 3 deletions npm/ng-packs/packages/schematics/src/utils/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -68,15 +72,15 @@ 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;
}

const existingImport = imports.find(
({ keyword, path }) => keyword === newImport.keyword && path === newImport.path,
);

if (!existingImport){
if (!existingImport) {
return imports.push(newImport);
}

Expand All @@ -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';
}
Expand Down

0 comments on commit fad8c4c

Please sign in to comment.