From f5779c9e8966fad0974a6c3638b3f541c4a246c2 Mon Sep 17 00:00:00 2001 From: Piotr Szmyd Date: Mon, 10 Feb 2014 21:56:49 +0100 Subject: [PATCH] Features. Added confirm popup when disabling a feature that other enabled features depend on. --- .../Controllers/AdminController.cs | 6 ++++-- .../Orchard.Modules/Models/ModuleFeature.cs | 9 ++++++++- .../Orchard.Modules/Scripts/features.admin.js | 15 ++++++++++----- .../Orchard.Modules/Scripts/features.admin.min.js | 6 ++++-- .../Scripts/features.admin.min.js.map | 4 ++-- .../Orchard.Modules/Services/IModuleService.cs | 7 +++++++ .../Orchard.Modules/Services/ModuleService.cs | 9 +++++++++ .../Orchard.Modules/Views/Admin/Features.cshtml | 12 +++++++++++- 8 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs index 51771c4c3..33dc4dedc 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs @@ -179,8 +179,10 @@ namespace Orchard.Modules.Controllers { Descriptor = f, IsEnabled = _shellDescriptor.Features.Any(sf => sf.Name == f.Id), IsRecentlyInstalled = _moduleService.IsRecentlyInstalled(f.Extension), - NeedsUpdate = featuresThatNeedUpdate.Contains(f.Id) - }); + NeedsUpdate = featuresThatNeedUpdate.Contains(f.Id), + DependentFeatures = _moduleService.GetDependentFeatures(f.Id).Where(x => x.Id != f.Id).ToList() + }) + .ToList(); return View(new FeaturesViewModel { Features = features }); } diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Models/ModuleFeature.cs b/src/Orchard.Web/Modules/Orchard.Modules/Models/ModuleFeature.cs index 2ca10f4fd..80270752b 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Models/ModuleFeature.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Models/ModuleFeature.cs @@ -1,4 +1,6 @@ -using Orchard.Environment.Extensions.Models; +using System.Collections; +using System.Collections.Generic; +using Orchard.Environment.Extensions.Models; namespace Orchard.Modules.Models { /// @@ -29,5 +31,10 @@ namespace Orchard.Modules.Models { /// Boolean value indicating if the feature was recently installed. /// public bool IsRecentlyInstalled { get; set; } + + /// + /// List of features that depend on this feature. + /// + public IEnumerable DependentFeatures { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.js b/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.js index 332484393..d178cbcc7 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.js +++ b/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.js @@ -41,13 +41,18 @@ var featureId = actionLink.data("feature-id"); var action = actionLink.data("feature-action"); var force = actionLink.data("feature-force"); + var dependants = actionLink.data("feature-dependants"); - $("[name='submit.BulkExecute']").val("yes"); - $("[name='featureIds']").val(featureId); - $("[name='bulkAction']").val(action); - $("[name='force']").val(force); + if (!dependants || /^\s*$/.test(dependants) || confirm(confirmDisableMessage + "\n\n" + dependants)) { + + $("[name='submit.BulkExecute']").val("yes"); + $("[name='featureIds']").val(featureId); + $("[name='bulkAction']").val(action); + $("[name='force']").val(force); + + actionLink.parents("form:first").submit(); + } - actionLink.parents("form:first").submit(); e.preventDefault(); }); }; diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.min.js b/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.min.js index 290669a05..dc6081236 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.min.js +++ b/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.min.js @@ -1,2 +1,4 @@ -$(function(){var n=function(){var n=$(".bulk-actions-wrapper").addClass("visible"),t=$(".switch-for-switchable");t.prepend(n),$("#search-box").focus().keyup(function(){var n=$(this).val(),t;if(n==""){$("li.category").show(),$("li.feature:hidden").show();return}$("li.feature").each(function(){var t=$(this),i=t.find("h3:first").text();i.toLowerCase().indexOf(n.toLowerCase())>=0?t.show():t.hide()}),$("li.category:hidden").show(),t=$("li.category:not(:has(li.feature:visible))").hide()})},t=function(){$("li.feature h3").on("change","input[type='checkbox']",function(){var n=$(this).is(":checked"),t=$(this).parents("li.feature:first");t.toggleClass("selected",n)})},i=function(){$("li.feature .actions").on("click","a[data-feature-action]",function(n){var t=$(this),i=t.data("feature-id"),r=t.data("feature-action"),u=t.data("feature-force");$("[name='submit.BulkExecute']").val("yes"),$("[name='featureIds']").val(i),$("[name='bulkAction']").val(r),$("[name='force']").val(u),t.parents("form:first").submit(),n.preventDefault()})};n(),t(),i()}); -//@ sourceMappingURL=features.admin.min.js.map \ No newline at end of file +$(function(){var n=function(){var n=$(".bulk-actions-wrapper").addClass("visible"),t=$(".switch-for-switchable");t.prepend(n);$("#search-box").focus().keyup(function(){var n=$(this).val(),t;if(n==""){$("li.category").show();$("li.feature:hidden").show();return}$("li.feature").each(function(){var t=$(this),i=t.find("h3:first").text();i.toLowerCase().indexOf(n.toLowerCase())>=0?t.show():t.hide()});$("li.category:hidden").show();t=$("li.category:not(:has(li.feature:visible))").hide()})},t=function(){$("li.feature h3").on("change","input[type='checkbox']",function(){var n=$(this).is(":checked"),t=$(this).parents("li.feature:first");t.toggleClass("selected",n)})},i=function(){$("li.feature .actions").on("click","a[data-feature-action]",function(n){var t=$(this),r=t.data("feature-id"),u=t.data("feature-action"),f=t.data("feature-force"),i=t.data("feature-dependants");(!i||/^\s*$/.test(i)||confirm(confirmDisableMessage+"\n\n"+i))&&($("[name='submit.BulkExecute']").val("yes"),$("[name='featureIds']").val(r),$("[name='bulkAction']").val(u),$("[name='force']").val(f),t.parents("form:first").submit());n.preventDefault()})};n();t();i()}); +/* +//# sourceMappingURL=features.admin.min.js.map +*/ \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.min.js.map b/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.min.js.map index bf48f7e9b..f90f0b5ac 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.min.js.map +++ b/src/Orchard.Web/Modules/Orchard.Modules/Scripts/features.admin.min.js.map @@ -2,7 +2,7 @@ "version":3, "file":"features.admin.min.js", "lineCount":1, -"mappings":"AAAAA,CAAC,CAAC,QAAQ,CAAA,CAAG,CAET,IAAIC,EAAuBA,QAAQ,CAAA,CAAG,CAClC,IAAIC,EAAcF,CAAC,CAAC,uBAAD,CAAyBG,SAAS,CAAC,SAAD,EACjDC,EAAYJ,CAAC,CAAC,wBAAD,CAD+C,CAEhEI,CAASC,QAAQ,CAACH,CAAD,CAAa,CAC9BF,CAAC,CAAC,aAAD,CAAeM,MAAM,CAAA,CAAEC,MAAM,CAAC,QAAQ,CAAA,CAAG,CACtC,IAAIC,EAAOR,CAAC,CAAC,IAAD,CAAMS,IAAI,CAAA,EAkBlBC,CAlBoB,CAExB,GAAIF,CAAK,EAAG,GAAI,CACZR,CAAC,CAAC,aAAD,CAAeW,KAAK,CAAA,CAAE,CACvBX,CAAC,CAAC,mBAAD,CAAqBW,KAAK,CAAA,CAAE,CAC7B,MAHY,CAMhBX,CAAC,CAAC,YAAD,CAAcY,KAAK,CAAC,QAAQ,CAAA,CAAG,CAC5B,IAAIC,EAAMb,CAAC,CAAC,IAAD,EACPc,EAAQD,CAAGE,KAAK,CAAC,UAAD,CAAYP,KAAK,CAAA,CADpB,CAEbM,CAAKE,YAAY,CAAA,CAAEC,QAAQ,CAACT,CAAIQ,YAAY,CAAA,CAAjB,CAAqB,EAAG,CAAvD,CACIH,CAAGF,KAAK,CAAA,CADZ,CAGIE,CAAGK,KAAK,CAAA,CANgB,CAAZ,CAOlB,CAEFlB,CAAC,CAAC,oBAAD,CAAsBW,KAAK,CAAA,CAAE,CAC1BD,CAAO,CAAEV,CAAC,CAAC,2CAAD,CAA6CkB,KAAK,CAAA,CAnB1B,CAAZ,CAJI,EA2BlCC,EAA8BA,QAAQ,CAAA,CAAG,CACzCnB,CAAC,CAAC,eAAD,CAAiBoB,GAAG,CAAC,QAAQ,CAAE,wBAAwB,CAAE,QAAQ,CAAA,CAAG,CACjE,IAAIC,EAAUrB,CAAC,CAAC,IAAD,CAAMsB,GAAG,CAAC,UAAD,EACpBC,EAAUvB,CAAC,CAAC,IAAD,CAAMwB,QAAQ,CAAC,kBAAD,CADO,CAEpCD,CAAOE,YAAY,CAAC,UAAU,CAAEJ,CAAb,CAH8C,CAAhD,CADoB,EAQzCK,EAAwBA,QAAQ,CAAA,CAAG,CACnC1B,CAAC,CAAC,qBAAD,CAAuBoB,GAAG,CAAC,OAAO,CAAE,wBAAwB,CAAE,QAAQ,CAACO,CAAD,CAAI,CACvE,IAAIC,EAAa5B,CAAC,CAAC,IAAD,EACd6B,EAAYD,CAAUE,KAAK,CAAC,YAAD,EAC3BC,EAASH,CAAUE,KAAK,CAAC,gBAAD,EACxBE,EAAQJ,CAAUE,KAAK,CAAC,eAAD,CAHH,CAKxB9B,CAAC,CAAC,6BAAD,CAA+BS,IAAI,CAAC,KAAD,CAAO,CAC3CT,CAAC,CAAC,qBAAD,CAAuBS,IAAI,CAACoB,CAAD,CAAW,CACvC7B,CAAC,CAAC,qBAAD,CAAuBS,IAAI,CAACsB,CAAD,CAAQ,CACpC/B,CAAC,CAAC,gBAAD,CAAkBS,IAAI,CAACuB,CAAD,CAAO,CAE9BJ,CAAUJ,QAAQ,CAAC,YAAD,CAAcS,OAAO,CAAA,CAAE,CACzCN,CAACO,eAAe,CAAA,CAZuD,CAAhD,CADQ,CAVtC,CA2BDjC,CAAoB,CAAA,CAAE,CACtBkB,CAA2B,CAAA,CAAE,CAC7BO,CAAqB,CAAA,CAxDZ,CAAZ,CAyDC", +"mappings":"AAAAA,CAAC,CAAC,QAAQ,CAAA,CAAG,CAET,IAAIC,EAAuB,QAAQ,CAAA,CAAG,CAClC,IAAIC,EAAcF,CAAC,CAAC,uBAAD,CAAyBG,SAAS,CAAC,SAAD,EACjDC,EAAYJ,CAAC,CAAC,wBAAD,CAD+C,CAEhEI,CAASC,QAAQ,CAACH,CAAD,CAAa,CAC9BF,CAAC,CAAC,aAAD,CAAeM,MAAM,CAAA,CAAEC,MAAM,CAAC,QAAQ,CAAA,CAAG,CACtC,IAAIC,EAAOR,CAAC,CAAC,IAAD,CAAMS,IAAI,CAAA,EAkBlBC,CAlBoB,CAExB,GAAIF,CAAK,EAAG,GAAI,CACZR,CAAC,CAAC,aAAD,CAAeW,KAAK,CAAA,CAAE,CACvBX,CAAC,CAAC,mBAAD,CAAqBW,KAAK,CAAA,CAAE,CAC7B,MAHY,CAMhBX,CAAC,CAAC,YAAD,CAAcY,KAAK,CAAC,QAAQ,CAAA,CAAG,CAC5B,IAAIC,EAAMb,CAAC,CAAC,IAAD,EACPc,EAAQD,CAAGE,KAAK,CAAC,UAAD,CAAYP,KAAK,CAAA,CADpB,CAEbM,CAAKE,YAAY,CAAA,CAAEC,QAAQ,CAACT,CAAIQ,YAAY,CAAA,CAAjB,CAAqB,EAAG,CAAvD,CACIH,CAAGF,KAAK,CAAA,CADZ,CAGIE,CAAGK,KAAK,CAAA,CANgB,CAAZ,CAOlB,CAEFlB,CAAC,CAAC,oBAAD,CAAsBW,KAAK,CAAA,CAAE,CAC1BD,CAAO,CAAEV,CAAC,CAAC,2CAAD,CAA6CkB,KAAK,CAAA,CAnB1B,CAAZ,CAJI,EA2BlCC,EAA8B,QAAQ,CAAA,CAAG,CACzCnB,CAAC,CAAC,eAAD,CAAiBoB,GAAG,CAAC,QAAQ,CAAE,wBAAwB,CAAE,QAAQ,CAAA,CAAG,CACjE,IAAIC,EAAUrB,CAAC,CAAC,IAAD,CAAMsB,GAAG,CAAC,UAAD,EACpBC,EAAUvB,CAAC,CAAC,IAAD,CAAMwB,QAAQ,CAAC,kBAAD,CADO,CAEpCD,CAAOE,YAAY,CAAC,UAAU,CAAEJ,CAAb,CAH8C,CAAhD,CADoB,EAQzCK,EAAwB,QAAQ,CAAA,CAAG,CACnC1B,CAAC,CAAC,qBAAD,CAAuBoB,GAAG,CAAC,OAAO,CAAE,wBAAwB,CAAE,QAAQ,CAACO,CAAD,CAAI,CACvE,IAAIC,EAAa5B,CAAC,CAAC,IAAD,EACd6B,EAAYD,CAAUE,KAAK,CAAC,YAAD,EAC3BC,EAASH,CAAUE,KAAK,CAAC,gBAAD,EACxBE,EAAQJ,CAAUE,KAAK,CAAC,eAAD,EACvBG,EAAaL,CAAUE,KAAK,CAAC,oBAAD,CAJR,EAMpB,CAACG,CAAW,EAAU,OAAAC,KAAK,CAACD,CAAD,CAAa,EAAGE,OAAO,CAACC,qBAAsB,CAAE,MAAO,CAAEH,CAAlC,E,GAElDjC,CAAC,CAAC,6BAAD,CAA+BS,IAAI,CAAC,KAAD,CAAO,CAC3CT,CAAC,CAAC,qBAAD,CAAuBS,IAAI,CAACoB,CAAD,CAAW,CACvC7B,CAAC,CAAC,qBAAD,CAAuBS,IAAI,CAACsB,CAAD,CAAQ,CACpC/B,CAAC,CAAC,gBAAD,CAAkBS,IAAI,CAACuB,CAAD,CAAO,CAE9BJ,CAAUJ,QAAQ,CAAC,YAAD,CAAca,OAAO,CAAA,EAAE,CAG7CV,CAACW,eAAe,CAAA,CAjBuD,CAAhD,CADQ,CAVtC,CAgCDrC,CAAoB,CAAA,CAAE,CACtBkB,CAA2B,CAAA,CAAE,CAC7BO,CAAqB,CAAA,CA7DZ,CAAZ,CA8DC", "sources":["features.admin.js"], -"names":["$","initializeFeaturesUI","bulkActions","addClass","theSwitch","prepend","focus","keyup","text","val","toHide","show","each","elt","value","find","toLowerCase","indexOf","hide","initializeSelectionBehavior","on","checked","is","wrapper","parents","toggleClass","initializeActionLinks","e","actionLink","featureId","data","action","force","submit","preventDefault"] +"names":["$","initializeFeaturesUI","bulkActions","addClass","theSwitch","prepend","focus","keyup","text","val","toHide","show","each","elt","value","find","toLowerCase","indexOf","hide","initializeSelectionBehavior","on","checked","is","wrapper","parents","toggleClass","initializeActionLinks","e","actionLink","featureId","data","action","force","dependants","test","confirm","confirmDisableMessage","submit","preventDefault"] } diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Services/IModuleService.cs b/src/Orchard.Web/Modules/Orchard.Modules/Services/IModuleService.cs index 07ecb070a..ea9120dc7 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Services/IModuleService.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Services/IModuleService.cs @@ -42,5 +42,12 @@ namespace Orchard.Modules.Services { /// The extension descriptor. /// True if the feature was recently installed; false otherwise. bool IsRecentlyInstalled(ExtensionDescriptor extensionDescriptor); + + /// + /// Gets a list of dependent features of a given feature. + /// + /// ID of a feature. + /// List of dependent feature descriptors. + IEnumerable GetDependentFeatures(string featureId); } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs b/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs index 3616a9052..6c9fd9da8 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs @@ -115,6 +115,15 @@ namespace Orchard.Modules.Services { return DateTime.UtcNow.Subtract(lastWrittenUtc) < new TimeSpan(1, 0, 0, 0); } + public IEnumerable GetDependentFeatures(string featureId) { + var dependants = _featureManager.GetDependentFeatures(featureId); + var availableFeatures = _featureManager.GetAvailableFeatures().ToLookup(f => f.Id, StringComparer.OrdinalIgnoreCase); + + return dependants + .SelectMany(id => availableFeatures[id]) + .ToList(); + } + /// /// Retrieves the full path of the manifest file for a module's extension descriptor. /// diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml index 1c6f7db9d..9324bfcae 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml @@ -75,6 +75,7 @@ .Where(d => !Model.Features.Any(f => f.Descriptor.Id.Equals(d, StringComparison.OrdinalIgnoreCase))); var showDisable = categoryName.ToString() != "Core"; var showEnable = !missingDependencies.Any() && feature.Descriptor.Id != "Orchard.Setup"; +
  • @@ -107,7 +108,8 @@
    @if (showDisable && feature.IsEnabled) { - @T("Disable") + var dependantsJoined = string.Join(", ", feature.DependentFeatures.Select(f => f.Name)); + @T("Disable") } @if (showEnable && !feature.IsEnabled) { @@ -123,4 +125,12 @@ }
  • } }} + + using (Script.Foot()) { + + } } \ No newline at end of file