Browse Source

fixed build problem in several modules for MudBlazor

pull/25235/head
İsmail ÇAĞDAŞ 9 months ago
parent
commit
4bf9ceba48
  1. 271
      docs/en/Migration-Plan-Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.md
  2. 15
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/AbpAspNetCoreComponentsWebThemingMudBlazorModule.cs
  3. 19
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/AbpDynamicLayoutComponentOptions.cs
  4. 61
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Bundling/AbpScripts.razor
  5. 75
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Bundling/AbpStyles.razor
  6. 11
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Bundling/IComponentBundleManager.cs
  7. 7
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/DynamicLayoutComponent.razor
  8. 10
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/DynamicLayoutComponent.razor.cs
  9. 7
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/LayoutHooks/LayoutHook.razor
  10. 43
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/LayoutHooks/LayoutHook.razor.cs
  11. 65
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/PageHeader.razor
  12. 127
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/PageHeader.razor.cs
  13. 65
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Layout/PageHeader.razor
  14. 199
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Layout/PageHeader.razor.cs
  15. 8
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Layout/PageHeaderOptions.cs
  16. 54
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Layout/PageLayout.cs
  17. 9
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Layout/StandardLayouts.cs
  18. 8
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/IPageToolbarContributor.cs
  19. 8
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/IPageToolbarManager.cs
  20. 34
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/MudBlazorPageToolbarExtensions.cs
  21. 13
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/MudPageToolbarButton.razor
  22. 33
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/MudPageToolbarButton.razor.cs
  23. 11
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbar.cs
  24. 20
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarContributionContext.cs
  25. 8
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarContributor.cs
  26. 7
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarContributorList.cs
  27. 8
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarDictionary.cs
  28. 69
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarExtensions.cs
  29. 25
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarItem.cs
  30. 8
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarItemList.cs
  31. 38
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarManager.cs
  32. 58
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/SimplePageToolbarContributor.cs
  33. 15
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Routing/AbpRouterOptions.cs
  34. 9
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Routing/RouterAssemblyList.cs
  35. 13
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/AbpThemingOptions.cs
  36. 34
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/DefaultThemeManager.cs
  37. 36
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/DefaultThemeSelector.cs
  38. 8
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/ITheme.cs
  39. 6
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/IThemeManager.cs
  40. 6
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/IThemeSelector.cs
  41. 23
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/ThemeDictionary.cs
  42. 27
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/ThemeExtensions.cs
  43. 24
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/ThemeInfo.cs
  44. 23
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/ThemeNameAttribute.cs
  45. 15
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/AbpToolbarOptions.cs
  46. 27
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/IToolbarConfigurationContext.cs
  47. 8
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/IToolbarContributor.cs
  48. 8
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/IToolbarManager.cs
  49. 6
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/StandardToolbars.cs
  50. 17
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/Toolbar.cs
  51. 51
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/ToolbarConfigurationContext.cs
  52. 21
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/ToolbarItem.cs
  53. 38
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/ToolbarManager.cs
  54. 11
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.csproj
  55. 6
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/_Imports.razor
  56. 17
      framework/src/Volo.Abp.MudBlazorUI/BreadcrumbItem.cs
  57. 24
      framework/src/Volo.Abp.MudBlazorUI/Components/AbpMudExtensibleDataGrid.razor.cs
  58. 3
      modules/feature-management/Volo.Abp.FeatureManagement.slnx
  59. 9
      modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Components/FeatureManagementModal.razor
  60. 3
      modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Components/FeatureSettingGroup/FeatureSettingManagementComponent.razor
  61. 3
      modules/setting-management/Volo.Abp.SettingManagement.slnx
  62. 3
      modules/setting-management/src/Volo.Abp.SettingManagement.Blazor.MudBlazor/AbpSettingManagementBlazorMudBlazorModule.cs
  63. 16
      modules/setting-management/src/Volo.Abp.SettingManagement.Blazor.MudBlazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor.cs
  64. 4
      modules/setting-management/src/Volo.Abp.SettingManagement.Blazor.MudBlazor/Pages/SettingManagement/SettingManagement.razor.cs
  65. 3
      modules/tenant-management/Volo.Abp.TenantManagement.slnx
  66. 3
      modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor.MudBlazor/AbpTenantManagementBlazorMudBlazorModule.cs
  67. 9
      modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor.MudBlazor/Pages/TenantManagement/TenantManagement.razor.cs

271
docs/en/Migration-Plan-Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.md

