Browse Source

Disable features based on inheritance relationship.

pull/5176/head
maliming 6 years ago
parent
commit
c36f724323
  1. 6
      modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/FeatureDto.cs
  2. 5
      modules/feature-management/src/Volo.Abp.FeatureManagement.Application/Volo/Abp/FeatureManagement/FeatureAppService.cs
  3. 7
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DefaultValueFeatureManagementProvider.cs
  4. 7
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementProvider.cs
  5. 84
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs
  6. 19
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureNameValueWithGrantedProvider.cs
  7. 21
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureValueProviderInfo.cs
  8. 5
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManagementProvider.cs
  9. 6
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManager.cs
  10. 11
      modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml
  11. 9
      modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs

6
modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/FeatureDto.cs

@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using Volo.Abp.Validation.StringValues; using Volo.Abp.Validation.StringValues;
namespace Volo.Abp.FeatureManagement namespace Volo.Abp.FeatureManagement
@ -11,6 +11,8 @@ namespace Volo.Abp.FeatureManagement
public string Value { get; set; } public string Value { get; set; }
public string ProviderName { get; set; }
public string Description { get; set; } public string Description { get; set; }
public IStringValueType ValueType { get; set; } public IStringValueType ValueType { get; set; }
@ -19,4 +21,4 @@ namespace Volo.Abp.FeatureManagement
public string ParentName { get; set; } public string ParentName { get; set; }
} }
} }

5
modules/feature-management/src/Volo.Abp.FeatureManagement.Application/Volo/Abp/FeatureManagement/FeatureAppService.cs

@ -33,6 +33,8 @@ namespace Volo.Abp.FeatureManagement
foreach (var featureDefinition in featureDefinitions) foreach (var featureDefinition in featureDefinitions)
{ {
var value = await FeatureManager.GetOrNullWithProviderAsync(featureDefinition.Name, providerName,
providerKey);
features.Add(new FeatureDto features.Add(new FeatureDto
{ {
Name = featureDefinition.Name, Name = featureDefinition.Name,
@ -40,7 +42,8 @@ namespace Volo.Abp.FeatureManagement
ValueType = featureDefinition.ValueType, ValueType = featureDefinition.ValueType,
Description = featureDefinition.Description?.Localize(StringLocalizerFactory), Description = featureDefinition.Description?.Localize(StringLocalizerFactory),
ParentName = featureDefinition.Parent?.Name, ParentName = featureDefinition.Parent?.Name,
Value = await FeatureManager.GetOrNullAsync(featureDefinition.Name, providerName, providerKey) Value = value.Value,
ProviderName = value.Provider.Name
}); });
} }

7
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DefaultValueFeatureManagementProvider.cs

@ -8,6 +8,11 @@ namespace Volo.Abp.FeatureManagement
{ {
public string Name => DefaultValueFeatureValueProvider.ProviderName; public string Name => DefaultValueFeatureValueProvider.ProviderName;
public bool Compatible(string providerName)
{
return providerName == Name;
}
public virtual Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey) public virtual Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey)
{ {
return Task.FromResult(feature.DefaultValue); return Task.FromResult(feature.DefaultValue);
@ -23,4 +28,4 @@ namespace Volo.Abp.FeatureManagement
throw new AbpException($"Can not clear default value of a feature. It is only possible while defining the feature in a {typeof(IFeatureDefinitionProvider)} implementation."); throw new AbpException($"Can not clear default value of a feature. It is only possible while defining the feature in a {typeof(IFeatureDefinitionProvider)} implementation.");
} }
} }
} }

7
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementProvider.cs

@ -14,6 +14,11 @@ namespace Volo.Abp.FeatureManagement
Store = store; Store = store;
} }
public virtual bool Compatible(string providerName)
{
return providerName == Name;
}
public virtual async Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey) public virtual async Task<string> GetOrNullAsync(FeatureDefinition feature, string providerKey)
{ {
return await Store.GetOrNullAsync(feature.Name, Name, NormalizeProviderKey(providerKey)); return await Store.GetOrNullAsync(feature.Name, Name, NormalizeProviderKey(providerKey));
@ -34,4 +39,4 @@ namespace Volo.Abp.FeatureManagement
return providerKey; return providerKey;
} }
} }
} }

