Browse Source

created feature management module pages for MudBlazor

pull/25235/head
İsmail ÇAĞDAŞ 9 months ago
parent
commit
4393a24d7c
  1. 12
      modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/AbpFeatureManagementComponentBase.cs
  2. 90
      modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Components/FeatureManagementModal.razor
  3. 263
      modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Components/FeatureManagementModal.razor.cs
  4. 19
      modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Components/FeatureSettingGroup/FeatureSettingManagementComponent.razor
  5. 41
      modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Components/FeatureSettingGroup/FeatureSettingManagementComponent.razor.cs
  6. 6
      modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Components/FeatureSettingGroup/FeatureSettingViewModel.cs
  7. 41
      modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Settings/FeatureSettingManagementComponentContributor.cs
  8. 4
      modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/_Imports.razor

12
modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/AbpFeatureManagementComponentBase.cs

@ -0,0 +1,12 @@
using Volo.Abp.AspNetCore.Components;
using Volo.Abp.FeatureManagement.Localization;
namespace Volo.Abp.FeatureManagement.Blazor.MudBlazor;
public abstract class AbpFeatureManagementComponentBase : AbpComponentBase
{
protected AbpFeatureManagementComponentBase()
{
LocalizationResource = typeof(AbpFeatureManagementResource);
}
}

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

@ -0,0 +1,90 @@
@using Volo.Abp.Validation.StringValues
@using Microsoft.Extensions.Localization
@using MudBlazor
@using Volo.Abp.FeatureManagement.Localization
@inherits AbpFeatureManagementComponentBase
<MudDialog @bind-IsVisible="@_isVisible" Options="@(new DialogOptions { MaxWidth = MaxWidth.Large, FullWidth = true })" CloseOnEscapeKey="true">
<TitleContent>
<MudText Typo="Typo.h6">@L["Features"]@ProviderKeyDisplayName</MudText>
</TitleContent>
<DialogContent>
@if (Groups == null || !Groups.Any())
{
<MudText Class="m-3">@L["NoFeatureFoundMessage"]</MudText>
}
else
{
<MudTabs @bind-ActivePanelIndex="@_activeTabIndex"
Variant="Variant.Pills"
Position="Position.Left"
PanelClass="pa-4">
@foreach (var group in Groups)
{
<MudTabPanel Text="@group.DisplayName">
<MudText Typo="Typo.h6" Class="mb-3">@group.DisplayName</MudText>
<MudDivider Class="my-2" />
@foreach (var feature in group.Features)
{
var disabled = IsDisabled(feature);
<div class="mt-2" style="@GetFeatureStyles(feature)">
@if (feature.ValueType is FreeTextStringValueType)
{
<MudTextField Label="@GetShownName(feature)"
Disabled="@disabled"
Value="@feature.Value"
ValueChanged="@(async (v) => await OnFeatureValueChangedAsync(v, feature))"
Variant="Variant.Outlined" />
@if (feature.Description != null)
{
<MudText Typo="Typo.caption" Class="mt-1">@feature.Description</MudText>
}
}
@if (feature.ValueType is SelectionStringValueType)
{
var items = ((SelectionStringValueType)feature.ValueType).ItemSource.Items;
var selectedValue = SelectionStringValues[feature.Name];
<MudSelect T="string"
Label="@GetShownName(feature)"
Disabled="@disabled"
Value="@selectedValue"
ValueChanged="@(s => SelectionStringValues[feature.Name] = s)"
Variant="Variant.Outlined">
@foreach (var item in items)
{
<MudSelectItem Value="@item.Value">
@CreateStringLocalizer(item.DisplayText.ResourceName).GetString(item.DisplayText.Name)
</MudSelectItem>
}
</MudSelect>
@if (feature.Description != null)
{
<MudText Typo="Typo.caption" Class="mt-1">@feature.Description</MudText>
}
}
@if (feature.ValueType is ToggleStringValueType)
{
<MudCheckBox Disabled="@disabled"
Checked="@ToggleValues[feature.Name]"
CheckedChanged="@(async (v) => await OnSelectedValueChangedAsync(v, feature))"
Label="@GetShownName(feature)" />
@if (feature.Description != null)
{
<MudText Typo="Typo.caption" Class="mt-1">@feature.Description</MudText>
}
}
</div>
}
</MudTabPanel>
}
</MudTabs>
}
</DialogContent>
<DialogActions>
<MudButton OnClick="@CloseModal">@L["Cancel"]</MudButton>
<MudButton Color="Color.Primary" Variant="Variant.Text" OnClick="@(async () => await DeleteAsync(ProviderName, ProviderKey))">@L["ResetToDefault"]</MudButton>
<MudButton Color="Color.Primary" Variant="Variant.Filled" OnClick="@SaveAsync">@L["Save"]</MudButton>
</DialogActions>
</MudDialog>

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

@ -0,0 +1,263 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using MudBlazor;
using Volo.Abp.AspNetCore.Components.Messages;
using Volo.Abp.AspNetCore.Components.Web.Configuration;
using Volo.Abp.FeatureManagement.Blazor.MudBlazor;
using Volo.Abp.Features;
using Volo.Abp.Localization;
using Volo.Abp.Validation.StringValues;
namespace Volo.Abp.FeatureManagement.Blazor.MudBlazor.Components;
public partial class FeatureManagementModal
{
[Inject] protected IFeatureAppService FeatureAppService { get; set; } = default!;
[Inject] protected IUiMessageService UiMessageService { get; set; } = default!;
[Inject] protected IStringLocalizerFactory HtmlLocalizerFactory { get; set; } = default!;
[Inject] protected IOptions<AbpLocalizationOptions> LocalizationOptions { get; set; } = default!;
[Inject] protected ICurrentApplicationConfigurationCacheResetService CurrentApplicationConfigurationCacheResetService { get; set; } = default!;
[Inject] protected ISnackbar Snackbar { get; set; } = default!;
[Inject] protected IDialogService DialogService { get; set; } = default!;
protected bool _isVisible;
protected int _activeTabIndex = 0;
protected string? ProviderName;
protected string? ProviderKey;
protected string? ProviderKeyDisplayName;
protected List<FeatureGroupDto>? Groups { get; set; }
protected Dictionary<string, bool> ToggleValues = new();
protected Dictionary<string, string> SelectionStringValues = new();
public virtual async Task OpenAsync(string providerName, string? providerKey = null, string? providerKeyDisplayName = null)
{
try
{
ProviderName = providerName;
ProviderKey = providerKey;
ToggleValues = new Dictionary<string, bool>();
SelectionStringValues = new Dictionary<string, string>();
if (!providerKeyDisplayName.IsNullOrWhiteSpace())
{
ProviderKeyDisplayName = $" - {providerKeyDisplayName}";
}
else
{
ProviderKeyDisplayName = string.Empty;
}
var result = await FeatureAppService.GetAsync(ProviderName, ProviderKey);
Groups = result?.Groups ?? new List<FeatureGroupDto>();
if (Groups.Any())
{
_activeTabIndex = 0;
}
foreach (var featureGroupDto in Groups)
{
foreach (var featureDto in featureGroupDto.Features)
{
if (featureDto.ValueType is ToggleStringValueType)
{
ToggleValues.Add(featureDto.Name, bool.Parse(featureDto.Value));
}
if (featureDto.ValueType is SelectionStringValueType)
{
SelectionStringValues.Add(featureDto.Name, featureDto.Value);
}
}
}
_isVisible = true;
await InvokeAsync(StateHasChanged);
}
catch (Exception ex)
{
await HandleErrorAsync(ex);
}
}
public virtual Task CloseModal()
{
_isVisible = false;
return InvokeAsync(StateHasChanged);
}
protected virtual async Task SaveAsync()
{
try
{
if (Groups == null)
{
return;
}
var features = new UpdateFeaturesDto
{
Features = Groups.SelectMany(g => g.Features).Select(f => new UpdateFeatureDto
{
Name = f.Name,
Value = f.ValueType is ToggleStringValueType ? ToggleValues[f.Name].ToString() :
f.ValueType is SelectionStringValueType ? SelectionStringValues[f.Name] : f.Value
}).ToList()
};
await FeatureAppService.UpdateAsync(ProviderName!, ProviderKey, features);
await CurrentApplicationConfigurationCacheResetService.ResetAsync();
_isVisible = false;
await InvokeAsync(StateHasChanged);
Snackbar.Add(L["SavedSuccessfully"], Severity.Success);
}
catch (Exception ex)
{
await HandleErrorAsync(ex);
}
}
public virtual async Task DeleteAsync(string providerName, string? providerKey = null)
{
try
{
var confirmed = await DialogService.ShowMessageBox(
L["AreYouSure"],
L["AreYouSureToResetToDefault"],
yesText: L["Yes"],
cancelText: L["Cancel"]);
if (confirmed != true)
{
return;
}
await FeatureAppService.DeleteAsync(ProviderName!, ProviderKey);
Snackbar.Add(L["ResetedToDefault"], Severity.Success);
await CloseModal();
}
catch (Exception ex)
{
await HandleErrorAsync(ex);
}
}
protected virtual string GetNormalizedGroupName(string name)
{
return "FeatureGroup_" + name.Replace(".", "_");
}
protected virtual string GetFeatureStyles(FeatureDto feature)
{
return $"margin-left: {feature.Depth * 20}px";
}
protected virtual bool IsDisabled(FeatureDto feature)
{
return feature.Value != null &&
feature.Provider.Name != null &&
feature.Provider.Name != ProviderName &&
feature.Provider.Name != DefaultValueFeatureValueProvider.ProviderName;
}
public virtual string GetShownName(FeatureDto featureDto)
{
return !IsDisabled(featureDto)
? featureDto.DisplayName
: $"{featureDto.DisplayName} ({featureDto.Provider.Name})";
}
protected virtual async Task OnFeatureValueChangedAsync(string? value, FeatureDto feature)
{
if (feature?.ValueType?.Validator.IsValid(value) == true)
{
feature.Value = value;
}
else
{
await UiMessageService.Warn(L["Volo.Abp.FeatureManagement:InvalidFeatureValue", feature.DisplayName]);
}
}
protected virtual Task OnSelectedValueChangedAsync(bool value, FeatureDto feature)
{
ToggleValues[feature.Name] = value;
if (value)
{
CheckParents(feature.ParentName);
}
else
{
UncheckChildren(feature.Name);
}
return Task.CompletedTask;
}
protected virtual void CheckParents(string? parentName)
{
if (parentName.IsNullOrWhiteSpace() || Groups == null)
{
return;
}
foreach (var featureGroupDto in Groups)
{
foreach (var featureDto in featureGroupDto.Features)
{
if (featureDto.Name == parentName && ToggleValues.ContainsKey(featureDto.Name))
{
ToggleValues[featureDto.Name] = true;
CheckParents(featureDto.ParentName);
}
}
}
}
protected virtual void UncheckChildren(string featureName)
{
if (Groups == null)
{
return;
}
foreach (var featureGroupDto in Groups)
{
foreach (var featureDto in featureGroupDto.Features)
{
if (featureDto.ParentName == featureName && ToggleValues.ContainsKey(featureDto.Name))
{
ToggleValues[featureDto.Name] = false;
UncheckChildren(featureDto.Name);
}
}
}
}
protected virtual IStringLocalizer CreateStringLocalizer(string resourceName)
{
return HtmlLocalizerFactory.CreateByResourceNameOrNull(resourceName) ??
HtmlLocalizerFactory.CreateDefaultOrNull();
}
}

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

@ -0,0 +1,19 @@
@using MudBlazor
@using Volo.Abp.FeatureManagement.Localization
@inherits Volo.Abp.AspNetCore.Components.AbpComponentBase
@if (Settings != null && Settings.HasManageHostFeaturesPermission)
{
<MudForm>
<MudText Typo="Typo.body1" Class="mb-3">@L["ManageHostFeaturesText"]</MudText>
<MudButton Size="Size.Small"
Color="Color.Primary"
Variant="Variant.Filled"
StartIcon="@Icons.Material.Filled.Settings"
OnClick="@OnManageHostFeaturesClicked">
@L["ManageHostFeatures"]
</MudButton>
</MudForm>
<FeatureManagementModal @ref="FeatureManagementModal"/>
}

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

@ -0,0 +1,41 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Volo.Abp.AspNetCore.Components;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.FeatureManagement.Blazor.MudBlazor.Components;
using Volo.Abp.FeatureManagement.Localization;
using Volo.Abp.Features;
namespace Volo.Abp.FeatureManagement.Blazor.MudBlazor.Components.FeatureSettingGroup;
public partial class FeatureSettingManagementComponent : AbpComponentBase
{
[Inject]
protected PermissionChecker PermissionChecker { get; set; } = default!;
protected FeatureManagementModal? FeatureManagementModal;
protected FeatureSettingViewModel? Settings;
public FeatureSettingManagementComponent()
{
LocalizationResource = typeof(AbpFeatureManagementResource);
}
protected async override Task OnInitializedAsync()
{
Settings = new FeatureSettingViewModel
{
HasManageHostFeaturesPermission = await AuthorizationService.IsGrantedAsync(FeatureManagementPermissions.ManageHostFeatures)
};
}
protected virtual async Task OnManageHostFeaturesClicked()
{
if (FeatureManagementModal != null)
{
await FeatureManagementModal.OpenAsync(TenantFeatureValueProvider.ProviderName);
}
}
}