@ -0,0 +1,271 @@
# Implementation Plan: Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor
## Overview
This document outlines the plan to implement all missing features from `Volo.Abp.AspNetCore.Components.Web.Theming` (Blazorise version) into `Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor` (MudBlazor version).
## Current Status
### ✅ Already Implemented
1. **PageHeader Component** (`Components/PageHeader.razor` + `.razor.cs`)
2. **MudPageToolbarButton** (`PageToolbars/MudPageToolbarButton.razor` + `.razor.cs`)
3. **MudBlazorPageToolbarExtensions** (`PageToolbars/MudBlazorPageToolbarExtensions.cs`) - Contains `AddMudButton` method
4. **Module Registration** (`AbpAspNetCoreComponentsWebThemingMudBlazorModule.cs`)
### ❌ Missing Features
## Implementation Plan
### Phase 1: Core Components (High Priority)
#### 1.1 DynamicLayoutComponent
**Location:** `Components/DynamicLayoutComponent.razor` + `.razor.cs`
**Description:** Renders dynamic components configured in `AbpDynamicLayoutComponentOptions`.
**Implementation:**
- Copy `DynamicLayoutComponent.razor` from Blazorise version (no UI-specific code, should work as-is)
- Copy `DynamicLayoutComponent.razor.cs` from Blazorise version (no UI-specific code, should work as-is)
- These components are UI-agnostic and can be directly copied
**Files to Create:**
- `framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/DynamicLayoutComponent.razor`
- `framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/DynamicLayoutComponent.razor.cs`
**Dependencies:** None (uses base `AbpAspNetCoreComponentsWebThemingModule`)
---
#### 1.2 LayoutHook Component
**Location:** `Components/LayoutHooks/LayoutHook.razor` + `.razor.cs`
**Description:** Renders layout hooks that allow injecting components at specific points in layouts.
**Implementation:**
- Copy `LayoutHook.razor` from Blazorise version (no UI-specific code, should work as-is)
- Copy `LayoutHook.razor.cs` from Blazorise version (no UI-specific code, should work as-is)
- These components are UI-agnostic and can be directly copied
**Files to Create:**
- `framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/LayoutHooks/LayoutHook.razor`
- `framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/LayoutHooks/LayoutHook.razor.cs`
**Dependencies:** None (uses base `AbpAspNetCoreComponentsWeb.Theming` infrastructure)
---
### Phase 2: Bundling Components (High Priority)
#### 2.1 AbpStyles Component
**Location:** `Bundling/AbpStyles.razor`
**Description:** Renders CSS stylesheets with support for prerendering and WebAssembly.
**Implementation:**
- Copy `AbpStyles.razor` from Blazorise version
- This component is UI-agnostic and can be directly copied
- Handles:
- Prerendering support
- WebAssembly style file handling
- Bundle management via `IComponentBundleManager`
**Files to Create:**
- `framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Bundling/AbpStyles.razor`
**Dependencies:**
- `IComponentBundleManager` (from base `Volo.Abp.AspNetCore.Components.Web.Theming`)
---
#### 2.2 AbpScripts Component
**Location:** `Bundling/AbpScripts.razor`
**Description:** Renders JavaScript files with support for prerendering and WebAssembly.
**Implementation:**
- Copy `AbpScripts.razor` from Blazorise version
- This component is UI-agnostic and can be directly copied
- Handles:
- Prerendering support
- WebAssembly script file handling
- Bundle management via `IComponentBundleManager`
**Files to Create:**
- `framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Bundling/AbpScripts.razor`
**Dependencies:**
- `IComponentBundleManager` (from base `Volo.Abp.AspNetCore.Components.Web.Theming`)
---
### Phase 3: PageToolbar Extensions (Medium Priority)
#### 3.1 AddComponent Extension Methods
**Location:** `PageToolbars/MudBlazorPageToolbarExtensions.cs`
**Description:** Add `AddComponent` extension methods to `PageToolbar` for adding custom components to toolbars.
**Current State:** Only `AddMudButton` exists.
**Implementation:**
- Add `AddComponent<TComponent>` generic method
- Add `AddComponent(Type componentType, ...)` non-generic method
- These methods should use `SimplePageToolbarContributor` (from base project)
- Follow the same pattern as Blazorise version but without UI-specific code
**Files to Update:**
- `framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/MudBlazorPageToolbarExtensions.cs`
**Example Implementation:**
```csharp
public static PageToolbar AddComponent<TComponent>(
this PageToolbar toolbar,
Dictionary<string, object?>? arguments = null,
int order = 0,
string? requiredPolicyName = null)
{
return toolbar.AddComponent(
typeof(TComponent),
arguments,
order,
requiredPolicyName
);
}
public static PageToolbar AddComponent(
this PageToolbar toolbar,
Type componentType,
Dictionary<string, object?>? arguments = null,
int order = 0,
string? requiredPolicyName = null)
{
toolbar.Contributors.Add(
new SimplePageToolbarContributor(
componentType,
arguments,
order,
requiredPolicyName
)
);
return toolbar;
}
```
**Dependencies:**
- `SimplePageToolbarContributor` (from base `Volo.Abp.AspNetCore.Components.Web.Theming`)
---
### Phase 4: Module Configuration (Low Priority - Optional)
#### 4.1 Module Service Configuration
**Location:** `AbpAspNetCoreComponentsWebThemingMudBlazorModule.cs`
**Description:** Configure any MudBlazor-specific services or options.
**Current State:** Module is empty (only depends on base modules).
**Implementation:**
- Review if any MudBlazor-specific configuration is needed
- Currently, the base `AbpAspNetCoreComponentsWebThemingModule` handles `AbpDynamicLayoutComponentOptions`
- May need to add MudBlazor-specific component registrations if required
**Files to Update:**
- `framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/AbpAspNetCoreComponentsWebThemingMudBlazorModule.cs`
**Note:** This may not be necessary if all configuration is handled in the base module or in theme-specific packages.
---
## Implementation Notes
### UI-Agnostic Components
The following components are **UI-agnostic** and can be copied directly from the Blazorise version:
- `DynamicLayoutComponent`
- `LayoutHook`
- `AbpStyles`
- `AbpScripts`
These components don't use any Blazorise-specific UI components and rely only on:
- Base Blazor components (`ComponentBase`, `DynamicComponent`)
- ABP infrastructure (options, services)
- Standard .NET types
### Infrastructure Already Available
The following infrastructure is already available in the base `Volo.Abp.AspNetCore.Components.Web.Theming` project and doesn't need to be reimplemented:
- `PageToolbar`, `PageToolbarManager`, `IPageToolbarManager`
- `PageToolbarContributor`, `SimplePageToolbarContributor`
- `PageToolbarItem`, `PageToolbarItemList`
- `PageLayout`, `PageHeaderOptions`
- `StandardLayouts`
- `AbpRouterOptions`, `RouterAssemblyList`
- `IThemeManager`, `ITheme`, theme infrastructure
- `ToolbarManager`, `Toolbar`, toolbar infrastructure
- `AbpDynamicLayoutComponentOptions`
- `IComponentBundleManager`
### Testing Checklist
After implementing each phase, verify:
1. ✅ Components compile without errors
2. ✅ Components can be used in MudBlazor layouts
3. ✅ Bundling components work with prerendering
4. ✅ Layout hooks render correctly
5. ✅ Dynamic layout components render correctly
6. ✅ PageToolbar extensions work with MudBlazor components
---
## Implementation Order
1. **Phase 1** - Core Components (DynamicLayoutComponent, LayoutHook)
- These are foundational and used by layouts
- UI-agnostic, easy to implement
2. **Phase 2** - Bundling Components (AbpStyles, AbpScripts)
- Required for proper asset loading
- UI-agnostic, easy to implement
3. **Phase 3** - PageToolbar Extensions
- Enhances toolbar functionality
- Straightforward implementation
4. **Phase 4** - Module Configuration
- Optional, only if needed
---
## Files Summary
### Files to Create (7 files)
1. `Components/DynamicLayoutComponent.razor`
2. `Components/DynamicLayoutComponent.razor.cs`
3. `Components/LayoutHooks/LayoutHook.razor`
4. `Components/LayoutHooks/LayoutHook.razor.cs`
5. `Bundling/AbpStyles.razor`
6. `Bundling/AbpScripts.razor`
7. (Optional) Update `PageToolbars/MudBlazorPageToolbarExtensions.cs`
### Files to Update (1 file)
1. `PageToolbars/MudBlazorPageToolbarExtensions.cs` - Add `AddComponent` methods
---
## Estimated Effort
- **Phase 1:** ~30 minutes (copy files, verify)
- **Phase 2:** ~30 minutes (copy files, verify)
- **Phase 3:** ~20 minutes (add extension methods)
- **Phase 4:** ~10 minutes (if needed)
**Total:** ~1.5 hours
---
## Dependencies
All required dependencies are already available:
- Base `Volo.Abp.AspNetCore.Components.Web.Theming` project
- `Volo.Abp.MudBlazorUI` project
- Standard Blazor infrastructure
No new NuGet packages or project references are required.

15
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/AbpAspNetCoreComponentsWebThemingMudBlazorModule.cs

@ -1,12 +1,21 @@
using Volo.Abp.AspNetCore.Components.Web.Theming; using Volo.Abp.Application;
using Volo.Abp.Authorization;
using Volo.Abp.Features;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.MudBlazorUI; using Volo.Abp.MudBlazorUI;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor; namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor;
[DependsOn( [DependsOn(
typeof(AbpAspNetCoreComponentsWebThemingModule), typeof(AbpAspNetCoreComponentsWebModule),
typeof(AbpMudBlazorUIModule) typeof(AbpMudBlazorUIModule),
typeof(AbpUiNavigationModule),
typeof(AbpDddApplicationContractsModule),
typeof(AbpAuthorizationModule),
typeof(AbpGlobalFeaturesModule),
typeof(AbpFeaturesModule)
)] )]
public class AbpAspNetCoreComponentsWebThemingMudBlazorModule : AbpModule public class AbpAspNetCoreComponentsWebThemingMudBlazorModule : AbpModule
{ {

19
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/AbpDynamicLayoutComponentOptions.cs

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor;
public class AbpDynamicLayoutComponentOptions
{
/// <summary>
/// Used to define components that renders in the layout
/// </summary>
[NotNull]
public Dictionary<Type, IDictionary<string,object>?> Components { get; set; }
public AbpDynamicLayoutComponentOptions()
{
Components = new Dictionary<Type, IDictionary<string, object>?>();
}
}

61
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Bundling/AbpScripts.razor

@ -0,0 +1,61 @@
@implements IDisposable
@inject IComponentBundleManager BundleManager
@inject PersistentComponentState ApplicationState
@if (ScriptFiles != null)
{
foreach (var file in ScriptFiles)
{
var src = file;
if (!AppBasePath.IsNullOrWhiteSpace())
{
src = AppBasePath.EnsureEndsWith('/') + file.RemovePreFix("/");
}
<script src="@src"></script>
}
}
@code {
private const string PrerenderedKey = "abp_script_prerendered";
[Parameter]
public List<string>? WebAssemblyScriptFiles { get; set; }
[Parameter]
public string? BundleName { get; set; }
[Parameter]
public string? AppBasePath { get; set; }
private List<string>? ScriptFiles { get; set; }
private PersistingComponentStateSubscription _persistingSubscription;
protected override async Task OnInitializedAsync()
{
_persistingSubscription = ApplicationState.RegisterOnPersisting(Callback);
if (!ApplicationState.TryTakeFromJson<string>(PrerenderedKey, out _))
{
// We are in prerendering mode
if (!BundleName.IsNullOrWhiteSpace())
{
ScriptFiles = (await BundleManager.GetScriptBundleFilesAsync(BundleName!)).ToList();
}
}
else
{
if (OperatingSystem.IsBrowser() && WebAssemblyScriptFiles != null)
{
ScriptFiles = WebAssemblyScriptFiles;
}
}
}
private Task Callback()
{
ApplicationState.PersistAsJson(PrerenderedKey, PrerenderedKey);
return Task.CompletedTask;
}
public void Dispose() => _persistingSubscription.Dispose();
}

75
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Bundling/AbpStyles.razor

@ -0,0 +1,75 @@
@implements IDisposable
@inject IComponentBundleManager BundleManager
@inject PersistentComponentState ApplicationState
@if (StyleFiles != null)
{
foreach (var file in StyleFiles)
{
var href = file;
if (!AppBasePath.IsNullOrWhiteSpace())
{
href = AppBasePath.EnsureEndsWith('/') + file.RemovePreFix("/");
}
<link rel="stylesheet" href="@href" />
}
}
@code {
private const string PrerenderedKey = "abp_style_prerendered";
[Parameter]
public List<string>? WebAssemblyStyleFiles { get; set; }
[Parameter]
public string? BundleName { get; set; }
[Parameter]
public string? AppBasePath { get; set; }
private List<string>? StyleFiles { get; set; }
private PersistingComponentStateSubscription _persistingSubscription;
protected override async Task OnInitializedAsync()
{
_persistingSubscription = ApplicationState.RegisterOnPersisting(Callback);
if (!ApplicationState.TryTakeFromJson<List<string>>(PrerenderedKey, out var scriptFiles))
{
// We are in prerendering mode
if (!BundleName.IsNullOrWhiteSpace())
{
StyleFiles = (await BundleManager.GetStyleBundleFilesAsync(BundleName!)).ToList();
}
}
else
{
StyleFiles = scriptFiles;
if (OperatingSystem.IsBrowser() && StyleFiles != null && WebAssemblyStyleFiles != null)
{
StyleFiles.AddIfNotContains(WebAssemblyStyleFiles);
}
}
}
private bool _hasRemoveServerStyle = false;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!_hasRemoveServerStyle && OperatingSystem.IsBrowser() && WebAssemblyStyleFiles != null)
{
_hasRemoveServerStyle = true;
await Task.Delay(3000);
StyleFiles = WebAssemblyStyleFiles;
StateHasChanged();
}
}
private Task Callback()
{
ApplicationState.PersistAsJson(PrerenderedKey, StyleFiles);
return Task.CompletedTask;
}
public void Dispose() => _persistingSubscription.Dispose();
}