84
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs

@ -35,23 +35,37 @@ namespace Volo.Abp.FeatureManagement
true true
); );
} }
public virtual Task<string> GetOrNullAsync( public virtual async Task<string> GetOrNullAsync(
string name, string name,
string providerName, string providerName,
string providerKey, string providerKey,
bool fallback = true) bool fallback = true)
{ {
Check.NotNull(name, nameof(name)); Check.NotNull(name, nameof(name));
Check.NotNull(providerName, nameof(providerName)); Check.NotNull(providerName, nameof(providerName));
return GetOrNullInternalAsync(name, providerName, providerKey, fallback); return (await GetOrNullInternalAsync(name, providerName, providerKey, fallback)).Value;
} }
public virtual async Task<List<FeatureNameValue>> GetAllAsync( public virtual async Task<List<FeatureNameValue>> GetAllAsync(
string providerName, string providerName,
string providerKey, string providerKey,
bool fallback = true) bool fallback = true)
{
return (await GetAllWithProviderAsync(providerName, providerKey, fallback))
.Select(x => new FeatureNameValue(x.Name, x.Value)).ToList();
}
public async Task<FeatureNameValueWithGrantedProvider> GetOrNullWithProviderAsync(string name, string providerName, string providerKey, bool fallback = true)
{
Check.NotNull(name, nameof(name));
Check.NotNull(providerName, nameof(providerName));
return await GetOrNullInternalAsync(name, providerName, providerKey, fallback);
}
public async Task<List<FeatureNameValueWithGrantedProvider>> GetAllWithProviderAsync(string providerName, string providerKey, bool fallback = true)
{ {
Check.NotNull(providerName, nameof(providerName)); Check.NotNull(providerName, nameof(providerName));
@ -68,31 +82,35 @@ namespace Volo.Abp.FeatureManagement
if (!providerList.Any()) if (!providerList.Any())
{ {
return new List<FeatureNameValue>(); return new List<FeatureNameValueWithGrantedProvider>();
} }
var featureValues = new Dictionary<string, FeatureNameValue>(); var featureValues = new Dictionary<string, FeatureNameValueWithGrantedProvider>();
foreach (var feature in featureDefinitions) foreach (var feature in featureDefinitions)
{ {
string value = null; FeatureNameValueWithGrantedProvider value = null;
foreach (var provider in providerList) foreach (var provider in providerList)
{ {
var pk = provider.Name == providerName ? providerKey : null;
var providerValue = await provider.GetOrNullAsync( var providerValue = await provider.GetOrNullAsync(
feature, feature,
provider.Name == providerName ? providerKey : null pk
); );
if (providerValue != null) if (providerValue != null)
{ {
value = providerValue; value = new FeatureNameValueWithGrantedProvider(feature.Name, providerValue)
{
Provider = new FeatureValueProviderInfo(provider.Name, pk)
};
} }
} }
if (value != null) if (value != null)
{ {
featureValues[feature.Name] = new FeatureNameValue(feature.Name, value); featureValues[feature.Name] = value;
} }
} }
@ -100,10 +118,10 @@ namespace Volo.Abp.FeatureManagement
} }
public virtual async Task SetAsync( public virtual async Task SetAsync(
string name, string name,
string value, string value,
string providerName, string providerName,
string providerKey, string providerKey,
bool forceToSet = false) bool forceToSet = false)
{ {
Check.NotNull(name, nameof(name)); Check.NotNull(name, nameof(name));
@ -120,11 +138,11 @@ namespace Volo.Abp.FeatureManagement
{ {
return; return;
} }
if (providers.Count > 1 && !forceToSet && value != null) if (providers.Count > 1 && !forceToSet && value != null)
{ {
var fallbackValue = await GetOrNullInternalAsync(name, providers[1].Name, null); var fallbackValue = await GetOrNullInternalAsync(name, providers[1].Name, null);
if (fallbackValue == value) if (fallbackValue.Value == value)
{ {
//Clear the value if it's same as it's fallback value //Clear the value if it's same as it's fallback value
value = null; value = null;
@ -151,10 +169,10 @@ namespace Volo.Abp.FeatureManagement
} }
} }
protected virtual async Task<string> GetOrNullInternalAsync( protected virtual async Task<FeatureNameValueWithGrantedProvider> GetOrNullInternalAsync(
string name, string name,
string providerName, string providerName,
string providerKey, string providerKey,
bool fallback = true) //TODO: Fallback is not used bool fallback = true) //TODO: Fallback is not used
{ {
var feature = FeatureDefinitionManager.Get(name); var feature = FeatureDefinitionManager.Get(name);
@ -166,21 +184,27 @@ namespace Volo.Abp.FeatureManagement
providers = providers.SkipWhile(c => c.Name != providerName); providers = providers.SkipWhile(c => c.Name != providerName);
} }
string value = null; FeatureNameValueWithGrantedProvider featureNameValueWithGrantedProvider = null;
foreach (var provider in providers) foreach (var provider in providers)
{ {
value = await provider.GetOrNullAsync( string pk = null;
feature, if (provider.Compatible(providerName))
provider.Name == providerName ? providerKey : null {
); pk = providerKey;
}
var value = await provider.GetOrNullAsync(feature, pk);
if (value != null) if (value != null)
{ {
featureNameValueWithGrantedProvider = new FeatureNameValueWithGrantedProvider(name, value)
{
Provider = new FeatureValueProviderInfo(provider.Name, pk)
};
break; break;
} }
} }
return value; return featureNameValueWithGrantedProvider;
} }
} }
} }