6
modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Components/FeatureSettingGroup/FeatureSettingViewModel.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.FeatureManagement.Blazor.MudBlazor.Components.FeatureSettingGroup;
public class FeatureSettingViewModel
{
public bool HasManageHostFeaturesPermission { get; set; }
}

41
modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/Settings/FeatureSettingManagementComponentContributor.cs

@ -0,0 +1,41 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Volo.Abp.FeatureManagement.Blazor.MudBlazor.Components.FeatureSettingGroup;
using Volo.Abp.FeatureManagement.Localization;
using Volo.Abp.SettingManagement.Blazor.MudBlazor;
namespace Volo.Abp.FeatureManagement.Blazor.MudBlazor.Settings;
public class FeatureSettingManagementComponentContributor: ISettingComponentContributor
{
public virtual async Task ConfigureAsync(SettingComponentCreationContext context)
{
if (!await CheckPermissionsInternalAsync(context))
{
return;
}
var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<AbpFeatureManagementResource>>();
context.Groups.Add(
new SettingComponentGroup(
"Volo.Abp.Feature",
l["Permission:FeatureManagement"],
typeof(FeatureSettingManagementComponent)
)
);
}
public virtual async Task<bool> CheckPermissionsAsync(SettingComponentCreationContext context)
{
return await CheckPermissionsInternalAsync(context);
}
protected virtual async Task<bool> CheckPermissionsInternalAsync(SettingComponentCreationContext context)
{
var authorizationService = context.ServiceProvider.GetRequiredService<IAuthorizationService>();
return await authorizationService.IsGrantedAsync(FeatureManagementPermissions.ManageHostFeatures);
}
}

4
modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor.MudBlazor/_Imports.razor

@ -0,0 +1,4 @@
@using Microsoft.AspNetCore.Components.Web
@using Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor
@using MudBlazor
@using Volo.Abp.MudBlazorUI
Loading…
Cancel
Save