11
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Bundling/IComponentBundleManager.cs

@ -0,0 +1,11 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Bundling;
public interface IComponentBundleManager
{
Task<IReadOnlyList<string>> GetStyleBundleFilesAsync(string bundleName);
Task<IReadOnlyList<string>> GetScriptBundleFilesAsync(string bundleName);
}

7
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/DynamicLayoutComponent.razor

@ -0,0 +1,7 @@
@if (AbpDynamicLayoutComponentOptions.Value.Components.Any())
{
foreach (var (componentType, parameters) in AbpDynamicLayoutComponentOptions.Value.Components)
{
<DynamicComponent Type="@componentType" Parameters="@parameters" />
}
}

10
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/DynamicLayoutComponent.razor.cs

@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Components;
public partial class DynamicLayoutComponent : ComponentBase
{
[Inject]
protected IOptions<AbpDynamicLayoutComponentOptions> AbpDynamicLayoutComponentOptions { get; set; } = default!;
}

7
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/LayoutHooks/LayoutHook.razor

@ -0,0 +1,7 @@
@if (LayoutHookViewModel.Hooks.Any())
{
foreach (var hook in LayoutHookViewModel.Hooks)
{
<DynamicComponent Type="@hook.ComponentType" />
}
}

43
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/LayoutHooks/LayoutHook.razor.cs

@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
using Volo.Abp.Ui.LayoutHooks;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Components.LayoutHooks;
public partial class LayoutHook : ComponentBase
{
[Parameter]
public string Name { get; set; } = default!;
[Parameter]
public string? Layout { get; set; }
[Inject]
protected IOptions<AbpLayoutHookOptions> LayoutHookOptions { get; set; } = default!;
protected LayoutHookViewModel LayoutHookViewModel { get; private set; } = default!;
protected override Task OnInitializedAsync()
{
if (LayoutHookOptions.Value.Hooks.TryGetValue(Name, out var layoutHooks))
{
layoutHooks = layoutHooks
.Where(x => IsComponentBase(x) && (string.IsNullOrWhiteSpace(x.Layout) || x.Layout == Layout))
.ToList();
}
layoutHooks ??= new List<LayoutHookInfo>();
LayoutHookViewModel = new LayoutHookViewModel(layoutHooks.ToArray(), Layout);
return Task.CompletedTask;
}
protected virtual bool IsComponentBase(LayoutHookInfo layoutHook)
{
return typeof(ComponentBase).IsAssignableFrom(layoutHook.ComponentType);
}
}

65
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/PageHeader.razor

@ -1,65 +0,0 @@
@using Microsoft.AspNetCore.Components.Web
@using Volo.Abp.Ui.Branding
@inject IBrandingProvider BrandingProvider
@using global::MudBlazor
<MudGrid Class="entry-row">
@if (PageLayout.Title.IsNullOrEmpty())
{
<PageTitle>@BrandingProvider.AppName</PageTitle>
}
else
{
<PageTitle>@PageLayout.Title | @BrandingProvider.AppName</PageTitle>
}
@if (Options.Value.RenderPageTitle)
{
<MudItem xs="12" sm="6">
<MudText Typo="Typo.h4" Class="content-header-title">
@PageLayout.Title
</MudText>
</MudItem>
}
@if (Options.Value.RenderBreadcrumbs && PageLayout.BreadcrumbItems.Any())
{
<MudItem xs="12" sm="6">
<MudBreadcrumbs MaxItems="4">
@if (BreadcrumbShowHome)
{
<MudBreadcrumbItem Href="/">
<MudIcon Icon="@Icons.Material.Filled.Home" />
</MudBreadcrumbItem>
}
@foreach (var item in PageLayout.BreadcrumbItems)
{
<MudBreadcrumbItem Href="@item.Url">
@item.Text
</MudBreadcrumbItem>
}
</MudBreadcrumbs>
</MudItem>
}
@if (Options.Value.RenderToolbar)
{
<MudItem xs="12">
<MudStack Row="true" Justify="Justify.FlexEnd" Spacing="1">
@if (Toolbar == null)
{
@ChildContent
}
@foreach (var toolbarItemRender in ToolbarItemRenders)
{
<MudStackItem>
@toolbarItemRender
</MudStackItem>
}
</MudStack>
</MudItem>
}
</MudGrid>

127
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Components/PageHeader.razor.cs

@ -1,127 +0,0 @@
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Components.Web.Theming.Layout;
using Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars;
using Volo.Abp.BlazoriseUI;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Components;
public partial class PageHeader : ComponentBase, IDisposable
{
protected List<RenderFragment> ToolbarItemRenders { get; set; }
[Inject]
public IPageToolbarManager PageToolbarManager { get; set; } = default!;
[Inject]
public PageLayout PageLayout { get; private set; } = default!;
[Inject]
public IOptions<PageHeaderOptions> Options { get; set; } = default!;
[Parameter]
public string? Title { get => PageLayout.Title; set => PageLayout.Title = value; }
[Parameter]
public bool BreadcrumbShowHome { get; set; } = true;
[Parameter]
public bool BreadcrumbShowCurrent { get; set; } = true;
[Parameter]
public RenderFragment ChildContent { get; set; } = default!;
[Parameter]
public List<BreadcrumbItem> BreadcrumbItems
{
get => PageLayout.BreadcrumbItems.ToList();
set
{
PageLayout.BreadcrumbItems.Clear();
if (value != null)
{
foreach (var item in value)
{
PageLayout.BreadcrumbItems.Add(item);
}
}
}
}
[Parameter]
public PageToolbar? Toolbar { get; set; }
public PageHeader()
{
ToolbarItemRenders = new List<RenderFragment>();
}
protected async override Task OnParametersSetAsync()
{
await base.OnParametersSetAsync();
if (Toolbar != null)
{
var toolbarItems = await PageToolbarManager.GetItemsAsync(Toolbar);
if (!ShouldRenderToolbarItems(toolbarItems))
{
return;
}
ToolbarItemRenders.Clear();
if (!Options.Value.RenderToolbar)
{
PageLayout.ToolbarItems.Clear();
foreach (var item in toolbarItems)
{
PageLayout.ToolbarItems.Add(item);
}
return;
}
foreach (var item in toolbarItems)
{
var sequence = 0;
ToolbarItemRenders.Add(builder =>
{
builder.OpenComponent(sequence, item.ComponentType);
if (item.Arguments != null)
{
foreach (var argument in item.Arguments)
{
sequence++;
builder.AddAttribute(sequence, argument.Key, argument.Value);
}
}
builder.CloseComponent();
});
}
}
}
protected virtual bool ShouldRenderToolbarItems(PageToolbarItem[] items)
{
if (items.Length != PageLayout.ToolbarItems.Count)
{
return true;
}
return items.Where((t, i) => t.ComponentType != PageLayout.ToolbarItems[i].ComponentType).Any();
}
protected async override Task OnInitializedAsync()
{
await base.OnInitializedAsync();
}
public void Dispose()
{
PageLayout.Reset();
ToolbarItemRenders.Clear();
}
}

