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..11e1c6c005 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,3 @@ -using System.Collections.Generic; using Volo.Abp.Validation.StringValues; namespace Volo.Abp.FeatureManagement @@ -11,6 +10,8 @@ namespace Volo.Abp.FeatureManagement public string Value { get; set; } + public FeatureProviderDto Provider { get; set; } + public string Description { get; set; } public IStringValueType ValueType { get; set; } @@ -19,4 +20,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.Contracts/Volo/Abp/FeatureManagement/FeatureProviderDto.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/FeatureProviderDto.cs new file mode 100644 index 0000000000..59c9dcb2ef --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/FeatureProviderDto.cs @@ -0,0 +1,9 @@ +namespace Volo.Abp.FeatureManagement +{ + public class FeatureProviderDto + { + public string Name { get; set; } + + public string Key { get; set; } + } +} 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..f0c310650d 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,7 @@ namespace Volo.Abp.FeatureManagement foreach (var featureDefinition in featureDefinitions) { + var feature = await FeatureManager.GetOrNullWithProviderAsync(featureDefinition.Name, providerName, providerKey); features.Add(new FeatureDto { Name = featureDefinition.Name, @@ -40,7 +41,12 @@ 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 = feature.Value, + Provider = new FeatureProviderDto + { + Name = feature.Provider?.Name, + Key = feature.Provider?.Key + } }); } 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/DefaultValueFeatureManagerExtensions.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DefaultValueFeatureManagerExtensions.cs index c000b66df3..7ff616fccf 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DefaultValueFeatureManagerExtensions.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DefaultValueFeatureManagerExtensions.cs @@ -16,5 +16,15 @@ namespace Volo.Abp.FeatureManagement { return featureManager.GetAllAsync(DefaultValueFeatureValueProvider.ProviderName, null, fallback); } + + public static Task GetOrNullWithProviderAsync(this IFeatureManager featureManager, [NotNull] string name, bool fallback = true) + { + return featureManager.GetOrNullWithProviderAsync(name, DefaultValueFeatureValueProvider.ProviderName, null, fallback); + } + + public static Task> GetAllWithProviderAsync(this IFeatureManager featureManager, bool fallback = true) + { + return featureManager.GetAllWithProviderAsync(DefaultValueFeatureValueProvider.ProviderName, null, fallback); + } } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/EditionFeatureManagerExtensions.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/EditionFeatureManagerExtensions.cs index be8bbfc95a..2b26ec94e1 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/EditionFeatureManagerExtensions.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/EditionFeatureManagerExtensions.cs @@ -18,9 +18,19 @@ namespace Volo.Abp.FeatureManagement return featureManager.GetAllAsync(EditionFeatureValueProvider.ProviderName, editionId.ToString(), fallback); } + public static Task GetOrNullWithProviderForEditionAsync(this IFeatureManager featureManager, [NotNull] string name, Guid editionId, bool fallback = true) + { + return featureManager.GetOrNullWithProviderAsync(name, EditionFeatureValueProvider.ProviderName, editionId.ToString(), fallback); + } + + public static Task> GetAllWithProviderForEditionAsync(this IFeatureManager featureManager, Guid editionId, bool fallback = true) + { + return featureManager.GetAllWithProviderAsync(EditionFeatureValueProvider.ProviderName, editionId.ToString(), fallback); + } + public static Task SetForEditionAsync(this IFeatureManager featureManager, Guid editionId, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false) { return featureManager.SetAsync(name, value, EditionFeatureValueProvider.ProviderName, editionId.ToString(), forceToSet); } } -} \ 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..454ade5476 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,34 @@ 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; - + var featureNameValueWithGrantedProvider = new FeatureNameValueWithGrantedProvider(feature.Name, null); foreach (var provider in providerList) { - var providerValue = await provider.GetOrNullAsync( - feature, - provider.Name == providerName ? providerKey : null - ); + string pk = null; + if (provider.Compatible(providerName)) + { + pk = providerKey; + } - if (providerValue != null) + var value = await provider.GetOrNullAsync(feature, pk); + if (value != null) { - value = providerValue; + featureNameValueWithGrantedProvider.Value = value; + featureNameValueWithGrantedProvider.Provider = new FeatureValueProviderInfo(provider.Name, pk); + break; } } - if (value != null) + if (featureNameValueWithGrantedProvider.Value != null) { - featureValues[feature.Name] = new FeatureNameValue(feature.Name, value); + featureValues[feature.Name] = featureNameValueWithGrantedProvider; } } @@ -100,10 +117,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 +137,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 +168,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 +183,25 @@ namespace Volo.Abp.FeatureManagement providers = providers.SkipWhile(c => c.Name != providerName); } - string value = null; + var featureNameValueWithGrantedProvider = new FeatureNameValueWithGrantedProvider(name, 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.Value = value; + featureNameValueWithGrantedProvider.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.Domain/Volo/Abp/FeatureManagement/TenantFeatureManagerExtensions.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/TenantFeatureManagerExtensions.cs index 972c8f7d53..97a148d959 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/TenantFeatureManagerExtensions.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/TenantFeatureManagerExtensions.cs @@ -18,6 +18,16 @@ namespace Volo.Abp.FeatureManagement return featureManager.GetAllAsync(TenantFeatureValueProvider.ProviderName, tenantId.ToString(), fallback); } + public static Task GetOrNullWithProviderForTenantAsync(this IFeatureManager featureManager, [NotNull] string name, Guid tenantId, bool fallback = true) + { + return featureManager.GetOrNullWithProviderAsync(name, TenantFeatureValueProvider.ProviderName, tenantId.ToString(), fallback); + } + + public static Task> GetAllWithProviderForTenantAsync(this IFeatureManager featureManager, Guid tenantId, bool fallback = true) + { + return featureManager.GetAllWithProviderAsync(TenantFeatureValueProvider.ProviderName, tenantId.ToString(), fallback); + } + public static Task SetForTenantAsync(this IFeatureManager featureManager, Guid tenantId, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false) { return featureManager.SetAsync(name, value, TenantFeatureValueProvider.ProviderName, tenantId.ToString(), forceToSet); 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..f5adbf79d4 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.Provider.Name);
- @feature.DisplayName + @feature.DisplayName @(disabled ? $"({feature.Provider.Name})" : "") + @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 +}