Some work on the feature managment UI

- start of dependency aware feature disable/enable
- bit of a perf improvement when working with the available features list (thanks, ToList, as usual)

--HG--
branch : dev
This commit is contained in:
Nathan Heskew
2010-05-14 15:52:22 -07:00
parent d5cdc0d37e
commit 7db897c475
4 changed files with 66 additions and 106 deletions

View File

@@ -44,44 +44,12 @@ namespace Orchard.Modules.Controllers {
});
}
public ActionResult Features(FeaturesOptions options) {
public ActionResult Features() {
if (!Services.Authorizer.Authorize(Permissions.ManageFeatures, T("Not allowed to manage features")))
return new HttpUnauthorizedResult();
var features = _moduleService.GetAvailableFeatures();
return View(new FeaturesViewModel {Features = features, Options = options});
}
[HttpPost, ActionName("Features")]
[FormValueRequired("submit.BulkEdit")]
public ActionResult FeaturesPOST(FeaturesOptions options, IList<string> selection) {
if (selection != null && selection.Count > 0)
{
switch (options.BulkAction)
{
case FeaturesBulkAction.None:
break;
case FeaturesBulkAction.Enable:
if (!Services.Authorizer.Authorize(Permissions.ManageFeatures, T("Not allowed to enable features")))
return new HttpUnauthorizedResult();
_moduleService.EnableFeatures(selection);
//todo: (heskew) need better messages
//todo: (heskew) hmmm...need a helper to comma-separate all but last, which would get the " and " treatment...all localized, of course
Services.Notifier.Information(T("{0} were enabled", string.Join(", ", selection.ToArray())));
break;
case FeaturesBulkAction.Disable:
if (!Services.Authorizer.Authorize(Permissions.ManageFeatures, T("Not allowed to disable features")))
return new HttpUnauthorizedResult();
_moduleService.DisableFeatures(selection);
//todo: (heskew) need better messages
Services.Notifier.Information(T("{0} were disabled", string.Join(", ", selection.ToArray())));
break;
default:
throw new ArgumentOutOfRangeException();
}
}
return RedirectToAction("Features");
return View(new FeaturesViewModel {Features = features});
}
[ValidateAntiForgeryTokenOrchard]
@@ -107,7 +75,7 @@ namespace Orchard.Modules.Controllers {
return new NotFoundResult();
_moduleService.DisableFeatures(new[] { featureName });
Services.Notifier.Information(T("{0} was disabled", featureName));
//Services.Notifier.Information(T("{0} was disabled", featureName));
return RedirectToAction("Features");
}

View File

@@ -48,10 +48,11 @@ namespace Orchard.Modules.Services {
}
public IEnumerable<IModuleFeature> GetAvailableFeatures() {
var enabledFeatures = _shellDescriptorManager.GetShellDescriptor().EnabledFeatures;
var enabledFeatures = _shellDescriptorManager.GetShellDescriptor().EnabledFeatures.ToList();
return GetInstalledModules()
.SelectMany(m => _extensionManager.LoadFeatures(m.Features))
.Select(f => AssembleModuleFromDescriptor(f, enabledFeatures.FirstOrDefault(sf => string.Equals(sf.Name, f.Descriptor.Name, StringComparison.OrdinalIgnoreCase)) != null));
.Select(f => AssembleModuleFromDescriptor(f, enabledFeatures.FirstOrDefault(sf => string.Equals(sf.Name, f.Descriptor.Name, StringComparison.OrdinalIgnoreCase)) != null))
.ToList();
}
public IEnumerable<Feature> GetAvailableFeaturesByModule(string moduleName) {
@@ -69,9 +70,20 @@ namespace Orchard.Modules.Services {
public void DisableFeatures(IEnumerable<string> featureNames) {
var shellDescriptor = _shellDescriptorManager.GetShellDescriptor();
var enabledFeatures = shellDescriptor.EnabledFeatures.ToList();
enabledFeatures.RemoveAll(f => featureNames.Contains(f.Name));
var features = GetAvailableFeatures();
foreach (var featureName in featureNames) {
var feature = featureName;
var dependants = features.Where(f => f.IsEnabled && f.Descriptor.Dependencies != null && f.Descriptor.Dependencies.Contains(feature));
if (dependants.Count() == 0) {
enabledFeatures.RemoveAll(f => f.Name == feature);
}
else {
// list what else will be disabled with ok/cancel
}
}
_shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures, shellDescriptor.Parameters);
}

View File

@@ -4,16 +4,5 @@ using Orchard.Mvc.ViewModels;
namespace Orchard.Modules.ViewModels {
public class FeaturesViewModel : BaseViewModel {
public IEnumerable<IModuleFeature> Features { get; set; }
public FeaturesOptions Options { get; set; }
}
public class FeaturesOptions {
public FeaturesBulkAction BulkAction { get; set; }
}
public enum FeaturesBulkAction {
None,
Enable,
Disable
}
}

View File

@@ -2,31 +2,18 @@
<%@ Import Namespace="Orchard.Mvc.Html"%>
<%@ Import Namespace="Orchard.Modules.ViewModels"%>
<h1><%=Html.TitleForPage(T("Manage Features").ToString()) %></h1>
<div class="manage" style="visibility:hidden"><%=Html.ActionLink(T("∞").ToString(), "Features", new { }, new { @class = "button primaryAction" })%></div>
<% if (Model.Features.Count() > 0) {
using (Html.BeginFormAntiForgeryPost()) { %>
<%=Html.ValidationSummary()%>
<fieldset class="actions bulk">
<label for="publishActions"><%=_Encoded("Actions: ")%></label>
<select id="publishActions" name="<%=Html.NameOf(m => m.Options.BulkAction) %>">
<%=Html.SelectOption(Model.Options.BulkAction, FeaturesBulkAction.None, _Encoded("Choose action...").ToString())%>
<%=Html.SelectOption(Model.Options.BulkAction, FeaturesBulkAction.Enable, _Encoded("Enable").ToString())%>
<%=Html.SelectOption(Model.Options.BulkAction, FeaturesBulkAction.Disable, _Encoded("Disable").ToString())%>
</select>
<input class="button" type="submit" name="submit.BulkEdit" value="<%=_Encoded("Apply") %>" />
</fieldset>
<fieldset class="pageList">
<% if (Model.Features.Count() > 0) { %>
<ul class="contentItems"><%
foreach (var featureGroup in Model.Features.OrderBy(f => f.Descriptor.Category).GroupBy(f => f.Descriptor.Category)) { %>
<li<%=featureGroup == Model.Features.Last() ? " class=\"last\"" : "" %>>
var featureGroups = Model.Features.OrderBy(f => f.Descriptor.Category).GroupBy(f => f.Descriptor.Category);
foreach (var featureGroup in featureGroups) { %>
<li<%=featureGroup == featureGroups.Last() ? " class=\"last\"" : "" %>>
<h2><%=Html.Encode(featureGroup.First().Descriptor.Category ?? T("Uncategorized")) %></h2>
<ul><%
foreach (var feature in featureGroup.OrderBy(f => f.Descriptor.Name)) {%>
<li<%=feature == featureGroup.Last() ? " class=\"last\"" : "" %> id="<%=Html.Encode(feature.Descriptor.Name) %>">
var features = featureGroup.OrderBy(f => f.Descriptor.Name);
foreach (var feature in features) {%>
<li<%=feature == features.Last() ? " class=\"last\"" : "" %> id="<%=Html.Encode(feature.Descriptor.Name) %>">
<div class="summary">
<div class="properties">
<input type="checkbox" name="selection" value="<%=Html.Encode(feature.Descriptor.Name) %>" />
<h3><%=Html.Encode(feature.Descriptor.Name) %></h3>
<ul class="pageStatus">
<li><%
@@ -45,10 +32,16 @@ using (Html.BeginFormAntiForgeryPost()) { %>
</ul>
</div>
<div class="related"><%
if (feature.IsEnabled) { %>
<a href="<%=Html.AntiForgeryTokenGetUrl(Url.Action("Disable", new { featureName = feature.Descriptor.Name, area = "Orchard.Modules" })) %>"><%=_Encoded("Disable") %></a><%
} else { %>
<a href="<%=Html.AntiForgeryTokenGetUrl(Url.Action("Enable", new { featureName = feature.Descriptor.Name, area = "Orchard.Modules" })) %>"><%=_Encoded("Enable") %></a><%
if (feature.IsEnabled) {
using (Html.BeginFormAntiForgeryPost(string.Format("{0}#{1}", Url.Action("Disable", new { area = "Orchard.Modules" }), Html.AttributeEncode(feature.Descriptor.Name)), FormMethod.Post, new {@class = "inline link"})) { %>
<%=Html.Hidden("featureName", feature.Descriptor.Name) %>
<button type="submit"><%=_Encoded("Disable") %></button><%
}
} else {
using (Html.BeginFormAntiForgeryPost(string.Format("{0}#{1}", Url.Action("Enable", new { area = "Orchard.Modules" }), Html.AttributeEncode(feature.Descriptor.Name)), FormMethod.Post, new {@class = "inline link"})) { %>
<%=Html.Hidden("featureName", feature.Descriptor.Name) %>
<button type="submit"><%=_Encoded("Enable") %></button><%
}
} %>
</div>
</div>
@@ -59,5 +52,3 @@ using (Html.BeginFormAntiForgeryPost()) { %>
} %>
</ul><%
} %>
</fieldset><%
} %>