65
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Layout/PageHeader.razor

@ -0,0 +1,65 @@
@using global::MudBlazor
@using Microsoft.Extensions.Options
@using Microsoft.AspNetCore.Components.Web
@using Volo.Abp.Ui.Branding
@inject IOptions<PageHeaderOptions> Options
@inject IBrandingProvider BrandingProvider
<MudGrid Class="entry-row">
@if (PageLayout.Title.IsNullOrEmpty())
{
<PageTitle>@BrandingProvider.AppName</PageTitle>
}
else
{
<PageTitle>@PageLayout.Title | @BrandingProvider.AppName</PageTitle>
}
@if(Options.Value.RenderPageTitle)
{
<MudItem xs="12" sm="12">
<MudText Typo="Typo.h4" Class="content-header-title">@PageLayout.Title</MudText>
</MudItem>
}
@if (Options.Value.RenderBreadcrumbs && PageLayout.BreadcrumbItems.Any())
{
<MudItem xs="12" lg="12" Class="pl-lg-0">
<MudBreadcrumbs Items="_breadcrumbItems" Class="pa-0">
<ItemTemplate Context="item">
<MudLink Href="@item.Href">
@if (!string.IsNullOrEmpty(item.Icon))
{
<MudIcon Icon="@item.Icon" Size="Size.Small" Class="mr-1" />
}
@item.Text
</MudLink>
</ItemTemplate>
<SeparatorTemplate>
<MudIcon Icon="@Icons.Material.Filled.ChevronRight" Size="Size.Small" />
</SeparatorTemplate>
</MudBreadcrumbs>
</MudItem>
}
@if(Options.Value.RenderToolbar)
{
<MudItem xs="12" Class="d-flex justify-end flex-grow-1">
<MudStack Row="true" Spacing="2" Class="align-center">
@if (Toolbar == null)
{
@ChildContent
}
@foreach (var toolbarItemRender in ToolbarItemRenders)
{
<MudItem Class="px-1 py-2">
@toolbarItemRender
</MudItem>
}
</MudStack>
</MudItem>
}
</MudGrid>

199
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Layout/PageHeader.razor.cs

@ -0,0 +1,199 @@
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.Theming.MudBlazor.PageToolbars;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Layout;
public partial class PageHeader : ComponentBase, IDisposable
{
protected List<RenderFragment> ToolbarItemRenders { get; set; }
private List<BreadcrumbItem> _breadcrumbItems = new();
public IPageToolbarManager PageToolbarManager { get; set; } = default!;
[Inject]
public PageLayout PageLayout { get; private set; } = default!;
[Parameter] // TODO: Consider removing this property in future and use only PageLayout.
public string? Title { get => PageLayout.Title; set => PageLayout.Title = value; }
[Parameter]
public bool BreadcrumbShowHome { get; set; } = true;
[Parameter]
public bool BreadcrumbShowCurrent { get; set; } = true;
[Parameter]
public RenderFragment ChildContent { get; set; } = default!;
[Parameter] // TODO: Consider removing this property in future and use only PageLayout.
public List<BreadcrumbItem> BreadcrumbItems {
get => PageLayout.BreadcrumbItems.ToList();
set
{
PageLayout.BreadcrumbItems.Clear();
foreach (var item in value)
{
PageLayout.BreadcrumbItems.Add(item);
}
}
}
[Parameter]
public PageToolbar? Toolbar { get; set; }
public PageHeader()
{
ToolbarItemRenders = new List<RenderFragment>();
}
protected override async Task OnParametersSetAsync()
{
await base.OnParametersSetAsync();
// Build MudBlazor breadcrumb items
BuildBreadcrumbItems();
if (Toolbar != null)
{
var toolbarItems = await PageToolbarManager.GetItemsAsync(Toolbar);
if (!ShouldRenderToolbarItems(toolbarItems))
{
return;
}
ToolbarItemRenders.Clear();
if (!Options.Value.RenderToolbar)
{
PageLayout.ToolbarItems.Clear();
foreach (var item in toolbarItems)
{
PageLayout.ToolbarItems.Add(item);
}
return;
}
foreach (var item in toolbarItems)
{
var sequence = 0;
ToolbarItemRenders.Add(builder =>
{
builder.OpenComponent(sequence, item.ComponentType);
if (item.Arguments != null)
{
foreach (var argument in item.Arguments)
{
sequence++;
builder.AddAttribute(sequence, argument.Key, argument.Value);
}
}
builder.CloseComponent();
});
}
}
}
private void BuildBreadcrumbItems()
{
_breadcrumbItems.Clear();
if (BreadcrumbShowHome)
{
_breadcrumbItems.Add(new BreadcrumbItem(string.Empty, href: "/", icon: Icons.Material.Filled.Home));
}
var pageItems = PageLayout.BreadcrumbItems.ToList();
for (var i = 0; i < pageItems.Count; i++)
{
var item = pageItems[i];
var isLast = i == pageItems.Count - 1;
// Convert Blazorise icon to MudBlazor icon if needed
var mudIcon = ConvertToMudIcon(item.Icon);
// If BreadcrumbShowCurrent is false, skip the last item or make it non-clickable
if (isLast && !BreadcrumbShowCurrent)
{
continue;
}
_breadcrumbItems.Add(new BreadcrumbItem(
item.Text,
href: isLast ? null : item.Href,
disabled: isLast,
icon: mudIcon));
}
}
/// <summary>
/// Converts Blazorise icon to MudBlazor icon.
/// You may need to expand this mapping based on the icons used in your application.
/// </summary>
private static string? ConvertToMudIcon(object? blazoriseIcon)
{
if (blazoriseIcon == null)
{
return null;
}
// If it's already a string (MudBlazor icon format), return as-is
if (blazoriseIcon is string iconString)
{
return iconString;
}
// Map common Blazorise icons to MudBlazor icons
// Add more mappings as needed for your application
var iconName = blazoriseIcon.ToString();
return iconName switch
{
"Home" => Icons.Material.Filled.Home,
"Edit" => Icons.Material.Filled.Edit,
"Delete" => Icons.Material.Filled.Delete,
"Add" => Icons.Material.Filled.Add,
"Search" => Icons.Material.Filled.Search,
"Settings" => Icons.Material.Filled.Settings,
"User" => Icons.Material.Filled.Person,
"Users" => Icons.Material.Filled.People,
"File" => Icons.Material.Filled.InsertDriveFile,
"Folder" => Icons.Material.Filled.Folder,
"Dashboard" => Icons.Material.Filled.Dashboard,
"List" => Icons.Material.Filled.List,
"Check" => Icons.Material.Filled.Check,
"Times" => Icons.Material.Filled.Close,
"Warning" => Icons.Material.Filled.Warning,
"Info" => Icons.Material.Filled.Info,
"Question" => Icons.Material.Filled.Help,
_ => null // Return null for unmapped icons
};
}
protected virtual bool ShouldRenderToolbarItems(PageToolbarItem[] items)
{
if (items.Length != PageLayout.ToolbarItems.Count)
{
return true;
}
return items.Where((t, i) => t.ComponentType != PageLayout.ToolbarItems[i].ComponentType).Any();
}
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
}
public void Dispose()
{
PageLayout.Reset();
ToolbarItemRenders.Clear();
}
}

8
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Layout/PageHeaderOptions.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Layout;
public class PageHeaderOptions
{
public bool RenderPageTitle { get; set; } = true;
public bool RenderBreadcrumbs { get; set; } = true;
public bool RenderToolbar { get; set; } = true;
}

54
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Layout/PageLayout.cs

@ -0,0 +1,54 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using MudBlazor;
using Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Layout;
public class PageLayout : IScopedDependency, INotifyPropertyChanged
{
private string? title;
// TODO: Consider using this property for setting Page Title too.
public virtual string? Title {
get => title;
set {
title = value;
OnPropertyChanged();
}
}
private string? menuItemName;
public string? MenuItemName {
get => menuItemName;
set
{
menuItemName = value;
OnPropertyChanged();
}
}
public bool ShowToolbar { get; set; } = true;
public virtual ObservableCollection<BreadcrumbItem> BreadcrumbItems { get; } = new();
public virtual ObservableCollection<PageToolbarItem> ToolbarItems { get; } = new();
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void Reset()
{
Title = string.Empty;
MenuItemName = string.Empty;
BreadcrumbItems.Clear();
ToolbarItems.Clear();
}
}

9
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Layout/StandardLayouts.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Layout;
public static class StandardLayouts
{
public const string Application = "Application";
public const string Account = "Account";
public const string Public = "Public";
public const string Empty = "Empty";
}

8
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/IPageToolbarContributor.cs

@ -0,0 +1,8 @@
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public interface IPageToolbarContributor
{
Task ContributeAsync(PageToolbarContributionContext context);
}

8
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/IPageToolbarManager.cs

@ -0,0 +1,8 @@
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public interface IPageToolbarManager
{
Task<PageToolbarItem[]> GetItemsAsync(PageToolbar toolbar);
}

34
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/MudBlazorPageToolbarExtensions.cs

@ -1,34 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public static class MudBlazorPageToolbarExtensions
{
public static PageToolbar AddMudButton(
this PageToolbar toolbar,
string text,
Func<Task> clicked,
object? icon = null,
int order = 0,
string? requiredPolicyName = null)
{
toolbar.AddComponent(
typeof(MudPageToolbarButton),
new Dictionary<string, object?>
{
{ nameof(MudPageToolbarButton.Text), text },
{ nameof(MudPageToolbarButton.Disabled), false },
{ nameof(MudPageToolbarButton.Icon), icon },
{ nameof(MudPageToolbarButton.Clicked), clicked }
},
order,
requiredPolicyName
);
return toolbar;
}
}

13
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/MudPageToolbarButton.razor

@ -1,13 +0,0 @@
@using global::MudBlazor
<MudButton Variant="@Variant.Filled"
Color="@Color.Primary"
Disabled="Disabled"
OnClick="@OnClickCallback">
@if (Icon is string iconString && !string.IsNullOrWhiteSpace(iconString))
{
<MudIcon Icon="@iconString" Class="me-1" />
}
@Text
</MudButton>

33
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/MudPageToolbarButton.razor.cs

@ -1,33 +0,0 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using global::MudBlazor;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public partial class MudPageToolbarButton : ComponentBase
{
[Parameter]
public string Text { get; set; } = string.Empty;
[Parameter]
public bool Disabled { get; set; }
[Parameter]
public object? Icon { get; set; }
[Parameter]
public Func<Task>? Clicked { get; set; }
private EventCallback<MouseEventArgs> OnClickCallback => EventCallback.Factory.Create<MouseEventArgs>(this, OnClickAsync);
private async Task OnClickAsync(MouseEventArgs args)
{
if (Clicked != null && !Disabled)
{
await Clicked.Invoke();
}
await Task.CompletedTask;
}
}

11
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbar.cs

@ -0,0 +1,11 @@
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public class PageToolbar
{
public PageToolbarContributorList Contributors { get; set; }
public PageToolbar()
{
Contributors = new PageToolbarContributorList();
}
}

20
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarContributionContext.cs

@ -0,0 +1,20 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public class PageToolbarContributionContext
{
[NotNull]
public IServiceProvider ServiceProvider { get; }
[NotNull]
public PageToolbarItemList Items { get; }
public PageToolbarContributionContext(
[NotNull] IServiceProvider serviceProvider)
{
ServiceProvider = Check.NotNull(serviceProvider, nameof(serviceProvider));
Items = new PageToolbarItemList();
}
}

8
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarContributor.cs

@ -0,0 +1,8 @@
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public abstract class PageToolbarContributor : IPageToolbarContributor
{
public abstract Task ContributeAsync(PageToolbarContributionContext context);
}

7
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarContributorList.cs

@ -0,0 +1,7 @@
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public class PageToolbarContributorList : List<IPageToolbarContributor>
{
}

8
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarDictionary.cs

@ -0,0 +1,8 @@
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public class PageToolbarDictionary : Dictionary<string, PageToolbar>
{
}

69
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarExtensions.cs

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MudBlazor;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public static class PageToolbarExtensions
{
public static PageToolbar AddComponent<TComponent>(
this PageToolbar toolbar,
Dictionary<string, object?>? arguments = null,
int order = 0,
string? requiredPolicyName = null)
{
return toolbar.AddComponent(
typeof(TComponent),
arguments,
order,
requiredPolicyName
);
}
public static PageToolbar AddComponent(
this PageToolbar toolbar,
Type componentType,
Dictionary<string, object?>? arguments = null,
int order = 0,
string? requiredPolicyName = null)
{
toolbar.Contributors.Add(
new SimplePageToolbarContributor(
componentType,
arguments,
order,
requiredPolicyName
)
);
return toolbar;
}
public static PageToolbar AddButton(
this PageToolbar toolbar,
string text,
Func<Task> clicked,
object? icon = null,
Color? color = null,
bool disabled = false,
int order = 0,
string? requiredPolicyName = null)
{
// TODO@MudBlazor: Implement ToolbarButton contributor
// toolbar.AddComponent<ToolbarButton>(
// new Dictionary<string, object?>
// {
// { nameof(ToolbarButton.Color), color ?? Color.Primary},
// { nameof(ToolbarButton.Text), text},
// { nameof(ToolbarButton.Disabled), disabled},
// { nameof(ToolbarButton.Icon), icon},
// { nameof(ToolbarButton.Clicked),clicked},
// },
// order,
// requiredPolicyName
// );
return toolbar;
}
}

25
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarItem.cs

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public class PageToolbarItem
{
[NotNull]
public Type ComponentType { get; }
public Dictionary<string, object?>? Arguments { get; set; }
public int Order { get; set; }
public PageToolbarItem(
[NotNull] Type componentType,
Dictionary<string, object?>? arguments = null,
int order = 0)
{
ComponentType = Check.NotNull(componentType, nameof(componentType));
Arguments = arguments;
Order = order;
}
}

8
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarItemList.cs

@ -0,0 +1,8 @@
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public class PageToolbarItemList : List<PageToolbarItem>
{
}

38
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/PageToolbarManager.cs

@ -0,0 +1,38 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public class PageToolbarManager : IPageToolbarManager, ITransientDependency
{
protected IServiceScopeFactory ServiceScopeFactory { get; }
public PageToolbarManager(
IServiceScopeFactory serviceScopeFactory)
{
ServiceScopeFactory = serviceScopeFactory;
}
public virtual async Task<PageToolbarItem[]> GetItemsAsync(PageToolbar toolbar)
{
if (toolbar == null || !toolbar.Contributors.Any())
{
return Array.Empty<PageToolbarItem>();
}
using (var scope = ServiceScopeFactory.CreateScope())
{
var context = new PageToolbarContributionContext(scope.ServiceProvider);
foreach (var contributor in toolbar.Contributors)
{
await contributor.ContributeAsync(context);
}
return context.Items.OrderBy(i => i.Order).ToArray();
}
}
}

58
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/PageToolbars/SimplePageToolbarContributor.cs

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.PageToolbars;
public class SimplePageToolbarContributor : IPageToolbarContributor
{
public Type ComponentType { get; }
public Dictionary<string, object?>? Arguments { get; set; }
public int Order { get; }
public string? RequiredPolicyName { get; }
private bool? _shouldAddComponent;
public SimplePageToolbarContributor(
Type componentType,
Dictionary<string, object?>? arguments = null,
int order = 0,
string? requiredPolicyName = null)
{
ComponentType = componentType;
Arguments = arguments;
Order = order;
RequiredPolicyName = requiredPolicyName;
}
public async Task ContributeAsync(PageToolbarContributionContext context)
{
if (await ShouldAddComponentAsync(context))
{
context.Items.Add(new PageToolbarItem(ComponentType, Arguments, Order));
}
}
protected virtual async Task<bool> ShouldAddComponentAsync(PageToolbarContributionContext context)
{
if (_shouldAddComponent.HasValue)
{
return _shouldAddComponent.Value;
}
if (RequiredPolicyName == null)
{
_shouldAddComponent = true;
return _shouldAddComponent.Value;
}
var authorizationService = context.ServiceProvider.GetRequiredService<IAuthorizationService>();
_shouldAddComponent = await authorizationService.IsGrantedAsync(RequiredPolicyName);
return _shouldAddComponent.Value;
}
}

15
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Routing/AbpRouterOptions.cs

@ -0,0 +1,15 @@
using System.Reflection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Routing;
public class AbpRouterOptions
{
public Assembly AppAssembly { get; set; } = default!;
public RouterAssemblyList AdditionalAssemblies { get; }
public AbpRouterOptions()
{
AdditionalAssemblies = new RouterAssemblyList();
}
}

9
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Routing/RouterAssemblyList.cs

@ -0,0 +1,9 @@
using System.Collections.Generic;
using System.Reflection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Routing;
public class RouterAssemblyList : List<Assembly>
{
}

13
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/AbpThemingOptions.cs