19
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureNameValueWithGrantedProvider.cs

@ -0,0 +1,19 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.FeatureManagement
{
[Serializable]
public class FeatureNameValueWithGrantedProvider : NameValue
{
public FeatureValueProviderInfo Provider { get; set; }
public FeatureNameValueWithGrantedProvider([NotNull] string name, string value)
{
Check.NotNull(name, nameof(name));
Name = name;
Value = value;
}
}
}

21
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureValueProviderInfo.cs

@ -0,0 +1,21 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.FeatureManagement
{
[Serializable]
public class FeatureValueProviderInfo
{
public string Name { get; }
public string Key { get; }
public FeatureValueProviderInfo([NotNull]string name, string key)
{
Check.NotNull(name, nameof(name));
Name = name;
Key = key;
}
}
}

5
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManagementProvider.cs

@ -8,10 +8,13 @@ namespace Volo.Abp.FeatureManagement
{ {
string Name { get; } string Name { get; }
//TODO: Other better method name.
bool Compatible(string providerName);
Task<string> GetOrNullAsync([NotNull] FeatureDefinition feature, [CanBeNull] string providerKey); Task<string> GetOrNullAsync([NotNull] FeatureDefinition feature, [CanBeNull] string providerKey);
Task SetAsync([NotNull] FeatureDefinition feature, [NotNull] string value, [CanBeNull] string providerKey); Task SetAsync([NotNull] FeatureDefinition feature, [NotNull] string value, [CanBeNull] string providerKey);
Task ClearAsync([NotNull] FeatureDefinition feature, [CanBeNull] string providerKey); Task ClearAsync([NotNull] FeatureDefinition feature, [CanBeNull] string providerKey);
} }
} }

6
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManager.cs

@ -10,6 +10,10 @@ namespace Volo.Abp.FeatureManagement
Task<List<FeatureNameValue>> GetAllAsync([NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true); Task<List<FeatureNameValue>> GetAllAsync([NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true);
Task<FeatureNameValueWithGrantedProvider> GetOrNullWithProviderAsync([NotNull]string name, [NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true);
Task<List<FeatureNameValueWithGrantedProvider>> GetAllWithProviderAsync([NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true);
Task SetAsync([NotNull] string name, [CanBeNull] string value, [NotNull] string providerName, [CanBeNull] string providerKey, bool forceToSet = false); Task SetAsync([NotNull] string name, [CanBeNull] string value, [NotNull] string providerName, [CanBeNull] string providerKey, bool forceToSet = false);
} }
} }

11
modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml

@ -4,6 +4,7 @@
@using Volo.Abp.FeatureManagement.Localization @using Volo.Abp.FeatureManagement.Localization
@using Volo.Abp.Validation.StringValues @using Volo.Abp.Validation.StringValues
@using Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement @using Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement
@using Volo.Abp.Features
@model FeatureManagementModal @model FeatureManagementModal
@inject IHtmlLocalizer<AbpFeatureManagementResource> L @inject IHtmlLocalizer<AbpFeatureManagementResource> L
@{ @{
@ -20,20 +21,22 @@
@for (var i = 0; i < Model.FeatureListDto.Features.Count; i++) @for (var i = 0; i < Model.FeatureListDto.Features.Count; i++)
{ {
var feature = Model.FeatureListDto.Features[i]; var feature = Model.FeatureListDto.Features[i];
var disabled = Model.IsDisabled((feature.ProviderName));
<div class="mt-2" style="padding-left: @(feature.Depth * 20)px"> <div class="mt-2" style="padding-left: @(feature.Depth * 20)px">
<spam class="mr-2">@feature.DisplayName</spam> <spam class="mr-2">@feature.DisplayName @(disabled ? $"({feature.ProviderName})" : "")</spam>
<input type="text" name="Features[@i].ProviderName" value="@feature.ProviderName" hidden />
<input type="text" name="Features[@i].Type" value="@feature.ValueType?.Name" hidden /> <input type="text" name="Features[@i].Type" value="@feature.ValueType?.Name" hidden />
@if (feature.ValueType is FreeTextStringValueType) @if (feature.ValueType is FreeTextStringValueType)
{ {
<input type="text" name="Features[@i].Name" value="@feature.Name" hidden /> <input type="text" name="Features[@i].Name" value="@feature.Name" hidden />
<input type="text" name="Features[@i].Value" value="@feature.Value" /> <input disabled="@disabled" type="text" name="Features[@i].Value" value="@feature.Value" />
} }
@if (feature.ValueType is SelectionStringValueType) @if (feature.ValueType is SelectionStringValueType)
{ {
<input type="text" name="Features[@i].Name" value="@feature.Name" hidden /> <input type="text" name="Features[@i].Name" value="@feature.Name" hidden />
<select name="Features[@i].Value"> <select disabled="@disabled" name="Features[@i].Value">
@foreach (var item in (feature.ValueType as SelectionStringValueType).ItemSource.Items) @foreach (var item in (feature.ValueType as SelectionStringValueType).ItemSource.Items)
{ {
if (item.Value == feature.Value) if (item.Value == feature.Value)
@ -50,7 +53,7 @@
@if (feature.ValueType is ToggleStringValueType) @if (feature.ValueType is ToggleStringValueType)
{ {
<input type="text" name="Features[@i].Name" value="@feature.Name" hidden /> <input type="text" name="Features[@i].Name" value="@feature.Name" hidden />
<input type="checkbox" class="FeatureValueCheckbox" name="Features[@i].BoolValue" value="@feature.Value" <input disabled="@disabled" type="checkbox" class="FeatureValueCheckbox" name="Features[@i].BoolValue" value="@feature.Value"
@Html.Raw(feature.Value == "True" ? "checked" : "") /> @Html.Raw(feature.Value == "True" ? "checked" : "") />
} }
</div> </div>

9
modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs

@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Features;
using Volo.Abp.Validation.StringValues; using Volo.Abp.Validation.StringValues;
namespace Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement namespace Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement
@ -55,6 +56,10 @@ namespace Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement
return NoContent(); return NoContent();
} }
public virtual bool IsDisabled(string providerName)
{
return providerName != ProviderName && providerName != DefaultValueFeatureValueProvider.ProviderName;
}
public class ProviderInfoViewModel public class ProviderInfoViewModel
{ {
@ -69,9 +74,11 @@ namespace Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement
public string Value { get; set; } public string Value { get; set; }
public string ProviderName { get; set; }
public bool BoolValue { get; set; } public bool BoolValue { get; set; }
public string Type { get; set; } public string Type { get; set; }
} }
} }
} }

Loading…
Cancel
Save