created feature-management modal & added to tenant management

pull/905/head
Yunus Emre Kalkan 7 years ago
parent dd9fbcda60
commit 8a28f5e303

@ -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,78 @@
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)
{
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)
{
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);
}
}
}
}
}

@ -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);

@ -11,19 +11,17 @@
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="wwwroot\**\*.*" />
<EmbeddedResource Include="Pages\**\*.cshtml" Exclude="*.cs" />
<EmbeddedResource Include="Pages\**\*.cshtml" />
<EmbeddedResource Include="Pages\**\*.js" />
<EmbeddedResource Include="Pages\**\*.css" />
<EmbeddedResource Include="Localization\Resources\**\*.json" />
</ItemGroup>
<ItemGroup>
<Content Remove="wwwroot\**\*.*" />
<Content Remove="Pages\**\*.cshtml" />
<Content Remove="Pages\**\*.js" />
<Content Remove="Pages\**\*.css" />
<Content Remove="Localization\Resources\**\*.json" />
<Content Remove="Properties\launchSettings.json" />
<None Include="Properties\launchSettings.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" />

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\common.props" />
@ -15,6 +15,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.TenantManagement.Domain.Shared\Volo.Abp.TenantManagement.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\feature-management\src\Volo.Abp.FeatureManagement.Application.Contracts\Volo.Abp.FeatureManagement.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Ddd.Application\Volo.Abp.Ddd.Application.csproj" />
</ItemGroup>

@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.FeatureManagement;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.TenantManagement.Localization;
@ -10,6 +11,7 @@ namespace Volo.Abp.TenantManagement
{
[DependsOn(typeof(AbpDddApplicationModule))]
[DependsOn(typeof(AbpTenantManagementDomainSharedModule))]
[DependsOn(typeof(AbpFeatureManagementApplicationContractsModule))]
public class AbpTenantManagementApplicationContractsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\common.props" />
@ -16,8 +16,9 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.TenantManagement.Application.Contracts\Volo.Abp.TenantManagement.Application.Contracts.csproj" />
<ProjectReference Include="..\Volo.Abp.TenantManagement.Domain\Volo.Abp.TenantManagement.Domain.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.UI\Volo.Abp.UI.csproj" />
<ProjectReference Include="..\..\..\feature-management\src\Volo.Abp.FeatureManagement.Application\Volo.Abp.FeatureManagement.Application.csproj" />
</ItemGroup>
</Project>

@ -1,11 +1,13 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper;
using Volo.Abp.FeatureManagement;
using Volo.Abp.Modularity;
namespace Volo.Abp.TenantManagement
{
[DependsOn(typeof(AbpTenantManagementDomainModule))]
[DependsOn(typeof(AbpTenantManagementApplicationContractsModule))]
[DependsOn(typeof(AbpFeatureManagementApplicationModule))]
public class AbpTenantManagementApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)

@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AutoMapper;
using Volo.Abp.FeatureManagement;
using Volo.Abp.Localization;
using Volo.Abp.Localization.Resources.AbpValidation;
using Volo.Abp.Modularity;
@ -16,6 +17,7 @@ namespace Volo.Abp.TenantManagement.Web
{
[DependsOn(typeof(AbpTenantManagementHttpApiModule))]
[DependsOn(typeof(AbpAspNetCoreMvcUiBootstrapModule))]
[DependsOn(typeof(AbpFeatureManagementWebModule))]
[DependsOn(typeof(AbpAutoMapperModule))]
public class AbpTenantManagementWebModule : AbpModule
{

@ -13,7 +13,10 @@
PageLayout.Content.MenuItemName = TenantManagementMenuNames.Tenants;
}
@section scripts {
<script type="text/javascript" src="~/modules/multi-tenancy/views/tenants/index.js"></script>
<abp-script-bundle name="@typeof(IndexModel).FullName">
<abp-script src="/modules/multi-tenancy/views/tenants/index.js" />
<abp-script src="/Pages/FeatureManagement/feature-management-modal.js" />
</abp-script-bundle>
}
<abp-card id="TenantsWrapper">
<abp-card-header>

@ -29,8 +29,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\feature-management\src\Volo.Abp.FeatureManagement.Web\Volo.Abp.FeatureManagement.Web.csproj" />
<ProjectReference Include="..\Volo.Abp.TenantManagement.HttpApi\Volo.Abp.TenantManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
</ItemGroup>

@ -5,6 +5,7 @@
var _editModal = new abp.ModalManager(abp.appPath + 'TenantManagement/Tenants/EditModal');
var _createModal = new abp.ModalManager(abp.appPath + 'TenantManagement/Tenants/CreateModal');
var _featuresModal = new abp.ModalManager(abp.appPath + 'FeatureManagement/FeatureManagementModal');
$(function () {
@ -27,6 +28,18 @@
});
}
},
{
text: l('Features'),
visible: function () {
return true; //TODO: Check permission
},
action: function (data) {
_featuresModal.open({
providerName: 'Tenant',
providerKey: data.record.id
});
}
},
{
text: l('Delete'),
visible: function () { return true; }, //TODO: Check permission

Loading…
Cancel
Save