@ -0,0 +1,13 @@
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Theming;
public class AbpThemingOptions
{
public ThemeDictionary Themes { get; }
public string? DefaultThemeName { get; set; }
public AbpThemingOptions()
{
Themes = new ThemeDictionary();
}
}

34
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/DefaultThemeManager.cs

@ -0,0 +1,34 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Theming;
public class DefaultThemeManager : IThemeManager, IScopedDependency, IServiceProviderAccessor
{
public IServiceProvider ServiceProvider { get; }
public ITheme CurrentTheme => GetCurrentTheme();
private ITheme? _currentTheme;
protected IThemeSelector ThemeSelector { get; }
public DefaultThemeManager(
IServiceProvider serviceProvider,
IThemeSelector themeSelector)
{
ServiceProvider = serviceProvider;
ThemeSelector = themeSelector;
}
protected virtual ITheme GetCurrentTheme()
{
if (_currentTheme != null)
{
return _currentTheme;
}
_currentTheme = (ITheme)ServiceProvider.GetRequiredService(ThemeSelector.GetCurrentThemeInfo().ThemeType);
return _currentTheme;
}
}

36
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/DefaultThemeSelector.cs

@ -0,0 +1,36 @@
using System.Linq;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Theming;
public class DefaultThemeSelector : IThemeSelector, ITransientDependency
{
protected AbpThemingOptions Options { get; }
public DefaultThemeSelector(IOptions<AbpThemingOptions> options)
{
Options = options.Value;
}
public virtual ThemeInfo GetCurrentThemeInfo()
{
if (!Options.Themes.Any())
{
throw new AbpException($"No theme registered! Use {nameof(AbpThemingOptions)} to register themes.");
}
if (Options.DefaultThemeName == null)
{
return Options.Themes.Values.First();
}
var themeInfo = Options.Themes.Values.FirstOrDefault(t => t.Name == Options.DefaultThemeName);
if (themeInfo == null)
{
throw new AbpException("Default theme is configured but it's not found in the registered themes: " + Options.DefaultThemeName);
}
return themeInfo;
}
}

8
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/ITheme.cs

@ -0,0 +1,8 @@
using System;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Theming;
public interface ITheme
{
Type GetLayout(string name, bool fallbackToDefault = true);
}

6
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/IThemeManager.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Theming;
public interface IThemeManager
{
ITheme CurrentTheme { get; }
}

6
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/IThemeSelector.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Theming;
public interface IThemeSelector
{
ThemeInfo GetCurrentThemeInfo();
}

23
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/ThemeDictionary.cs

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Theming;
public class ThemeDictionary : Dictionary<Type, ThemeInfo>
{
public ThemeInfo Add<TTheme>()
where TTheme : ITheme
{
return Add(typeof(TTheme));
}
public ThemeInfo Add(Type themeType)
{
if (ContainsKey(themeType))
{
throw new AbpException("This theme is already added before: " + themeType.AssemblyQualifiedName);
}
return this[themeType] = new ThemeInfo(themeType);
}
}

27
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/ThemeExtensions.cs

@ -0,0 +1,27 @@
using System;
using Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Layout;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Theming;
public static class ThemeExtensions
{
public static Type GetApplicationLayout(this ITheme theme, bool fallbackToDefault = true)
{
return theme.GetLayout(StandardLayouts.Application, fallbackToDefault);
}
public static Type GetAccountLayout(this ITheme theme, bool fallbackToDefault = true)
{
return theme.GetLayout(StandardLayouts.Account, fallbackToDefault);
}
public static Type GetPublicLayout(this ITheme theme, bool fallbackToDefault = true)
{
return theme.GetLayout(StandardLayouts.Public, fallbackToDefault);
}
public static Type GetEmptyLayout(this ITheme theme, bool fallbackToDefault = true)
{
return theme.GetLayout(StandardLayouts.Empty, fallbackToDefault);
}
}

24
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/ThemeInfo.cs

@ -0,0 +1,24 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Theming;
public class ThemeInfo
{
public Type ThemeType { get; }
public string Name { get; }
public ThemeInfo([NotNull] Type themeType)
{
Check.NotNull(themeType, nameof(themeType));
if (!typeof(ITheme).IsAssignableFrom(themeType))
{
throw new AbpException($"Given {nameof(themeType)} ({themeType.AssemblyQualifiedName}) should be type of {typeof(ITheme).AssemblyQualifiedName}");
}
ThemeType = themeType;
Name = ThemeNameAttribute.GetName(themeType);
}
}

23
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Theming/ThemeNameAttribute.cs

@ -0,0 +1,23 @@
using System;
using System.Linq;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Theming;
[AttributeUsage(AttributeTargets.Class)]
public class ThemeNameAttribute : Attribute
{
public string Name { get; set; }
public ThemeNameAttribute(string name)
{
Name = name;
}
public static string GetName(Type themeType)
{
return themeType
.GetCustomAttributes(true)
.OfType<ThemeNameAttribute>()
.FirstOrDefault()?.Name ?? themeType.Name;
}
}

15
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/AbpToolbarOptions.cs

@ -0,0 +1,15 @@
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Toolbars;
public class AbpToolbarOptions
{
[NotNull]
public List<IToolbarContributor> Contributors { get; }
public AbpToolbarOptions()
{
Contributors = new List<IToolbarContributor>();
}
}

27
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/IToolbarConfigurationContext.cs

@ -0,0 +1,27 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Localization;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Toolbars;
public interface IToolbarConfigurationContext : IServiceProviderAccessor
{
Toolbar Toolbar { get; }
IAuthorizationService AuthorizationService { get; }
IStringLocalizerFactory StringLocalizerFactory { get; }
Task<bool> IsGrantedAsync(string policyName);
IStringLocalizer? GetDefaultLocalizer();
[NotNull]
public IStringLocalizer GetLocalizer<T>();
[NotNull]
public IStringLocalizer GetLocalizer(Type resourceType);
}

8
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/IToolbarContributor.cs

@ -0,0 +1,8 @@
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Toolbars;
public interface IToolbarContributor
{
Task ConfigureToolbarAsync(IToolbarConfigurationContext context);
}

8
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/IToolbarManager.cs

@ -0,0 +1,8 @@
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Toolbars;
public interface IToolbarManager
{
Task<Toolbar> GetAsync(string name);
}

6
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/StandardToolbars.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Toolbars;
public static class StandardToolbars
{
public const string Main = "Main";
}

17
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/Toolbar.cs

@ -0,0 +1,17 @@
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Toolbars;
public class Toolbar
{
public string Name { get; }
public List<ToolbarItem> Items { get; }
public Toolbar([NotNull] string name)
{
Name = Check.NotNull(name, nameof(name));
Items = new List<ToolbarItem>();
}
}

51
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/ToolbarConfigurationContext.cs

@ -0,0 +1,51 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Toolbars;
public class ToolbarConfigurationContext : IToolbarConfigurationContext
{
public IServiceProvider ServiceProvider { get; }
private readonly IAbpLazyServiceProvider _lazyServiceProvider;
public IAuthorizationService AuthorizationService => _lazyServiceProvider.LazyGetRequiredService<IAuthorizationService>();
public IStringLocalizerFactory StringLocalizerFactory => _lazyServiceProvider.LazyGetRequiredService<IStringLocalizerFactory>();
public Toolbar Toolbar { get; }
public ToolbarConfigurationContext(Toolbar toolbar, IServiceProvider serviceProvider)
{
Toolbar = toolbar;
ServiceProvider = serviceProvider;
_lazyServiceProvider = ServiceProvider.GetRequiredService<IAbpLazyServiceProvider>();
}
public Task<bool> IsGrantedAsync(string policyName)
{
return AuthorizationService.IsGrantedAsync(policyName);
}
public IStringLocalizer? GetDefaultLocalizer()
{
return StringLocalizerFactory.CreateDefaultOrNull();
}
[NotNull]
public IStringLocalizer GetLocalizer<T>()
{
return StringLocalizerFactory.Create<T>();
}
[NotNull]
public IStringLocalizer GetLocalizer(Type resourceType)
{
return StringLocalizerFactory.Create(resourceType);
}
}

21
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/ToolbarItem.cs

@ -0,0 +1,21 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Toolbars;
public class ToolbarItem
{
public Type ComponentType {
get => _componentType;
set => _componentType = Check.NotNull(value, nameof(value));
}
private Type _componentType = default!;
public int Order { get; set; }
public ToolbarItem([NotNull] Type componentType, int order = 0)
{
Order = order;
ComponentType = Check.NotNull(componentType, nameof(componentType));
}
}

38
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Toolbars/ToolbarManager.cs

