mirror of https://github.com/abpframework/abp.git
committed by
GitHub
28 changed files with 404 additions and 26 deletions
@ -0,0 +1,20 @@ |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.Validation.StringValues; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
{ |
|||
public class FeatureDto |
|||
{ |
|||
public string Name { get; set; } |
|||
|
|||
public string Value { get; set; } |
|||
|
|||
public string Description { get; set; } |
|||
|
|||
public IStringValueType ValueType { get; set; } |
|||
|
|||
public int Depth { get; set; } |
|||
|
|||
public string ParentName { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
{ |
|||
public class FeatureListDto |
|||
{ |
|||
public List<FeatureDto> Features { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
{ |
|||
public interface IFeatureAppService : IApplicationService |
|||
{ |
|||
Task<FeatureListDto> GetAsync([NotNull] string providerName, [NotNull] string providerKey); |
|||
|
|||
Task UpdateAsync([NotNull] string providerName, [NotNull] string providerKey, UpdateFeaturesDto input); |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
{ |
|||
public class UpdateFeatureDto |
|||
{ |
|||
public string Name { get; set; } |
|||
|
|||
public string Value { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
{ |
|||
public class UpdateFeaturesDto |
|||
{ |
|||
public List<UpdateFeatureDto> Features { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,93 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.Extensions.Localization; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Features; |
|||
|
|||
namespace Volo.Abp.FeatureManagement |
|||
{ |
|||
[Authorize] |
|||
public class FeatureAppService : ApplicationService, IFeatureAppService |
|||
{ |
|||
protected FeatureManagementOptions Options { get; } |
|||
|
|||
private readonly IFeatureManager _featureManager; |
|||
private readonly IFeatureDefinitionManager _featureDefinitionManager; |
|||
private readonly IStringLocalizerFactory _stringLocalizerFactory; |
|||
|
|||
public FeatureAppService(IFeatureManager featureManager, |
|||
IFeatureDefinitionManager featureDefinitionManager, |
|||
IStringLocalizerFactory stringLocalizerFactory, |
|||
IOptions<FeatureManagementOptions> options) |
|||
{ |
|||
_featureManager = featureManager; |
|||
_featureDefinitionManager = featureDefinitionManager; |
|||
_stringLocalizerFactory = stringLocalizerFactory; |
|||
Options = options.Value; |
|||
} |
|||
|
|||
public async Task<FeatureListDto> GetAsync([NotNull] string providerName, [NotNull] string providerKey) |
|||
{ |
|||
await CheckProviderPolicy(providerName); |
|||
|
|||
var featureDefinitions = _featureDefinitionManager.GetAll(); |
|||
var features = new List<FeatureDto>(); |
|||
|
|||
foreach (var featureDefinition in featureDefinitions) |
|||
{ |
|||
features.Add(new FeatureDto |
|||
{ |
|||
Name = featureDefinition.Name, |
|||
ValueType = featureDefinition.ValueType, |
|||
Description = featureDefinition.Description.Localize(_stringLocalizerFactory), |
|||
ParentName = featureDefinition.Parent?.Name, |
|||
Value = await _featureManager.GetOrNullAsync(featureDefinition.Name, providerName, providerKey) |
|||
}); |
|||
} |
|||
|
|||
SetFeatureDepth(features, providerName, providerKey); |
|||
|
|||
return new FeatureListDto { Features = features }; |
|||
} |
|||
|
|||
public async Task UpdateAsync([NotNull] string providerName, [NotNull] string providerKey, UpdateFeaturesDto input) |
|||
{ |
|||
await CheckProviderPolicy(providerName); |
|||
|
|||
foreach (var feature in input.Features) |
|||
{ |
|||
await _featureManager.SetAsync(feature.Name, feature.Value, providerName, providerKey); |
|||
} |
|||
} |
|||
|
|||
private void SetFeatureDepth(List<FeatureDto> features, string providerName, string providerKey, |
|||
FeatureDto parentFeature = null, int depth = 0) |
|||
{ |
|||
foreach (var feature in features) |
|||
{ |
|||
if ((parentFeature == null && feature.ParentName == null) || (parentFeature != null && parentFeature.Name == feature.ParentName)) |
|||
{ |
|||
feature.Depth = depth; |
|||
SetFeatureDepth(features, providerName, providerKey, feature, depth + 1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected virtual async Task CheckProviderPolicy(string providerName) |
|||
{ |
|||
var policyName = Options.ProviderPolicies.GetOrDefault(providerName); |
|||
if (policyName.IsNullOrEmpty()) |
|||
{ |
|||
throw new AbpException($"No policy defined to get/set permissions for the provider '{policyName}'. Use {nameof(FeatureManagementOptions)} to map the policy."); |
|||
} |
|||
|
|||
await AuthorizationService.CheckAsync(policyName); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
@page |
|||
@using Microsoft.AspNetCore.Mvc.Localization |
|||
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal |
|||
@using Volo.Abp.FeatureManagement.Localization |
|||
@using Volo.Abp.Validation.StringValues |
|||
@using Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement |
|||
@model FeatureManagementModal |
|||
@inject IHtmlLocalizer<AbpFeatureManagementResource> L |
|||
@{ |
|||
Layout = null; |
|||
} |
|||
<form method="post" asp-page="/FeatureManagement/FeatureManagementModal" data-script-class="abp.modals.FeatureManagement"> |
|||
<abp-modal size="Large"> |
|||
<abp-modal-header title="@(L["Features"].Value)"></abp-modal-header> |
|||
<abp-modal-body class="ml-4"> |
|||
<input asp-for="@Model.ProviderKey" /> |
|||
<input asp-for="@Model.ProviderName" /> |
|||
@for (var i = 0; i < Model.FeatureListDto.Features.Count; i++) |
|||
{ |
|||
var feature = Model.FeatureListDto.Features[i]; |
|||
<div class="mt-2" style="padding-left: @(feature.Depth * 20)px"> |
|||
|
|||
<spam class="mr-2">@feature.Name</spam> |
|||
|
|||
<input type="text" name="Features[@i].Type" value="@feature.ValueType.Name" hidden /> |
|||
@if (feature.ValueType is FreeTextStringValueType) |
|||
{ |
|||
<input type="text" name="Features[@i].Name" value="@feature.Name" hidden /> |
|||
<input type="text" name="Features[@i].Value" value="@feature.Value" /> |
|||
} |
|||
@if (feature.ValueType is SelectionStringValueType) |
|||
{ |
|||
<input type="text" name="Features[@i].Name" value="@feature.Name" hidden /> |
|||
<select name="Features[@i].Value"> |
|||
@foreach (var item in (feature.ValueType as SelectionStringValueType).ItemSource.Items) |
|||
{ |
|||
if (item.Value == feature.Value) |
|||
{ |
|||
<option value="@item.Value" selected="selected"> @L.GetString(item.DisplayText.Name) </option> |
|||
} |
|||
else |
|||
{ |
|||
<option value="@item.Value"> @L.GetString(item.DisplayText.Name) </option> |
|||
} |
|||
} |
|||
</select> |
|||
} |
|||
@if (feature.ValueType is ToggleStringValueType) |
|||
{ |
|||
<input type="text" name="Features[@i].Name" value="@feature.Name" hidden /> |
|||
<input type="checkbox" class="FeatureValueCheckbox" name="Features[@i].BoolValue" value="@feature.Value" |
|||
@Html.Raw(feature.Value == "True" ? "checked" : "") /> |
|||
} |
|||
</div> |
|||
} |
|||
</abp-modal-body> |
|||
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer> |
|||
</abp-modal> |
|||
</form> |
|||
|
|||
@ -0,0 +1,75 @@ |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; |
|||
using Volo.Abp.Validation.StringValues; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement |
|||
{ |
|||
public class FeatureManagementModal : AbpPageModel |
|||
{ |
|||
[Required] |
|||
[HiddenInput] |
|||
[BindProperty(SupportsGet = true)] |
|||
public string ProviderName { get; set; } |
|||
|
|||
[Required] |
|||
[HiddenInput] |
|||
[BindProperty(SupportsGet = true)] |
|||
public string ProviderKey { get; set; } |
|||
|
|||
[BindProperty] |
|||
public List<FeatureViewModel> Features { get; set; } |
|||
|
|||
public FeatureListDto FeatureListDto { get; set; } |
|||
|
|||
private readonly IFeatureAppService _featureAppService; |
|||
|
|||
public FeatureManagementModal(IFeatureAppService featureAppService) |
|||
{ |
|||
_featureAppService = featureAppService; |
|||
} |
|||
|
|||
public async Task OnGetAsync() |
|||
{ |
|||
FeatureListDto = await _featureAppService.GetAsync(ProviderName, ProviderKey); |
|||
} |
|||
|
|||
public async Task<IActionResult> OnPostAsync() |
|||
{ |
|||
var features = new UpdateFeaturesDto |
|||
{ |
|||
Features = Features.Select(f => new UpdateFeatureDto |
|||
{ |
|||
Name = f.Name, |
|||
Value = f.Type == nameof(ToggleStringValueType) ? f.BoolValue.ToString() : f.Value |
|||
}).ToList() |
|||
}; |
|||
|
|||
await _featureAppService.UpdateAsync(ProviderName, ProviderKey, features); |
|||
|
|||
return NoContent(); |
|||
} |
|||
|
|||
|
|||
public class ProviderInfoViewModel |
|||
{ |
|||
public string ProviderName { get; set; } |
|||
|
|||
public string ProviderKey { get; set; } |
|||
} |
|||
|
|||
public class FeatureViewModel |
|||
{ |
|||
public string Name { get; set; } |
|||
|
|||
public string Value { get; set; } |
|||
|
|||
public bool BoolValue { get; set; } |
|||
|
|||
public string Type { get; set; } |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
var abp = abp || {}; |
|||
(function ($) { |
|||
abp.modals = abp.modals || {}; |
|||
|
|||
abp.modals.FeatureManagement = function () { |
|||
|
|||
$('.FeatureValueCheckbox').change(function () { |
|||
if (this.checked) { |
|||
$(this).val("true"); |
|||
} |
|||
else { |
|||
$(this).val("false"); |
|||
} |
|||
}); |
|||
|
|||
}; |
|||
})(jQuery); |
|||
@ -0,0 +1,12 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp2.2</TargetFramework> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.TenantManagement.Domain.Shared\Volo.Abp.TenantManagement.Domain.Shared.csproj" /> |
|||
<ProjectReference Include="..\..\..\feature-management\src\Volo.Abp.FeatureManagement.Domain\Volo.Abp.FeatureManagement.Domain.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,18 @@ |
|||
using Volo.Abp.Features; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.TenantManagement |
|||
{ |
|||
public class AbpFeatureManagementDomainTenantManagementModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<FeatureManagementOptions>(options => |
|||
{ |
|||
options.Providers.Add<TenantFeatureManagementProvider>(); |
|||
|
|||
options.ProviderPolicies[TenantFeatureValueProvider.ProviderName] = "AbpTenantManagement.Tenants.ManageFeatures"; |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue