From c36f7243233f59dd215f491c5d022ecb276df877 Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Wed, 26 Aug 2020 14:48:22 +0800 Subject: [PATCH] Disable features based on inheritance relationship. --- .../Volo/Abp/FeatureManagement/FeatureDto.cs | 6 +- .../FeatureManagement/FeatureAppService.cs | 5 +- .../DefaultValueFeatureManagementProvider.cs | 7 +- .../FeatureManagementProvider.cs | 7 +- .../Abp/FeatureManagement/FeatureManager.cs | 84 ++++++++++++------- .../FeatureNameValueWithGrantedProvider.cs | 19 +++++ .../FeatureValueProviderInfo.cs | 21 +++++ .../IFeatureManagementProvider.cs | 5 +- .../Abp/FeatureManagement/IFeatureManager.cs | 6 +- .../FeatureManagementModal.cshtml | 11 ++- .../FeatureManagementModal.cshtml.cs | 9 +- 11 files changed, 138 insertions(+), 42 deletions(-) create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureNameValueWithGrantedProvider.cs create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureValueProviderInfo.cs diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/FeatureDto.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/FeatureDto.cs index 1128cfd2e2..26b41dbc8f 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/FeatureDto.cs +++ b/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; namespace Volo.Abp.FeatureManagement @@ -11,6 +11,8 @@ namespace Volo.Abp.FeatureManagement public string Value { get; set; } + public string ProviderName { get; set; } + public string Description { get; set; } public IStringValueType ValueType { get; set; } @@ -19,4 +21,4 @@ namespace Volo.Abp.FeatureManagement public string ParentName { get; set; } } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application/Volo/Abp/FeatureManagement/FeatureAppService.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application/Volo/Abp/FeatureManagement/FeatureAppService.cs index ab097a54a6..8fc761a632 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application/Volo/Abp/FeatureManagement/FeatureAppService.cs +++ b/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) { + var value = await FeatureManager.GetOrNullWithProviderAsync(featureDefinition.Name, providerName, + providerKey); features.Add(new FeatureDto { Name = featureDefinition.Name, @@ -40,7 +42,8 @@ namespace Volo.Abp.FeatureManagement ValueType = featureDefinition.ValueType, Description = featureDefinition.Description?.Localize(StringLocalizerFactory), ParentName = featureDefinition.Parent?.Name, - Value = await FeatureManager.GetOrNullAsync(featureDefinition.Name, providerName, providerKey) + Value = value.Value, + ProviderName = value.Provider.Name }); } diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DefaultValueFeatureManagementProvider.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DefaultValueFeatureManagementProvider.cs index 6c501166e2..744cedbbbf 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DefaultValueFeatureManagementProvider.cs +++ b/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 bool Compatible(string providerName) + { + return providerName == Name; + } + public virtual Task GetOrNullAsync(FeatureDefinition feature, string providerKey) { 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."); } } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementProvider.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementProvider.cs index 499d396e60..45e5f65b4c 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementProvider.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManagementProvider.cs @@ -14,6 +14,11 @@ namespace Volo.Abp.FeatureManagement Store = store; } + public virtual bool Compatible(string providerName) + { + return providerName == Name; + } + public virtual async Task GetOrNullAsync(FeatureDefinition feature, string providerKey) { return await Store.GetOrNullAsync(feature.Name, Name, NormalizeProviderKey(providerKey)); @@ -34,4 +39,4 @@ namespace Volo.Abp.FeatureManagement return providerKey; } } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs index 04b7ab6682..5ff7c18407 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs @@ -35,23 +35,37 @@ namespace Volo.Abp.FeatureManagement true ); } - - public virtual Task GetOrNullAsync( - string name, - string providerName, - string providerKey, + + public virtual async Task GetOrNullAsync( + string name, + string providerName, + string providerKey, bool fallback = true) { Check.NotNull(name, nameof(name)); Check.NotNull(providerName, nameof(providerName)); - return GetOrNullInternalAsync(name, providerName, providerKey, fallback); + return (await GetOrNullInternalAsync(name, providerName, providerKey, fallback)).Value; } public virtual async Task> GetAllAsync( - string providerName, - string providerKey, + string providerName, + string providerKey, bool fallback = true) + { + return (await GetAllWithProviderAsync(providerName, providerKey, fallback)) + .Select(x => new FeatureNameValue(x.Name, x.Value)).ToList(); + } + + public async Task 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> GetAllWithProviderAsync(string providerName, string providerKey, bool fallback = true) { Check.NotNull(providerName, nameof(providerName)); @@ -68,31 +82,35 @@ namespace Volo.Abp.FeatureManagement if (!providerList.Any()) { - return new List(); + return new List(); } - var featureValues = new Dictionary(); + var featureValues = new Dictionary(); foreach (var feature in featureDefinitions) { - string value = null; + FeatureNameValueWithGrantedProvider value = null; foreach (var provider in providerList) { + var pk = provider.Name == providerName ? providerKey : null; var providerValue = await provider.GetOrNullAsync( feature, - provider.Name == providerName ? providerKey : null + pk ); if (providerValue != null) { - value = providerValue; + value = new FeatureNameValueWithGrantedProvider(feature.Name, providerValue) + { + Provider = new FeatureValueProviderInfo(provider.Name, pk) + }; } } 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( - string name, - string value, - string providerName, - string providerKey, + string name, + string value, + string providerName, + string providerKey, bool forceToSet = false) { Check.NotNull(name, nameof(name)); @@ -120,11 +138,11 @@ namespace Volo.Abp.FeatureManagement { return; } - + if (providers.Count > 1 && !forceToSet && value != 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 value = null; @@ -151,10 +169,10 @@ namespace Volo.Abp.FeatureManagement } } - protected virtual async Task GetOrNullInternalAsync( - string name, - string providerName, - string providerKey, + protected virtual async Task GetOrNullInternalAsync( + string name, + string providerName, + string providerKey, bool fallback = true) //TODO: Fallback is not used { var feature = FeatureDefinitionManager.Get(name); @@ -166,21 +184,27 @@ namespace Volo.Abp.FeatureManagement providers = providers.SkipWhile(c => c.Name != providerName); } - string value = null; + FeatureNameValueWithGrantedProvider featureNameValueWithGrantedProvider = null; foreach (var provider in providers) { - value = await provider.GetOrNullAsync( - feature, - provider.Name == providerName ? providerKey : null - ); + string pk = null; + if (provider.Compatible(providerName)) + { + pk = providerKey; + } + var value = await provider.GetOrNullAsync(feature, pk); if (value != null) { + featureNameValueWithGrantedProvider = new FeatureNameValueWithGrantedProvider(name, value) + { + Provider = new FeatureValueProviderInfo(provider.Name, pk) + }; break; } } - return value; + return featureNameValueWithGrantedProvider; } } } diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureNameValueWithGrantedProvider.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureNameValueWithGrantedProvider.cs new file mode 100644 index 0000000000..d017cb3a9b --- /dev/null +++ b/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; + } + } +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureValueProviderInfo.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureValueProviderInfo.cs new file mode 100644 index 0000000000..3c2fc7ed30 --- /dev/null +++ b/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; + } + } +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManagementProvider.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManagementProvider.cs index 204ed16235..4026937f4b 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManagementProvider.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManagementProvider.cs @@ -8,10 +8,13 @@ namespace Volo.Abp.FeatureManagement { string Name { get; } + //TODO: Other better method name. + bool Compatible(string providerName); + Task GetOrNullAsync([NotNull] FeatureDefinition feature, [CanBeNull] string providerKey); Task SetAsync([NotNull] FeatureDefinition feature, [NotNull] string value, [CanBeNull] string providerKey); Task ClearAsync([NotNull] FeatureDefinition feature, [CanBeNull] string providerKey); } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManager.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManager.cs index df19cd332b..961110137c 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManager.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/IFeatureManager.cs @@ -10,6 +10,10 @@ namespace Volo.Abp.FeatureManagement Task> GetAllAsync([NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true); + Task GetOrNullWithProviderAsync([NotNull]string name, [NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true); + + Task> 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); } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml index ec8b4b1706..90659844ac 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml @@ -4,6 +4,7 @@ @using Volo.Abp.FeatureManagement.Localization @using Volo.Abp.Validation.StringValues @using Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement +@using Volo.Abp.Features @model FeatureManagementModal @inject IHtmlLocalizer L @{ @@ -20,20 +21,22 @@ @for (var i = 0; i < Model.FeatureListDto.Features.Count; i++) { var feature = Model.FeatureListDto.Features[i]; + var disabled = Model.IsDisabled((feature.ProviderName));
- @feature.DisplayName + @feature.DisplayName @(disabled ? $"({feature.ProviderName})" : "") + @if (feature.ValueType is FreeTextStringValueType) { - + } @if (feature.ValueType is SelectionStringValueType) { - @foreach (var item in (feature.ValueType as SelectionStringValueType).ItemSource.Items) { if (item.Value == feature.Value) @@ -50,7 +53,7 @@ @if (feature.ValueType is ToggleStringValueType) { - }
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs index fd32f69d63..e46d686e69 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs +++ b/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 Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Features; using Volo.Abp.Validation.StringValues; namespace Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement @@ -55,6 +56,10 @@ namespace Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement return NoContent(); } + public virtual bool IsDisabled(string providerName) + { + return providerName != ProviderName && providerName != DefaultValueFeatureValueProvider.ProviderName; + } public class ProviderInfoViewModel { @@ -69,9 +74,11 @@ namespace Volo.Abp.FeatureManagement.Web.Pages.FeatureManagement public string Value { get; set; } + public string ProviderName { get; set; } + public bool BoolValue { get; set; } public string Type { get; set; } } } -} \ No newline at end of file +}