@ -0,0 +1,38 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Toolbars;
public class ToolbarManager : IToolbarManager, ITransientDependency
{
protected AbpToolbarOptions Options { get; }
protected IServiceProvider ServiceProvider { get; }
public ToolbarManager(
IOptions<AbpToolbarOptions> options,
IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
Options = options.Value;
}
public async Task<Toolbar> GetAsync(string name)
{
var toolbar = new Toolbar(name);
using (var scope = ServiceProvider.CreateScope())
{
var context = new ToolbarConfigurationContext(toolbar, scope.ServiceProvider);
foreach (var contributor in Options.Contributors)
{
await contributor.ConfigureToolbarAsync(context);
}
}
return toolbar;
}
}

11
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.csproj

@ -10,8 +10,17 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.Web.Theming\Volo.Abp.AspNetCore.Components.Web.Theming.csproj" />
<ProjectReference Include="..\Volo.Abp.MudBlazorUI\Volo.Abp.MudBlazorUI.csproj" /> <ProjectReference Include="..\Volo.Abp.MudBlazorUI\Volo.Abp.MudBlazorUI.csproj" />
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.Web\Volo.Abp.AspNetCore.Components.Web.csproj" />
<ProjectReference Include="..\Volo.Abp.Authorization\Volo.Abp.Authorization.csproj" />
<ProjectReference Include="..\Volo.Abp.Ddd.Application.Contracts\Volo.Abp.Ddd.Application.Contracts.csproj" />
<ProjectReference Include="..\Volo.Abp.Features\Volo.Abp.Features.csproj" />
<ProjectReference Include="..\Volo.Abp.GlobalFeatures\Volo.Abp.GlobalFeatures.csproj" />
<ProjectReference Include="..\Volo.Abp.UI.Navigation\Volo.Abp.UI.Navigation.csproj" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="Layout\PageHeader.razor" />
</ItemGroup> </ItemGroup>
</Project> </Project>

6
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/_Imports.razor

@ -1,6 +0,0 @@
@using MudBlazor
@using Volo.Abp.AspNetCore.Components.Web.Theming
@using Volo.Abp.AspNetCore.Components.Web.Theming.Layout
@using Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars
@using Volo.Abp.BlazoriseUI

17
framework/src/Volo.Abp.MudBlazorUI/BreadcrumbItem.cs

@ -0,0 +1,17 @@
namespace Volo.Abp.MudBlazorUI;
public class BreadcrumbItem
{
public string Text { get; set; }
public object? Icon { get; set; }
public string? Url { get; set; }
public BreadcrumbItem(string text, string? url = null, object? icon = null)
{
Text = text;
Url = url;
Icon = icon;
}
}

24
framework/src/Volo.Abp.MudBlazorUI/Components/AbpMudExtensibleDataGrid.razor.cs

