# AbpMudBlazor **Repository Path**: abduwaris/abp-mud-blazor ## Basic Information - **Project Name**: AbpMudBlazor - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2023-11-25 - **Last Updated**: 2024-04-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MudBlazor Theme in ABP Blazor WebAssembly FINAL ## Introduction In this part, I will show you how to customize/override pre-built Blazor pages of the [Identity Module](https://docs.abp.io/en/abp/latest/Modules/Identity) using [MudBlazor](https://www.mudblazor.com/) components. I assume that Tenant and Setting management pages are rarely used by end-users, so these modules are not covered in this sample to keep it short. You can customize every page using the principles shown here. All you need to do is: 1. Deriving a class that inherits the class you want to override 2. And adding the following attributes to the derived class: ```razor @* to the razor file *@ @attribute [ExposeServices(typeof(BASE-CLASS))] @attribute [Dependency(ReplaceServices = true)] ``` ```charp // or to the C# file [ExposeServices(typeof(BASE-CLASS))] [Dependency(ReplaceServices = true)] ``` See [Blazor UI: Customization / Overriding Components](https://docs.abp.io/en/abp/latest/UI/Blazor/Customization-Overriding-Components) for more information. ## 16. Make Sure You Have Completed Previous Parts You must complete the steps in [Part 1](https://github.com/yellow-dragon-cloud/AbpMudBlazor), [Part 2](https://github.com/yellow-dragon-cloud/AbpMudBlazor2), [Part 3](https://github.com/yellow-dragon-cloud/AbpMudBlazor3), and [Part 4](https://github.com/yellow-dragon-cloud/AbpMudBlazor4) to continue. ## 17. Create Required Files Create `Identity` folder under `Acme.BookStore.Blazor/Pages/`. Create the following files in this folder: 1. `MudPermissionManagementModal.razor` 2. `MudPermissionManagementModal.razor.cs` 3. `MudRoleManagement.razor` 4. `MudRoleManagement.razor.cs` 5. `MudUserManagement.razor` 6. `MudUserManagement.razor.cs` ## 18. Modify These Files' Content As Shown Below 1. `MudPermissionManagementModal.razor` ```razor @using Microsoft.Extensions.Localization @using Volo.Abp.PermissionManagement.Blazor.Components @using Volo.Abp.PermissionManagement.Localization @inherits PermissionManagementModal @L["Permissions"] - @_entityDisplayName @L["SelectAllInAllTabs"] @if (_groups != null) { @* ?! *@      @foreach (var group in _groups) { @group.DisplayName @L["SelectAllInThisTab"] @foreach (var permission in group.Permissions) { @GetShownName(permission) } } } @L["Cancel"] @L["Save"] ``` *** 2. `MudPermissionManagementModal.razor.cs` ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Components; using MudBlazor; using Volo.Abp.AspNetCore.Components.Web.Configuration; using Volo.Abp.PermissionManagement; using Volo.Abp.PermissionManagement.Localization; namespace Acme.BookStore.Blazor.Pages.Identity; public partial class MudPermissionManagementModal { [Inject] private IPermissionAppService PermissionAppService { get; set; } [Inject] private ICurrentApplicationConfigurationCacheResetService CurrentApplicationConfigurationCacheResetService { get; set; } private bool _isVisible; protected virtual DialogOptions DialogOptions { get => new() { CloseButton = true, CloseOnEscapeKey = true, DisableBackdropClick = true, MaxWidth = MaxWidth.Medium }; } private string _providerName; private string _providerKey; private string _entityDisplayName; private List _groups; private readonly List _disabledPermissions = new(); private int _grantedPermissionCount = 0; private int _notGrantedPermissionCount = 0; private bool GrantAll { get => _notGrantedPermissionCount == 0; set { if (_groups == null) return; _grantedPermissionCount = 0; _notGrantedPermissionCount = 0; foreach (var permission in _groups.SelectMany(x => x.Permissions)) { if (IsDisabledPermission(permission)) continue; permission.IsGranted = value; if (value) _grantedPermissionCount++; else _notGrantedPermissionCount++; } } } public MudPermissionManagementModal() { LocalizationResource = typeof(AbpPermissionManagementResource); } public async Task OpenDialogAsync(string providerName, string providerKey, string entityDisplayName = null) { try { _providerName = providerName; _providerKey = providerKey; var result = await PermissionAppService.GetAsync(_providerName, _providerKey); _entityDisplayName = entityDisplayName ?? result.EntityDisplayName; _groups = result.Groups; _grantedPermissionCount = 0; _notGrantedPermissionCount = 0; foreach (var permission in _groups.SelectMany(x => x.Permissions)) { if (permission.IsGranted && permission.GrantedProviders.All(x => x.ProviderName != _providerName)) { _disabledPermissions.Add(permission); continue; } if (permission.IsGranted) _grantedPermissionCount++; else _notGrantedPermissionCount++; } _isVisible = true; StateHasChanged(); } catch (Exception e) { await HandleErrorAsync(e); } } private async Task CloseModalAsync() { await InvokeAsync(() => { _isVisible = false; }); } private async Task SaveAsync() { try { var updateDto = new UpdatePermissionsDto { Permissions = _groups .SelectMany(g => g.Permissions) .Select(p => new UpdatePermissionDto { IsGranted = p.IsGranted, Name = p.Name }) .ToArray() }; await PermissionAppService.UpdateAsync(_providerName, _providerKey, updateDto); await CurrentApplicationConfigurationCacheResetService.ResetAsync(); await CloseModalAsync(); } catch (Exception e) { await HandleErrorAsync(e); } } private void GroupGrantAllChanged(bool value, PermissionGroupDto permissionGroup) { foreach (var permission in permissionGroup.Permissions) { if (!IsDisabledPermission(permission)) SetPermissionGrant(permission, value); } } private void PermissionChanged(bool value, PermissionGroupDto permissionGroup, PermissionGrantInfoDto permission) { SetPermissionGrant(permission, value); if (value && permission.ParentName != null) { var parentPermission = GetParentPermission(permissionGroup, permission); SetPermissionGrant(parentPermission, true); } else if (value == false) { var childPermissions = GetChildPermissions(permissionGroup, permission); foreach (var childPermission in childPermissions) { SetPermissionGrant(childPermission, false); } } } private void SetPermissionGrant(PermissionGrantInfoDto permission, bool value) { if (permission.IsGranted == value) return; if (value) { _grantedPermissionCount++; _notGrantedPermissionCount--; } else { _grantedPermissionCount--; _notGrantedPermissionCount++; } permission.IsGranted = value; } private static PermissionGrantInfoDto GetParentPermission(PermissionGroupDto permissionGroup, PermissionGrantInfoDto permission) { return permissionGroup.Permissions.First(x => x.Name == permission.ParentName); } private static List GetChildPermissions(PermissionGroupDto permissionGroup, PermissionGrantInfoDto permission) { return permissionGroup.Permissions.Where(x => x.Name.StartsWith(permission.Name)).ToList(); } private bool IsDisabledPermission(PermissionGrantInfoDto permissionGrantInfo) { return _disabledPermissions.Any(x => x == permissionGrantInfo); } private string GetShownName(PermissionGrantInfoDto permissionGrantInfo) { if (!IsDisabledPermission(permissionGrantInfo)) return permissionGrantInfo.DisplayName; return string.Format( "{0} ({1})", permissionGrantInfo.DisplayName, permissionGrantInfo.GrantedProviders .Where(p => p.ProviderName != _providerName) .Select(p => p.ProviderName) .JoinAsString(", ") ); } } ``` *** 3. `MudRoleManagement.razor` ```razor @using MudBlazor; @using Blazorise @using Blazorise.DataGrid @using Volo.Abp.BlazoriseUI @using Volo.Abp.BlazoriseUI.Components @using Volo.Abp.Identity @using Microsoft.AspNetCore.Authorization @using Volo.Abp.PermissionManagement.Blazor.Components @using Volo.Abp.Identity.Localization @using Volo.Abp.AspNetCore.Components.Web @using Volo.Abp.AspNetCore.Components.Web.Theming @using Volo.Abp.BlazoriseUI.Components.ObjectExtending @using Volo.Abp.AspNetCore.Components.Web.Theming.Layout @using Volo.Abp.DependencyInjection @using Volo.Abp.Identity.Blazor.Pages.Identity @attribute [Authorize(IdentityPermissions.Roles.Default)] @attribute [ExposeServices(typeof(RoleManagement))] @attribute [Dependency(ReplaceServices = true)] @inject AbpBlazorMessageLocalizerHelper LH @inherits RoleManagement @* ************************* DATA GRID ************************* *@ @L["Roles"] @L["NewRole"] @if (HasUpdatePermission) { } @if (HasDeletePermission) { } @if (context.Item.IsDefault) { @L["DisplayName:IsDefault"] } @if (context.Item.IsPublic) { @L["DisplayName:IsPublic"] } @* ************************* CREATE MODAL ************************* *@ @if (HasCreatePermission) { @L["NewRole"] NewEntity.Name) /> @L["DisplayName:IsDefault"] @L["DisplayName:IsPublic"] @L["Cancel"] @L["Save"] } @* ************************* EDIT MODAL ************************* *@ @if (HasUpdatePermission) { @L["Edit"] EditingEntity.Name) /> @L["DisplayName:IsDefault"] @L["DisplayName:IsPublic"] @L["Cancel"] @L["Save"] } @if (HasManagePermissionsPermission) { } ``` *** 4. `MudRoleManagement.razor.cs` ```csharp using System.Threading.Tasks; using MudBlazor; using Volo.Abp.Application.Dtos; using Volo.Abp.Identity; namespace Acme.BookStore.Blazor.Pages.Identity; public partial class MudRoleManagement { private MudForm _createForm; private MudForm _editForm; private bool _createDialogVisible; private bool _editDialogVisible; private MudDataGrid _dataGrid; private MudPermissionManagementModal _permissionManagementModal; protected async Task> LoadServerData(GridState state) { if (GetListInput is PagedAndSortedResultRequestDto pageResultRequest) { pageResultRequest.MaxResultCount = state.PageSize; pageResultRequest.SkipCount = state.Page * state.PageSize; } var result = await AppService.GetListAsync(GetListInput); return new() { Items = result.Items, TotalItems = (int)result.TotalCount }; } protected override Task OpenCreateModalAsync() { NewEntity = new(); _createDialogVisible = true; return Task.CompletedTask; } protected override Task CloseCreateModalAsync() { _createDialogVisible = false; return Task.CompletedTask; } protected override async Task CreateEntityAsync() { if (_createForm.IsValid) { var createDto = MapToCreateInput(NewEntity); await AppService.CreateAsync(createDto); await _dataGrid.ReloadServerData(); _createDialogVisible = false; } } protected override Task OpenEditModalAsync(IdentityRoleDto entity) { EditingEntityId = entity.Id; EditingEntity = MapToEditingEntity(entity); _editDialogVisible = true; return Task.CompletedTask; } protected override Task CloseEditModalAsync() { _editDialogVisible = false; return Task.CompletedTask; } protected override async Task UpdateEntityAsync() { if (_editForm.IsValid) { await base.UpdateEntityAsync(); await _dataGrid.ReloadServerData(); _editDialogVisible = false; } } protected override async Task DeleteEntityAsync(IdentityRoleDto entity) { if (await Message.Confirm(GetDeleteConfirmationMessage(entity))) { await base.DeleteEntityAsync(entity); await _dataGrid.ReloadServerData(); } } protected override Task OnUpdatedEntityAsync() { return Task.CompletedTask; } protected virtual async Task OpenPermissionsModalAsync(IdentityRoleDto entity) { await _permissionManagementModal.OpenDialogAsync(PermissionProviderName, entity.Name); } protected virtual DialogOptions DialogOptions { get => new() { CloseButton = true, CloseOnEscapeKey = true, DisableBackdropClick = true }; } } ``` *** 5. `MudUserManagement.razor` ```razor @using Microsoft.AspNetCore.Authorization @using Volo.Abp.DependencyInjection @using Volo.Abp.PermissionManagement.Blazor.Components @using Volo.Abp.Identity.Localization @using Volo.Abp.AspNetCore.Components.Web.Theming.Layout @using Volo.Abp.Identity @using Volo.Abp.Identity.Blazor.Pages.Identity @attribute [Authorize(IdentityPermissions.Users.Default)] @attribute [ExposeServices(typeof(UserManagement))] @attribute [Dependency(ReplaceServices = true)] @inject AbpBlazorMessageLocalizerHelper LH @inherits UserManagement @* ************************* DATA GRID ************************* *@ @L["Users"] @L["NewUser"] @if (HasUpdatePermission) { } @if (HasDeletePermission) { } @* ************************* CREATE MODAL ************************* *@ @if (HasCreatePermission) { @L["NewUser"] @L["DisplayName:IsActive"] @L["DisplayName:LockoutEnabled"] @if (NewUserRoles != null) { @foreach (var role in NewUserRoles) { @role.Name } } else { N/A } @L["Cancel"] @L["Save"] } @* ************************* EDIT MODAL ************************* *@ @if (HasUpdatePermission) { @L["Edit"] @L["DisplayName:IsActive"] @L["DisplayName:LockoutEnabled"] @if (EditUserRoles != null) { @foreach (var role in EditUserRoles) { @role.Name } } else { N/A } @L["Cancel"] @L["Save"] } @if (HasManagePermissionsPermission) { } ``` *** 6. `MudUserManagement.razor.cs` ```csharp using System.Linq; using System.Threading.Tasks; using MudBlazor; using Volo.Abp.Application.Dtos; using Volo.Abp.Identity; using Volo.Abp.Identity.Blazor.Pages.Identity; namespace Acme.BookStore.Blazor.Pages.Identity; public partial class MudUserManagement { private MudForm _createForm; private MudForm _editForm; private bool _createDialogVisible; private bool _editDialogVisible; private MudDataGrid _dataGrid; private MudPermissionManagementModal _permissionManagementModal; protected async Task> LoadServerData(GridState state) { if (GetListInput is PagedAndSortedResultRequestDto pageResultRequest) { pageResultRequest.MaxResultCount = state.PageSize; pageResultRequest.SkipCount = state.Page * state.PageSize; } var result = await AppService.GetListAsync(GetListInput); return new() { Items = result.Items, TotalItems = (int)result.TotalCount }; } protected override Task OpenCreateModalAsync() { NewEntity = new() { IsActive = true }; NewUserRoles = Roles.Select(i => new AssignedRoleViewModel { Name = i.Name, IsAssigned = i.IsDefault }).ToArray(); _createDialogVisible = true; return Task.CompletedTask; } protected override Task CloseCreateModalAsync() { _createDialogVisible = false; return Task.CompletedTask; } protected override async Task CreateEntityAsync() { if (_createForm.IsValid) { var createDto = MapToCreateInput(NewEntity); await AppService.CreateAsync(createDto); await _dataGrid.ReloadServerData(); await CloseCreateModalAsync(); } } protected override async Task OpenEditModalAsync(IdentityUserDto entity) { var userRoleNames = (await AppService.GetRolesAsync(entity.Id)).Items.Select(r => r.Name).ToList(); EditUserRoles = Roles.Select(x => new AssignedRoleViewModel { Name = x.Name, IsAssigned = userRoleNames.Contains(x.Name) }).ToArray(); EditingEntityId = entity.Id; EditingEntity = MapToEditingEntity(entity); _editDialogVisible = true; } protected override Task CloseEditModalAsync() { _editDialogVisible = false; return Task.CompletedTask; } protected override async Task UpdateEntityAsync() { if (_editForm.IsValid) { await AppService.UpdateAsync(EditingEntityId, EditingEntity); await _dataGrid.ReloadServerData(); await CloseEditModalAsync(); } } protected override async Task DeleteEntityAsync(IdentityUserDto entity) { if (await Message.Confirm(GetDeleteConfirmationMessage(entity))) { await base.DeleteEntityAsync(entity); await _dataGrid.ReloadServerData(); } } protected override Task OnUpdatedEntityAsync() { return Task.CompletedTask; } protected virtual async Task OpenPermissionsModalAsync(IdentityUserDto entity) { await _permissionManagementModal.OpenDialogAsync( PermissionProviderName, entity.Id.ToString()); } protected virtual DialogOptions DialogOptions { get => new() { CloseButton = true, CloseOnEscapeKey = true, DisableBackdropClick = true }; } } ``` *** ## Screenshots ![image](images/screenshot5.png) ![image](images/screenshot6.png) ## Source Code The source code of this project is [available on Github](https://github.com/yellow-dragon-cloud/AbpMudBlazorFinal)