@ -71,30 +71,20 @@ public partial class AbpMudExtensibleDataGrid<TItem> : ComponentBase
return convertedValue; return convertedValue;
} }
protected virtual object? GetPropertyValue(TItem? item, string propertyPath) protected virtual object GetPropertyValue(TItem item, string propertyPath)
{ {
if (item == null) ArgumentNullException.ThrowIfNull(item);
{
return null;
}
var properties = propertyPath.Split('.'); var properties = propertyPath.Split('.');
object? value = item; object value = item;
foreach (var prop in properties) foreach (var prop in properties)
{ {
if (value == null) var propertyInfo = value.GetType().GetProperty(prop, BindingFlags.Public | BindingFlags.Instance)
{ ?? throw new ArgumentException($"Property '{prop}' not found on type '{value.GetType().Name}'", nameof(propertyPath));
return null;
}
var propertyInfo = value.GetType().GetProperty(prop, BindingFlags.Public | BindingFlags.Instance);
if (propertyInfo == null)
{
return null;
}
value = propertyInfo.GetValue(value); value = propertyInfo.GetValue(value)
?? throw new InvalidOperationException($"Property '{prop}' returned null");
} }
return value; return value;

3
modules/feature-management/Volo.Abp.FeatureManagement.slnx

@ -2,6 +2,9 @@
<Folder Name="/src/"> <Folder Name="/src/">
<Project Path="src/Volo.Abp.FeatureManagement.Application.Contracts/Volo.Abp.FeatureManagement.Application.Contracts.csproj" /> <Project Path="src/Volo.Abp.FeatureManagement.Application.Contracts/Volo.Abp.FeatureManagement.Application.Contracts.csproj" />
<Project Path="src/Volo.Abp.FeatureManagement.Application/Volo.Abp.FeatureManagement.Application.csproj" /> <Project Path="src/Volo.Abp.FeatureManagement.Application/Volo.Abp.FeatureManagement.Application.csproj" />
<Project Path="src/Volo.Abp.FeatureManagement.Blazor.MudBlazor.Server/Volo.Abp.FeatureManagement.Blazor.MudBlazor.Server.csproj" />
<Project Path="src/Volo.Abp.FeatureManagement.Blazor.MudBlazor.WebAssembly/Volo.Abp.FeatureManagement.Blazor.MudBlazor.WebAssembly.csproj" />
<Project Path="src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Volo.Abp.FeatureManagement.Blazor.MudBlazor.csproj" />
<Project Path="src/Volo.Abp.FeatureManagement.Blazor.Server/Volo.Abp.FeatureManagement.Blazor.Server.csproj" /> <Project Path="src/Volo.Abp.FeatureManagement.Blazor.Server/Volo.Abp.FeatureManagement.Blazor.Server.csproj" />
<Project Path="src/Volo.Abp.FeatureManagement.Blazor.WebAssembly/Volo.Abp.FeatureManagement.Blazor.WebAssembly.csproj" /> <Project Path="src/Volo.Abp.FeatureManagement.Blazor.WebAssembly/Volo.Abp.FeatureManagement.Blazor.WebAssembly.csproj" />
<Project Path="src/Volo.Abp.FeatureManagement.Blazor/Volo.Abp.FeatureManagement.Blazor.csproj" /> <Project Path="src/Volo.Abp.FeatureManagement.Blazor/Volo.Abp.FeatureManagement.Blazor.csproj" />

9
modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Components/FeatureManagementModal.razor

@ -1,3 +1,5 @@
@using global::MudBlazor
@using JetBrains.Annotations
@using Volo.Abp.Validation.StringValues @using Volo.Abp.Validation.StringValues
@using Microsoft.Extensions.Localization @using Microsoft.Extensions.Localization
@using MudBlazor @using MudBlazor
@ -33,7 +35,7 @@
<MudTextField Label="@GetShownName(feature)" <MudTextField Label="@GetShownName(feature)"
Disabled="@disabled" Disabled="@disabled"
Value="@feature.Value" Value="@feature.Value"
ValueChanged="@(async (v) => await OnFeatureValueChangedAsync(v, feature))" ValueChanged="@(async ([CanBeNull] string v) => await OnFeatureValueChangedAsync(v, feature))"
Variant="Variant.Outlined" /> Variant="Variant.Outlined" />
@if (feature.Description != null) @if (feature.Description != null)
{ {
@ -66,9 +68,8 @@
@if (feature.ValueType is ToggleStringValueType) @if (feature.ValueType is ToggleStringValueType)
{ {
<MudCheckBox Disabled="@disabled" <MudCheckBox Disabled="@disabled" Value="@ToggleValues[feature.Name]"
Checked="@ToggleValues[feature.Name]" ValueChanged="@(async (bool v) => await OnSelectedValueChangedAsync(v, feature))"
CheckedChanged="@(async (v) => await OnSelectedValueChangedAsync(v, feature))"
Label="@GetShownName(feature)" /> Label="@GetShownName(feature)" />
@if (feature.Description != null) @if (feature.Description != null)
{ {

3
modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Components/FeatureSettingGroup/FeatureSettingManagementComponent.razor

@ -1,5 +1,4 @@
@using MudBlazor @using global::MudBlazor
@using Volo.Abp.FeatureManagement.Localization
@inherits Volo.Abp.AspNetCore.Components.AbpComponentBase @inherits Volo.Abp.AspNetCore.Components.AbpComponentBase
@if (Settings != null && Settings.HasManageHostFeaturesPermission) @if (Settings != null && Settings.HasManageHostFeaturesPermission)

3
modules/setting-management/Volo.Abp.SettingManagement.slnx

@ -5,6 +5,9 @@
<Folder Name="/src/"> <Folder Name="/src/">
<Project Path="src/Volo.Abp.SettingManagement.Application.Contracts/Volo.Abp.SettingManagement.Application.Contracts.csproj" /> <Project Path="src/Volo.Abp.SettingManagement.Application.Contracts/Volo.Abp.SettingManagement.Application.Contracts.csproj" />
<Project Path="src/Volo.Abp.SettingManagement.Application/Volo.Abp.SettingManagement.Application.csproj" /> <Project Path="src/Volo.Abp.SettingManagement.Application/Volo.Abp.SettingManagement.Application.csproj" />
<Project Path="src/Volo.Abp.SettingManagement.Blazor.MudBlazor.Server/Volo.Abp.SettingManagement.Blazor.MudBlazor.Server.csproj" />
<Project Path="src/Volo.Abp.SettingManagement.Blazor.MudBlazor.WebAssembly/Volo.Abp.SettingManagement.Blazor.MudBlazor.WebAssembly.csproj" />
<Project Path="src/Volo.Abp.SettingManagement.Blazor.MudBlazor/Volo.Abp.SettingManagement.Blazor.MudBlazor.csproj" />
<Project Path="src/Volo.Abp.SettingManagement.Blazor.Server/Volo.Abp.SettingManagement.Blazor.Server.csproj" /> <Project Path="src/Volo.Abp.SettingManagement.Blazor.Server/Volo.Abp.SettingManagement.Blazor.Server.csproj" />
<Project Path="src/Volo.Abp.SettingManagement.Blazor.WebAssembly/Volo.Abp.SettingManagement.Blazor.WebAssembly.csproj" /> <Project Path="src/Volo.Abp.SettingManagement.Blazor.WebAssembly/Volo.Abp.SettingManagement.Blazor.WebAssembly.csproj" />
<Project Path="src/Volo.Abp.SettingManagement.Blazor/Volo.Abp.SettingManagement.Blazor.csproj" /> <Project Path="src/Volo.Abp.SettingManagement.Blazor/Volo.Abp.SettingManagement.Blazor.csproj" />

3
modules/setting-management/src/Volo.Abp.SettingManagement.Blazor.MudBlazor/AbpSettingManagementBlazorMudBlazorModule.cs

@ -1,13 +1,12 @@
using Localization.Resources.AbpUi; using Localization.Resources.AbpUi;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor; using Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor;
using Volo.Abp.AspNetCore.Components.Web.Theming.Routing;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Mapperly; using Volo.Abp.Mapperly;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.SettingManagement.Blazor.MudBlazor.Menus; using Volo.Abp.SettingManagement.Blazor.MudBlazor.Menus;
using Volo.Abp.SettingManagement.Blazor.MudBlazor.Settings; using Volo.Abp.SettingManagement.Blazor.MudBlazor.Settings;
using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Routing;
using Volo.Abp.SettingManagement.Localization; using Volo.Abp.SettingManagement.Localization;
using Volo.Abp.UI.Navigation; using Volo.Abp.UI.Navigation;

16
modules/setting-management/src/Volo.Abp.SettingManagement.Blazor.MudBlazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor.cs

@ -63,7 +63,13 @@ public partial class EmailSettingGroupViewComponent
{ {
try try
{ {
if (_emailFormRef != null && !await _emailFormRef.Validate()) if (_emailFormRef == null)
{
return;
}
await _emailFormRef.Validate();
if (!_emailFormRef.IsValid)
{ {
return; return;
} }
@ -121,7 +127,13 @@ public partial class EmailSettingGroupViewComponent
{ {
try try
{ {
if (_testEmailFormRef != null && !await _testEmailFormRef.Validate()) if (_testEmailFormRef == null)
{
return;
}
await _testEmailFormRef.Validate();
if (!_testEmailFormRef.IsValid)
{ {
return; return;
} }

4
modules/setting-management/src/Volo.Abp.SettingManagement.Blazor.MudBlazor/Pages/SettingManagement/SettingManagement.razor.cs

@ -5,7 +5,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.BlazoriseUI; using Volo.Abp.MudBlazorUI;
using Volo.Abp.SettingManagement.Localization; using Volo.Abp.SettingManagement.Localization;
namespace Volo.Abp.SettingManagement.Blazor.MudBlazor.Pages.SettingManagement; namespace Volo.Abp.SettingManagement.Blazor.MudBlazor.Pages.SettingManagement;
@ -28,7 +28,7 @@ public partial class SettingManagement
protected List<RenderFragment> SettingItemRenders { get; set; } = new List<RenderFragment>(); protected List<RenderFragment> SettingItemRenders { get; set; } = new List<RenderFragment>();
protected string? SelectedGroup; protected string? SelectedGroup;
protected List<BreadcrumbItem> BreadcrumbItems = new List<BreadcrumbItem>(); protected List<BreadcrumbItem> BreadcrumbItems = new();
protected int _activeTabIndex = 0; protected int _activeTabIndex = 0;

3
modules/tenant-management/Volo.Abp.TenantManagement.slnx

@ -2,6 +2,9 @@
<Folder Name="/src/"> <Folder Name="/src/">
<Project Path="src/Volo.Abp.TenantManagement.Application.Contracts/Volo.Abp.TenantManagement.Application.Contracts.csproj" /> <Project Path="src/Volo.Abp.TenantManagement.Application.Contracts/Volo.Abp.TenantManagement.Application.Contracts.csproj" />
<Project Path="src/Volo.Abp.TenantManagement.Application/Volo.Abp.TenantManagement.Application.csproj" /> <Project Path="src/Volo.Abp.TenantManagement.Application/Volo.Abp.TenantManagement.Application.csproj" />
<Project Path="src/Volo.Abp.TenantManagement.Blazor.MudBlazor.Server/Volo.Abp.TenantManagement.Blazor.MudBlazor.Server.csproj" />
<Project Path="src/Volo.Abp.TenantManagement.Blazor.MudBlazor.WebAssembly/Volo.Abp.TenantManagement.Blazor.MudBlazor.WebAssembly.csproj" />
<Project Path="src/Volo.Abp.TenantManagement.Blazor.MudBlazor/Volo.Abp.TenantManagement.Blazor.MudBlazor.csproj" />
<Project Path="src/Volo.Abp.TenantManagement.Blazor.Server/Volo.Abp.TenantManagement.Blazor.Server.csproj" /> <Project Path="src/Volo.Abp.TenantManagement.Blazor.Server/Volo.Abp.TenantManagement.Blazor.Server.csproj" />
<Project Path="src/Volo.Abp.TenantManagement.Blazor.WebAssembly/Volo.Abp.TenantManagement.Blazor.WebAssembly.csproj" /> <Project Path="src/Volo.Abp.TenantManagement.Blazor.WebAssembly/Volo.Abp.TenantManagement.Blazor.WebAssembly.csproj" />
<Project Path="src/Volo.Abp.TenantManagement.Blazor/Volo.Abp.TenantManagement.Blazor.csproj" /> <Project Path="src/Volo.Abp.TenantManagement.Blazor/Volo.Abp.TenantManagement.Blazor.csproj" />

3
modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor.MudBlazor/AbpTenantManagementBlazorMudBlazorModule.cs

@ -1,6 +1,5 @@
using Localization.Resources.AbpUi; using Localization.Resources.AbpUi;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Components.Web.Theming.Routing;
using Volo.Abp.Mapperly; using Volo.Abp.Mapperly;
using Volo.Abp.FeatureManagement.Blazor.MudBlazor; using Volo.Abp.FeatureManagement.Blazor.MudBlazor;
using Volo.Abp.FeatureManagement.Localization; using Volo.Abp.FeatureManagement.Localization;
@ -9,7 +8,7 @@ using Volo.Abp.Modularity;
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
using Volo.Abp.ObjectExtending.Modularity; using Volo.Abp.ObjectExtending.Modularity;
using Volo.Abp.TenantManagement.Blazor.MudBlazor.Navigation; using Volo.Abp.TenantManagement.Blazor.MudBlazor.Navigation;
using Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor; using Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.Routing;
using Volo.Abp.TenantManagement.Localization; using Volo.Abp.TenantManagement.Localization;
using Volo.Abp.Threading; using Volo.Abp.Threading;
using Volo.Abp.UI.Navigation; using Volo.Abp.UI.Navigation;

9
modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor.MudBlazor/Pages/TenantManagement/TenantManagement.razor.cs

@ -143,10 +143,17 @@ public partial class TenantManagement
protected override async Task CreateEntityAsync() protected override async Task CreateEntityAsync()
{ {
if (_createFormRef != null && !await _createFormRef.Validate()) if (_createFormRef == null)
{ {
return; return;
} }
await _createFormRef.Validate();
if (!_createFormRef.IsValid)
{
return;
}
await base.CreateEntityAsync(); await base.CreateEntityAsync();
} }

Loading…
Cancel
Save