diff --git a/src/Umbraco.Core/CodeAnnotations/ActionMetadataAttribute.cs b/src/Umbraco.Core/CodeAnnotations/ActionMetadataAttribute.cs
deleted file mode 100644
index 9ef87e9a5f..0000000000
--- a/src/Umbraco.Core/CodeAnnotations/ActionMetadataAttribute.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System;
-using Umbraco.Core.Exceptions;
-
-namespace Umbraco.Core.CodeAnnotations
-{
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
- internal class ActionMetadataAttribute : Attribute
- {
- public string Category { get; }
- public string Name { get; }
-
- ///
- /// Constructor used to assign a Category, since no name is assigned it will try to be translated from the language files based on the action's alias
- ///
- ///
- public ActionMetadataAttribute(string category)
- {
- if (string.IsNullOrWhiteSpace(category)) throw new ArgumentNullOrEmptyException(nameof(category));
- Category = category;
- }
-
- ///
- /// Constructor used to assign an explicit name and category
- ///
- ///
- ///
- public ActionMetadataAttribute(string category, string name)
- {
- if (string.IsNullOrWhiteSpace(category)) throw new ArgumentNullOrEmptyException(nameof(category));
- if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
- Category = category;
- Name = name;
- }
- }
-}
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 45f8b5ec52..acda9ef589 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -143,7 +143,6 @@
-
diff --git a/src/Umbraco.Tests/Composing/ActionCollectionTests.cs b/src/Umbraco.Tests/Composing/ActionCollectionTests.cs
deleted file mode 100644
index 46e4eee765..0000000000
--- a/src/Umbraco.Tests/Composing/ActionCollectionTests.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-using System.Linq;
-using NUnit.Framework;
-using Umbraco.Web;
-using Umbraco.Web.UI.Pages;
-using Umbraco.Web._Legacy.Actions;
-
-namespace Umbraco.Tests.Composing
-{
- [TestFixture]
- public class ActionCollectionTests : ComposingTestBase
- {
- [Test]
- public void ActionCollectionBuilderWorks()
- {
- var collectionBuilder = new ActionCollectionBuilder();
- collectionBuilder.SetProducer(() => TypeLoader.GetActions());
-
- var actions = collectionBuilder.CreateCollection();
- Assert.AreEqual(2, actions.Count());
-
- // order is unspecified, but both must be there
- var hasAction1 = actions.ElementAt(0) is SingletonAction || actions.ElementAt(1) is SingletonAction;
- var hasAction2 = actions.ElementAt(0) is NonSingletonAction || actions.ElementAt(1) is NonSingletonAction;
- Assert.IsTrue(hasAction1);
- Assert.IsTrue(hasAction2);
-
- var singletonAction = (SingletonAction) (actions.ElementAt(0) is SingletonAction ? actions.ElementAt(0) : actions.ElementAt(1));
-
- // ensure it is a singleton
- Assert.AreSame(SingletonAction.Instance, singletonAction);
- }
-
- #region Test Objects
-
- public class SingletonAction : IAction
- {
- public static SingletonAction Instance { get; } = new SingletonAction();
-
- public char Letter => 'I';
-
- public string JsFunctionName => $"{ClientTools.Scripts.GetAppActions}.actionAssignDomain()";
-
- public string JsSource => null;
-
- public string Alias => "assignDomain";
-
- public string Icon => ".sprDomain";
-
- public bool ShowInNotifier => false;
-
- public bool CanBePermissionAssigned => true;
-
- public bool OpensDialog => true;
- }
-
- public class NonSingletonAction : IAction
- {
- public char Letter => 'Q';
-
- public string JsFunctionName => $"{ClientTools.Scripts.GetAppActions}.actionAssignDomain()";
-
- public string JsSource => null;
-
- public string Alias => "asfasdf";
-
- public string Icon => ".sprDomain";
-
- public bool ShowInNotifier => false;
-
- public bool CanBePermissionAssigned => true;
-
- public bool OpensDialog => true;
- }
-
- #endregion
- }
-}
diff --git a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs
index 829c488af3..07625db9bf 100644
--- a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs
+++ b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs
@@ -268,13 +268,6 @@ AnotherContentFinder
Assert.AreEqual(2, foundTypes1.Count());
}
- [Test]
- public void Resolves_Actions()
- {
- var actions = _typeLoader.GetActions();
- Assert.AreEqual(33, actions.Count());
- }
-
[Test]
public void GetDataEditors()
{
diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs
index 117b0f9103..cce54c81a4 100644
--- a/src/Umbraco.Tests/Services/UserServiceTests.cs
+++ b/src/Umbraco.Tests/Services/UserServiceTests.cs
@@ -14,7 +14,8 @@ using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
using Umbraco.Tests.Testing;
-using Umbraco.Web._Legacy.Actions;
+using Umbraco.Web.Actions;
+
namespace Umbraco.Tests.Services
{
@@ -70,12 +71,12 @@ namespace Umbraco.Tests.Services
MockedContent.CreateSimpleContent(contentType)
};
ServiceContext.ContentService.Save(content);
- ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[2], ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionDelete.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionMove.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[1], ActionDelete.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[2], ActionBrowse.ActionLetter, new int[] { userGroup.Id });
// Act
var permissions = userService.GetPermissions(user, content[0].Id, content[1].Id, content[2].Id).ToArray();
@@ -103,12 +104,12 @@ namespace Umbraco.Tests.Services
MockedContent.CreateSimpleContent(contentType)
};
ServiceContext.ContentService.Save(content);
- ServiceContext.ContentService.SetPermission(content.ElementAt(0), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content.ElementAt(0), ActionDelete.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content.ElementAt(0), ActionMove.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content.ElementAt(1), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content.ElementAt(1), ActionDelete.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content.ElementAt(2), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content.ElementAt(0), ActionBrowse.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content.ElementAt(0), ActionDelete.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content.ElementAt(0), ActionMove.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content.ElementAt(1), ActionBrowse.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content.ElementAt(1), ActionDelete.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content.ElementAt(2), ActionBrowse.ActionLetter, new int[] { userGroup.Id });
// Act
var permissions = userService.GetPermissions(userGroup, false, content[0].Id, content[1].Id, content[2].Id).ToArray();
@@ -136,11 +137,11 @@ namespace Umbraco.Tests.Services
MockedContent.CreateSimpleContent(contentType)
};
ServiceContext.ContentService.Save(content);
- ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionDelete.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionMove.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[1], ActionDelete.ActionLetter, new int[] { userGroup.Id });
// Act
var permissions = userService.GetPermissions(userGroup, true, content[0].Id, content[1].Id, content[2].Id)
@@ -180,12 +181,12 @@ namespace Umbraco.Tests.Services
};
ServiceContext.ContentService.Save(content);
//assign permissions - we aren't assigning anything explicit for group3 and nothing explicit for content[2] /w group2
- ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup1.Id });
- ServiceContext.ContentService.SetPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup1.Id });
- ServiceContext.ContentService.SetPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup2.Id });
- ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup1.Id });
- ServiceContext.ContentService.SetPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup2.Id });
- ServiceContext.ContentService.SetPermission(content[2], ActionDelete.Instance.Letter, new int[] { userGroup1.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.ActionLetter, new int[] { userGroup1.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionDelete.ActionLetter, new int[] { userGroup1.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionMove.ActionLetter, new int[] { userGroup2.Id });
+ ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.ActionLetter, new int[] { userGroup1.Id });
+ ServiceContext.ContentService.SetPermission(content[1], ActionDelete.ActionLetter, new int[] { userGroup2.Id });
+ ServiceContext.ContentService.SetPermission(content[2], ActionDelete.ActionLetter, new int[] { userGroup1.Id });
// Act
//we don't pass in any nodes so it will return all of them
@@ -249,12 +250,12 @@ namespace Umbraco.Tests.Services
MockedContent.CreateSimpleContent(contentType)
};
ServiceContext.ContentService.Save(content);
- ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(content[2], ActionDelete.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionDelete.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[0], ActionMove.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[1], ActionDelete.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(content[2], ActionDelete.ActionLetter, new int[] { userGroup.Id });
// Act
//we don't pass in any nodes so it will return all of them
@@ -412,11 +413,11 @@ namespace Umbraco.Tests.Services
var child2 = MockedContent.CreateSimpleContent(contentType, "child2", child1);
ServiceContext.ContentService.Save(child2);
- ServiceContext.ContentService.SetPermission(parent, ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(parent, ActionDelete.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(parent, ActionMove.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(parent, ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.SetPermission(parent, ActionDelete.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(parent, ActionBrowse.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(parent, ActionDelete.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(parent, ActionMove.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(parent, ActionBrowse.ActionLetter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.SetPermission(parent, ActionDelete.ActionLetter, new int[] { userGroup.Id });
// Act
var permissions = userService.GetPermissionsForPath(userGroup, child2.Path);
diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
index 7f68f22a27..d80802b1cf 100644
--- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
+++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
@@ -36,9 +36,10 @@ using Umbraco.Web;
using Umbraco.Web.Services;
using Umbraco.Examine;
using Umbraco.Tests.Testing.Objects.Accessors;
+using Umbraco.Web.Actions;
using Umbraco.Web.Composing.CompositionRoots;
using Umbraco.Web.ContentApps;
-using Umbraco.Web._Legacy.Actions;
+
using Current = Umbraco.Core.Composing.Current;
using Umbraco.Web.Routing;
@@ -205,9 +206,7 @@ namespace Umbraco.Tests.Testing
Container.RegisterSingleton(f => runtimeStateMock.Object);
// ah...
- Container.RegisterCollectionBuilder()
- .SetProducer(Enumerable.Empty);
-
+ Container.RegisterCollectionBuilder();
Container.RegisterCollectionBuilder();
Container.RegisterSingleton();
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index c62e79b4ef..156bc06a14 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -406,7 +406,6 @@
-
diff --git a/src/Umbraco.Tests/Web/Controllers/BackOfficeControllerUnitTests.cs b/src/Umbraco.Tests/Web/Controllers/BackOfficeControllerUnitTests.cs
index 850870f395..fa9335bc3f 100644
--- a/src/Umbraco.Tests/Web/Controllers/BackOfficeControllerUnitTests.cs
+++ b/src/Umbraco.Tests/Web/Controllers/BackOfficeControllerUnitTests.cs
@@ -22,20 +22,5 @@ namespace Umbraco.Tests.Web.Controllers
};
- [TestCaseSource("TestLegacyJsActionPaths")]
- public void Separates_Legacy_JsActions_By_Block_Or_Url(object[] jsActions)
- {
- var jsBlocks =
- BackOfficeController.GetLegacyActionJsForActions(BackOfficeController.LegacyJsActionType.JsBlock,
- jsActions.Select(n => n.ToString()));
-
- var jsUrls =
- BackOfficeController.GetLegacyActionJsForActions(BackOfficeController.LegacyJsActionType.JsUrl,
- jsActions.Select(n => n.ToString()));
-
- Assert.That(jsBlocks.Count() == 4);
- Assert.That(jsUrls.Count() == 3);
- Assert.That(jsUrls.Last().StartsWith("~/") == false);
- }
}
}
diff --git a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs
index f75371d203..26a7403dac 100644
--- a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs
+++ b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs
@@ -22,7 +22,7 @@ using Umbraco.Web;
using Umbraco.Web.Editors;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.PublishedCache;
-using Umbraco.Web._Legacy.Actions;
+
using Task = System.Threading.Tasks.Task;
using Umbraco.Core.Dictionary;
using Umbraco.Web.PropertyEditors;
@@ -30,6 +30,7 @@ using System;
using Umbraco.Web.WebApi;
using Umbraco.Web.Trees;
using System.Globalization;
+using Umbraco.Web.Actions;
namespace Umbraco.Tests.Web.Controllers
{
@@ -53,10 +54,10 @@ namespace Umbraco.Tests.Web.Controllers
{
new EntityPermission(0, 123, new[]
{
- ActionBrowse.Instance.Letter.ToString(),
- ActionUpdate.Instance.Letter.ToString(),
- ActionPublish.Instance.Letter.ToString(),
- ActionNew.Instance.Letter.ToString()
+ ActionBrowse.ActionLetter.ToString(),
+ ActionUpdate.ActionLetter.ToString(),
+ ActionPublish.ActionLetter.ToString(),
+ ActionNew.ActionLetter.ToString()
}),
})));
diff --git a/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js b/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js
index bd7cf964d0..fbe73c4085 100644
--- a/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js
+++ b/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js
@@ -33,7 +33,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Application");
* Returns the root angular scope
*/
function getRootScope() {
- return angular.element(document.getElementById("umbracoMainPageBody")).scope();
+ return top.$("#umbracoMainPageBody").scope();
}
/**
@@ -46,7 +46,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Application");
* Returns the root angular injector
*/
function getRootInjector() {
- return angular.element(document.getElementById("umbracoMainPageBody")).injector();
+ return top.$("#umbracoMainPageBody").injector();
}
@@ -327,7 +327,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Application");
//add the callback to the jquery data for the modal so we can call it on close to support the legacy way dialogs worked.
dialog.element.data("modalCb", onCloseCallback);
//add the close triggers
- if (angular.isArray(closeTriggers)) {
+ if (top.angular.isArray(closeTriggers)) {
for (var i = 0; i < closeTriggers.length; i++) {
var e = dialog.find(closeTriggers[i]);
if (e.length > 0) {
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
index 3b605453c3..50a8760585 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
@@ -402,21 +402,34 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
throw "Cannot get a descendant node from a section container node without a treeAlias specified";
}
- //if it is a section container, we need to find the tree to be searched
- if (treeNode.isContainer) {
- var foundRoot = null;
- for (var c = 0; c < treeNode.children.length; c++) {
- if (this.getTreeAlias(treeNode.children[c]) === treeAlias) {
- foundRoot = treeNode.children[c];
- break;
+ //the treeNode passed in could be a section container, or it could be a section group
+ //in either case we need to go through the children until we can find the actual tree root with the treeAlias
+ var self = this;
+ function getTreeRoot(tn) {
+ //if it is a section container, we need to find the tree to be searched
+ if (tn.isContainer) {
+ for (var c = 0; c < tn.children.length; c++) {
+ if (tn.children[c].isContainer) {
+ //recurse
+ return getTreeRoot(tn.children[c]);
+ }
+ else if (self.getTreeAlias(tn.children[c]) === treeAlias) {
+ return tn.children[c];
+ }
}
+ return null;
}
- if (!foundRoot) {
- throw "Could not find a tree in the current section with alias " + treeAlias;
+ else {
+ return tn;
}
- treeNode = foundRoot;
}
+ var foundRoot = getTreeRoot(treeNode);
+ if (!foundRoot) {
+ throw "Could not find a tree in the current section with alias " + treeAlias;
+ }
+ treeNode = foundRoot;
+
//check this node
if (treeNode.id === id) {
return treeNode;
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.controller.js
new file mode 100644
index 0000000000..ed1af5af6c
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.controller.js
@@ -0,0 +1,34 @@
+/**
+ * @ngdoc controller
+ * @name Umbraco.Dialogs.LegacyDeleteController
+ * @function
+ *
+ * @description
+ * The controller for deleting content
+ */
+function LegacyDeleteController($scope, legacyResource, treeService, navigationService) {
+
+ $scope.performDelete = function () {
+
+ //mark it for deletion (used in the UI)
+ $scope.currentNode.loading = true;
+
+ legacyResource.deleteItem({
+ nodeId: $scope.currentNode.id,
+ nodeType: $scope.currentNode.nodeType,
+ alias: $scope.currentNode.name
+ }).then(function () {
+ $scope.currentNode.loading = false;
+ //TODO: Need to sync tree, etc...
+ treeService.removeNode($scope.currentNode);
+ navigationService.hideMenu();
+ });
+
+ };
+
+ $scope.cancel = function () {
+ navigationService.hideDialog();
+ };
+}
+
+angular.module("umbraco").controller("Umbraco.Dialogs.LegacyDeleteController", LegacyDeleteController);
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.html
new file mode 100644
index 0000000000..dda8f23b7d
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+ Are you sure you want to delete{{currentNode.name}} ?
+
+
+
+
+
+
+
+
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index 3dc5cd053a..d2867acfc9 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -324,8 +324,6 @@
-
- ASPXCodeBehind
diff --git a/src/Umbraco.Web.UI/Umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.js b/src/Umbraco.Web.UI/Umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.js
deleted file mode 100644
index 30d6611ba9..0000000000
--- a/src/Umbraco.Web.UI/Umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.js
+++ /dev/null
@@ -1,21 +0,0 @@
-function actionDeleteRelationType(relationTypeId, relationTypeName) {
-
- if (confirm('Are you sure you want to delete "' + relationTypeName + '"?')) {
- $.ajax({
- type: "POST",
- url: "developer/RelationTypes/RelationTypesWebService.asmx/DeleteRelationType",
- data: "{ 'relationTypeId' : '" + relationTypeId + "' }",
- contentType: "application/json; charset=utf-8",
- dataType: "json",
- success: function (data) {
- UmbClientMgr.mainTree().refreshTree('relationTypes');
- UmbClientMgr.appActions().openDashboard('developer');
- },
- error: function (data) { }
- });
-
- }
-
-}
-
-
diff --git a/src/Umbraco.Web.UI/Umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.js b/src/Umbraco.Web.UI/Umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.js
deleted file mode 100644
index 322e4b9ace..0000000000
--- a/src/Umbraco.Web.UI/Umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.js
+++ /dev/null
@@ -1,3 +0,0 @@
-function actionNewRelationType() {
- UmbClientMgr.openModalWindow('developer/RelationTypes/NewRelationType.aspx', 'Create New RelationType', true, 400, 300, 0, 0);
-}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Actions/ActionAssignDomain.cs b/src/Umbraco.Web/Actions/ActionAssignDomain.cs
new file mode 100644
index 0000000000..7dc3668e5d
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionAssignDomain.cs
@@ -0,0 +1,21 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when a domain is being assigned to a document
+ ///
+ public class ActionAssignDomain : IAction
+ {
+ public const char ActionLetter = 'I';
+
+ public char Letter => ActionLetter;
+ public string Alias => "assignDomain";
+ public string Category => Constants.Conventions.PermissionCategories.AdministrationCategory;
+ public string Icon => "home";
+ public bool ShowInNotifier => false;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionBrowse.cs b/src/Umbraco.Web/Actions/ActionBrowse.cs
new file mode 100644
index 0000000000..64882c142a
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionBrowse.cs
@@ -0,0 +1,27 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is used as a security constraint that grants a user the ability to view nodes in a tree
+ /// that has permissions applied to it.
+ ///
+ ///
+ /// This action should not be invoked. It is used as the minimum required permission to view nodes in the content tree. By
+ /// granting a user this permission, the user is able to see the node in the tree but not edit the document. This may be used by other trees
+ /// that support permissions in the future.
+ ///
+ public class ActionBrowse : IAction
+ {
+ public const char ActionLetter = 'F';
+
+ public char Letter => ActionLetter;
+ public bool ShowInNotifier => false;
+ public bool CanBePermissionAssigned => true;
+ public string Icon => "";
+ public string Alias => "browse";
+ public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionChangeDocType.cs b/src/Umbraco.Web/Actions/ActionChangeDocType.cs
new file mode 100644
index 0000000000..73772699d0
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionChangeDocType.cs
@@ -0,0 +1,20 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+using Umbraco.Web.UI.Pages;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when the document type of a piece of content is changed
+ ///
+ public class ActionChangeDocType : IAction
+ {
+ public char Letter => '7';
+ public string Alias => "changeDocType";
+ public string Category => Constants.Conventions.PermissionCategories.AdministrationCategory;
+ public string Icon => "axis-rotation-2";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs b/src/Umbraco.Web/Actions/ActionCollection.cs
similarity index 57%
rename from src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs
rename to src/Umbraco.Web/Actions/ActionCollection.cs
index 849fb3b619..64cf950c60 100644
--- a/src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs
+++ b/src/Umbraco.Web/Actions/ActionCollection.cs
@@ -3,8 +3,10 @@ using System.Globalization;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Composing;
+using Umbraco.Core.Models.Membership;
-namespace Umbraco.Web._Legacy.Actions
+
+namespace Umbraco.Web.Actions
{
public class ActionCollection : BuilderCollectionBase
{
@@ -15,7 +17,7 @@ namespace Umbraco.Web._Legacy.Actions
internal T GetAction()
where T : IAction
{
- return this.OfType().SingleOrDefault();
+ return this.OfType().FirstOrDefault();
}
internal IEnumerable GetByLetters(IEnumerable letters)
@@ -25,5 +27,15 @@ namespace Umbraco.Web._Legacy.Actions
.WhereNotNull()
.ToArray();
}
+
+ internal IReadOnlyList FromEntityPermission(EntityPermission entityPermission)
+ {
+ return entityPermission.AssignedPermissions
+ .Where(x => x.Length == 1)
+ .Select(x => x.ToCharArray()[0])
+ .SelectMany(c => this.Where(x => x.Letter == c))
+ .Where(action => action != null)
+ .ToList();
+ }
}
}
diff --git a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs
new file mode 100644
index 0000000000..6002c8d2b0
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using LightInject;
+using Umbraco.Core.Composing;
+
+
+namespace Umbraco.Web.Actions
+{
+ internal class ActionCollectionBuilder : LazyCollectionBuilderBase
+ {
+ public ActionCollectionBuilder(IServiceContainer container)
+ : base(container)
+ { }
+
+ protected override ActionCollectionBuilder This => this;
+
+ protected override IEnumerable CreateItems(params object[] args)
+ {
+ var items = base.CreateItems(args).ToList();
+ //validate the items, no actions should exist that do not either expose notifications or permissions
+ var invalid = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList();
+ if (invalid.Count > 0)
+ {
+ throw new InvalidOperationException($"Invalid actions '{string.Join(", ", invalid.Select(x => x.Alias))}'. All {typeof(IAction)} implementations must be true for either {nameof(IAction.CanBePermissionAssigned)} or {nameof(IAction.ShowInNotifier)}");
+ }
+ return items;
+ }
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionCopy.cs b/src/Umbraco.Web/Actions/ActionCopy.cs
new file mode 100644
index 0000000000..3e4b2ddc31
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionCopy.cs
@@ -0,0 +1,20 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+using Umbraco.Web.UI.Pages;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when copying a document, media, member
+ ///
+ public class ActionCopy : IAction
+ {
+ public char Letter => 'O';
+ public string Alias => "copy";
+ public string Category => Constants.Conventions.PermissionCategories.StructureCategory;
+ public string Icon => "documents";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionCreateBlueprintFromContent.cs b/src/Umbraco.Web/Actions/ActionCreateBlueprintFromContent.cs
new file mode 100644
index 0000000000..0a46393a81
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionCreateBlueprintFromContent.cs
@@ -0,0 +1,16 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+
+
+namespace Umbraco.Web.Actions
+{
+ public class ActionCreateBlueprintFromContent : IAction
+ {
+ public char Letter => 'ï';
+ public bool ShowInNotifier => false;
+ public bool CanBePermissionAssigned => true;
+ public string Icon => "blueprint";
+ public string Alias => "createblueprint";
+ public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionDelete.cs b/src/Umbraco.Web/Actions/ActionDelete.cs
new file mode 100644
index 0000000000..0cf2e60c5a
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionDelete.cs
@@ -0,0 +1,23 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+using Umbraco.Web.UI.Pages;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when a document, media, member is deleted
+ ///
+ public class ActionDelete : IAction
+ {
+ public const string ActionAlias = "delete";
+ public const char ActionLetter = 'D';
+
+ public char Letter => ActionLetter;
+ public string Alias => ActionAlias;
+ public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
+ public string Icon => "delete";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionMove.cs b/src/Umbraco.Web/Actions/ActionMove.cs
new file mode 100644
index 0000000000..7ae8474965
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionMove.cs
@@ -0,0 +1,22 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+using Umbraco.Web.UI.Pages;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked upon creation of a document, media, member
+ ///
+ public class ActionMove : IAction
+ {
+ public const char ActionLetter = 'M';
+
+ public char Letter => ActionLetter;
+ public string Alias => "move";
+ public string Category => Constants.Conventions.PermissionCategories.StructureCategory;
+ public string Icon => "enter";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionNew.cs b/src/Umbraco.Web/Actions/ActionNew.cs
new file mode 100644
index 0000000000..c07580b42a
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionNew.cs
@@ -0,0 +1,23 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+using Umbraco.Web.UI.Pages;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked upon creation of a document
+ ///
+ public class ActionNew : IAction
+ {
+ public const string ActionAlias = "create";
+ public const char ActionLetter = 'C';
+
+ public char Letter => ActionLetter;
+ public string Alias => ActionAlias;
+ public string Icon => "add";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionProtect.cs b/src/Umbraco.Web/Actions/ActionProtect.cs
new file mode 100644
index 0000000000..0e5f9f8433
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionProtect.cs
@@ -0,0 +1,20 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+using Umbraco.Web.UI.Pages;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when a document is protected or unprotected
+ ///
+ public class ActionProtect : IAction
+ {
+ public char Letter => 'P';
+ public string Alias => "protect";
+ public string Category => Constants.Conventions.PermissionCategories.AdministrationCategory;
+ public string Icon => "lock";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionPublish.cs b/src/Umbraco.Web/Actions/ActionPublish.cs
new file mode 100644
index 0000000000..5c9ce08c35
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionPublish.cs
@@ -0,0 +1,21 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when a document is being published
+ ///
+ public class ActionPublish : IAction
+ {
+ public const char ActionLetter = 'U';
+
+ public char Letter => ActionLetter;
+ public string Alias => "publish";
+ public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
+ public string Icon => string.Empty;
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionRestore.cs b/src/Umbraco.Web/Actions/ActionRestore.cs
new file mode 100644
index 0000000000..aa309131f2
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionRestore.cs
@@ -0,0 +1,20 @@
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when the content/media item is to be restored from the recycle bin
+ ///
+ public class ActionRestore : IAction
+ {
+ public const string ActionAlias = "restore";
+
+ public char Letter => 'V';
+ public string Alias => ActionAlias;
+ public string Category => null;
+ public string Icon => "undo";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => false;
+
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionRights.cs b/src/Umbraco.Web/Actions/ActionRights.cs
new file mode 100644
index 0000000000..0d9ace918e
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionRights.cs
@@ -0,0 +1,20 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+using Umbraco.Web.UI.Pages;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when rights are changed on a document
+ ///
+ public class ActionRights : IAction
+ {
+ public char Letter => 'R';
+ public string Alias => "rights";
+ public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
+ public string Icon => "vcard";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionRollback.cs b/src/Umbraco.Web/Actions/ActionRollback.cs
new file mode 100644
index 0000000000..96ce1e7767
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionRollback.cs
@@ -0,0 +1,22 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+using Umbraco.Web.UI.Pages;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when copying a document is being rolled back
+ ///
+ public class ActionRollback : IAction
+ {
+ public const char ActionLetter = 'K';
+
+ public char Letter => ActionLetter;
+ public string Alias => "rollback";
+ public string Category => Constants.Conventions.PermissionCategories.AdministrationCategory;
+ public string Icon => "undo";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionSort.cs b/src/Umbraco.Web/Actions/ActionSort.cs
new file mode 100644
index 0000000000..8b4e01823e
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionSort.cs
@@ -0,0 +1,19 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when children to a document, media, member is being sorted
+ ///
+ public class ActionSort : IAction
+ {
+ public char Letter => 'S';
+ public string Alias => "sort";
+ public string Category => Constants.Conventions.PermissionCategories.StructureCategory;
+ public string Icon => "navigation-vertical";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionToPublish.cs b/src/Umbraco.Web/Actions/ActionToPublish.cs
new file mode 100644
index 0000000000..518c82ab87
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionToPublish.cs
@@ -0,0 +1,22 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+using Umbraco.Web.UI.Pages;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when children to a document is being sent to published (by an editor without publishrights)
+ ///
+ public class ActionToPublish : IAction
+ {
+ public const char ActionLetter = 'H';
+
+ public char Letter => ActionLetter;
+ public string Alias => "sendtopublish";
+ public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
+ public string Icon => "outbox";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/ActionUnpublish.cs b/src/Umbraco.Web/Actions/ActionUnpublish.cs
new file mode 100644
index 0000000000..8ece4c008e
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionUnpublish.cs
@@ -0,0 +1,21 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+
+
+namespace Umbraco.Web.Actions
+{
+
+ ///
+ /// This action is invoked when a document is being unpublished
+ ///
+ public class ActionUnpublish : IAction
+ {
+ public char Letter => 'Z';
+ public string Alias => "unpublish";
+ public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
+ public string Icon => "circle-dotted";
+ public bool ShowInNotifier => false;
+ public bool CanBePermissionAssigned => true;
+ }
+
+}
diff --git a/src/Umbraco.Web/Actions/ActionUpdate.cs b/src/Umbraco.Web/Actions/ActionUpdate.cs
new file mode 100644
index 0000000000..a2fba0fd89
--- /dev/null
+++ b/src/Umbraco.Web/Actions/ActionUpdate.cs
@@ -0,0 +1,22 @@
+using Umbraco.Core;
+using Umbraco.Core.CodeAnnotations;
+using Umbraco.Web.UI.Pages;
+
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// This action is invoked when copying a document or media
+ ///
+ public class ActionUpdate : IAction
+ {
+ public const char ActionLetter = 'A';
+
+ public char Letter => ActionLetter;
+ public string Alias => "update";
+ public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
+ public string Icon => "save";
+ public bool ShowInNotifier => true;
+ public bool CanBePermissionAssigned => true;
+ }
+}
diff --git a/src/Umbraco.Web/Actions/IAction.cs b/src/Umbraco.Web/Actions/IAction.cs
new file mode 100644
index 0000000000..986ed9b509
--- /dev/null
+++ b/src/Umbraco.Web/Actions/IAction.cs
@@ -0,0 +1,46 @@
+using Umbraco.Core.Composing;
+
+namespace Umbraco.Web.Actions
+{
+ ///
+ /// Defines a back office action that can be permission assigned or subscribed to for notifications
+ ///
+ ///
+ /// If an IAction returns false for both ShowInNotifier and CanBePermissionAssigned then the IAction should not exist
+ ///
+ public interface IAction : IDiscoverable
+ {
+ ///
+ /// The letter used to assign a permission (must be unique)
+ ///
+ char Letter { get; }
+
+ ///
+ /// Whether to allow subscribing to notifications for this action
+ ///
+ bool ShowInNotifier { get; }
+
+ ///
+ /// Whether to allow assigning permissions based on this action
+ ///
+ bool CanBePermissionAssigned { get; }
+
+ ///
+ /// The icon to display for this action
+ ///
+ string Icon { get; }
+
+ ///
+ /// The alias for this action (must be unique)
+ ///
+ string Alias { get; }
+
+ ///
+ /// The category used for this action
+ ///
+ ///
+ /// Used in the UI when assigning permissions
+ ///
+ string Category { get; }
+ }
+}
diff --git a/src/Umbraco.Web/Components/NotificationsComponent.cs b/src/Umbraco.Web/Components/NotificationsComponent.cs
index 27fc604d29..79f5ee9f6d 100644
--- a/src/Umbraco.Web/Components/NotificationsComponent.cs
+++ b/src/Umbraco.Web/Components/NotificationsComponent.cs
@@ -5,23 +5,24 @@ using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
-using Umbraco.Web._Legacy.Actions;
+using Umbraco.Web.Actions;
+
namespace Umbraco.Web.Components
{
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public sealed class NotificationsComponent : UmbracoComponentBase, IUmbracoCoreComponent
{
- public void Initialize(INotificationService notificationService)
+ public void Initialize(INotificationService notificationService, ActionCollection actions)
{
ContentService.SentToPublish += (sender, args) =>
- notificationService.SendNotification(args.Entity, ActionToPublish.Instance);
+ notificationService.SendNotification(args.Entity, actions.GetAction());
//Send notifications for the published action
ContentService.Published += (sender, args) =>
{
foreach (var content in args.PublishedEntities)
- notificationService.SendNotification(content, ActionPublish.Instance);
+ notificationService.SendNotification(content, actions.GetAction());
};
//Send notifications for the update and created actions
@@ -45,22 +46,22 @@ namespace Umbraco.Web.Components
updatedEntities.Add(entity);
}
}
- notificationService.SendNotification(newEntities, ActionNew.Instance);
- notificationService.SendNotification(updatedEntities, ActionUpdate.Instance);
+ notificationService.SendNotification(newEntities, actions.GetAction());
+ notificationService.SendNotification(updatedEntities, actions.GetAction());
};
//Send notifications for the delete action
ContentService.Deleted += (sender, args) =>
{
foreach (var content in args.DeletedEntities)
- notificationService.SendNotification(content, ActionDelete.Instance);
+ notificationService.SendNotification(content, actions.GetAction());
};
//Send notifications for the unpublish action
ContentService.Unpublished += (sender, args) =>
{
foreach (var content in args.PublishedEntities)
- notificationService.SendNotification(content, ActionUnpublish.Instance);
+ notificationService.SendNotification(content, actions.GetAction());
};
}
}
diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs
index 3e3f6c75a6..839254f03c 100644
--- a/src/Umbraco.Web/Composing/Current.cs
+++ b/src/Umbraco.Web/Composing/Current.cs
@@ -19,6 +19,7 @@ using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Core.Sync;
using Umbraco.Core._Legacy.PackageActions;
+using Umbraco.Web.Actions;
using Umbraco.Web.Cache;
using Umbraco.Web.Editors;
using Umbraco.Web.HealthCheck;
@@ -27,7 +28,7 @@ using Umbraco.Web.Mvc;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.WebApi;
-using Umbraco.Web._Legacy.Actions;
+
using CoreCurrent = Umbraco.Core.Composing.Current;
namespace Umbraco.Web.Composing
diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs
index f33c8e98a8..38b0be3103 100644
--- a/src/Umbraco.Web/CompositionExtensions.cs
+++ b/src/Umbraco.Web/CompositionExtensions.cs
@@ -3,13 +3,13 @@ using LightInject;
using Umbraco.Core.Composing;
using Current = Umbraco.Web.Composing.Current;
using Umbraco.Core.Macros;
+using Umbraco.Web.Actions;
using Umbraco.Web.Editors;
using Umbraco.Web.HealthCheck;
using Umbraco.Web.Media;
using Umbraco.Web.Mvc;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
-using Umbraco.Web._Legacy.Actions;
using Umbraco.Web.ContentApps;
// the namespace here is intentional - although defined in Umbraco.Web assembly,
diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs
index 15554b7f50..7d0cc26d15 100644
--- a/src/Umbraco.Web/Editors/BackOfficeController.cs
+++ b/src/Umbraco.Web/Editors/BackOfficeController.cs
@@ -3,18 +3,15 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
-using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
-using LightInject;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
@@ -22,18 +19,13 @@ using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Core.Models.Identity;
-using Umbraco.Core.Models.Membership;
-using Umbraco.Core.Security;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
-
-using Umbraco.Web.Trees;
using Umbraco.Web.UI.JavaScript;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web.Features;
using Umbraco.Web.Security;
-using Action = Umbraco.Web._Legacy.Actions.Action;
using Constants = Umbraco.Core.Constants;
using JArray = Newtonsoft.Json.Linq.JArray;
@@ -197,11 +189,8 @@ namespace Umbraco.Web.Editors
{
var initJs = new JsInitialization(_manifestParser);
var initCss = new CssInitialization(_manifestParser);
-
- //get the legacy ActionJs file references to append as well
- var legacyActionJsRef = GetLegacyActionJs(LegacyJsActionType.JsUrl);
-
- var files = initJs.OptimizeBackOfficeScriptFiles(HttpContext, JsInitialization.GetDefaultInitialization(), legacyActionJsRef);
+
+ var files = initJs.OptimizeBackOfficeScriptFiles(HttpContext, JsInitialization.GetDefaultInitialization());
var result = JsInitialization.GetJavascriptInitialization(HttpContext, files, "umbraco");
result += initCss.GetStylesheetInitialization(HttpContext);
@@ -519,50 +508,7 @@ namespace Umbraco.Web.Editors
}
return true;
}
-
- internal static IEnumerable GetLegacyActionJsForActions(LegacyJsActionType type, IEnumerable values)
- {
- var blockList = new List();
- var urlList = new List();
- foreach (var jsFile in values)
- {
- var isJsPath = jsFile.DetectIsJavaScriptPath();
- if (isJsPath.Success)
-
- {
- urlList.Add(isJsPath.Result);
- }
- else
- {
- blockList.Add(isJsPath.Result);
- }
- }
-
- switch (type)
- {
- case LegacyJsActionType.JsBlock:
- return blockList;
- case LegacyJsActionType.JsUrl:
- return urlList;
- }
-
- return blockList;
- }
-
- ///
- /// Renders out all JavaScript references that have been declared in IActions
- ///
- private static IEnumerable GetLegacyActionJs(LegacyJsActionType type)
- {
- return GetLegacyActionJsForActions(type, Action.GetJavaScriptFileReferences());
- }
-
- internal enum LegacyJsActionType
- {
- JsBlock,
- JsUrl
- }
-
+
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs
index 9681a79ed1..53e2593fef 100644
--- a/src/Umbraco.Web/Editors/ContentController.cs
+++ b/src/Umbraco.Web/Editors/ContentController.cs
@@ -30,10 +30,11 @@ using Umbraco.Core.Models.Validation;
using Umbraco.Web.Composing;
using Umbraco.Web.Models;
using Umbraco.Web.WebServices;
-using Umbraco.Web._Legacy.Actions;
+
using Constants = Umbraco.Core.Constants;
using Language = Umbraco.Web.Models.ContentEditing.Language;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Web.Actions;
using Umbraco.Web.ContentApps;
using Umbraco.Web.Editors.Binders;
using Umbraco.Web.Editors.Filters;
@@ -931,14 +932,14 @@ namespace Umbraco.Web.Editors
var errMsg = Services.TextService.Localize(localizationKey, new[] { _allLangs.Value[culture].CultureName });
ModelState.AddModelError(key, errMsg);
}
-
+
///
/// Publishes a document with a given ID
///
///
///
///
- /// The CanAccessContentAuthorize attribute will deny access to this method if the current user
+ /// The EnsureUserPermissionForContent attribute will deny access to this method if the current user
/// does not have Publish access to this node.
///
///
@@ -1076,7 +1077,7 @@ namespace Umbraco.Web.Editors
if (sorted.ParentId > 0)
{
- Services.NotificationService.SendNotification(contentService.GetById(sorted.ParentId), ActionSort.Instance, UmbracoContext, Services.TextService, GlobalSettings);
+ Services.NotificationService.SendNotification(contentService.GetById(sorted.ParentId), Current.Actions.GetAction(), UmbracoContext, Services.TextService, GlobalSettings);
}
return Request.CreateResponse(HttpStatusCode.OK);
@@ -1223,7 +1224,7 @@ namespace Umbraco.Web.Editors
var permission = Services.UserService.GetPermissions(Security.CurrentUser, node.Path);
- if (permission.AssignedPermissions.Contains(ActionAssignDomain.Instance.Letter.ToString(), StringComparer.Ordinal) == false)
+ if (permission.AssignedPermissions.Contains(ActionAssignDomain.ActionLetter.ToString(), StringComparer.Ordinal) == false)
{
var response = Request.CreateResponse(HttpStatusCode.BadRequest);
response.Content = new StringContent("You do not have permission to assign domains on that node.");
@@ -1760,6 +1761,7 @@ namespace Umbraco.Web.Editors
: content.Variants.FirstOrDefault(x => x.Language.IsoCode == culture);
}
+ [EnsureUserPermissionForContent("contentId", ActionRollback.ActionLetter)]
[HttpPost]
public HttpResponseMessage PostRollbackContent(int contentId, int versionId, string culture = "*")
{
diff --git a/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs b/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs
index ed6e15ed09..2698986bcd 100644
--- a/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs
+++ b/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs
@@ -9,11 +9,12 @@ using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
+using Umbraco.Web.Actions;
using Umbraco.Web.Composing;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Security;
using Umbraco.Web.WebApi;
-using Umbraco.Web._Legacy.Actions;
+
namespace Umbraco.Web.Editors.Filters
{
@@ -94,24 +95,24 @@ namespace Umbraco.Web.Editors.Filters
switch (contentItem.Action)
{
case ContentSaveAction.Save:
- permissionToCheck.Add(ActionUpdate.Instance.Letter);
+ permissionToCheck.Add(ActionUpdate.ActionLetter);
contentToCheck = contentItem.PersistedContent;
contentIdToCheck = contentToCheck.Id;
break;
case ContentSaveAction.Publish:
- permissionToCheck.Add(ActionPublish.Instance.Letter);
+ permissionToCheck.Add(ActionPublish.ActionLetter);
contentToCheck = contentItem.PersistedContent;
contentIdToCheck = contentToCheck.Id;
break;
case ContentSaveAction.SendPublish:
- permissionToCheck.Add(ActionToPublish.Instance.Letter);
+ permissionToCheck.Add(ActionToPublish.ActionLetter);
contentToCheck = contentItem.PersistedContent;
contentIdToCheck = contentToCheck.Id;
break;
case ContentSaveAction.SaveNew:
//Save new requires ActionNew
- permissionToCheck.Add(ActionNew.Instance.Letter);
+ permissionToCheck.Add(ActionNew.ActionLetter);
if (contentItem.ParentId != Constants.System.Root)
{
@@ -126,8 +127,8 @@ namespace Umbraco.Web.Editors.Filters
case ContentSaveAction.SendPublishNew:
//Send new requires both ActionToPublish AND ActionNew
- permissionToCheck.Add(ActionNew.Instance.Letter);
- permissionToCheck.Add(ActionToPublish.Instance.Letter);
+ permissionToCheck.Add(ActionNew.ActionLetter);
+ permissionToCheck.Add(ActionToPublish.ActionLetter);
if (contentItem.ParentId != Constants.System.Root)
{
contentToCheck = _contentService.GetById(contentItem.ParentId);
@@ -142,8 +143,8 @@ namespace Umbraco.Web.Editors.Filters
//Publish new requires both ActionNew AND ActionPublish
//TODO: Shoudn't publish also require ActionUpdate since it will definitely perform an update to publish but maybe that's just implied
- permissionToCheck.Add(ActionNew.Instance.Letter);
- permissionToCheck.Add(ActionPublish.Instance.Letter);
+ permissionToCheck.Add(ActionNew.ActionLetter);
+ permissionToCheck.Add(ActionPublish.ActionLetter);
if (contentItem.ParentId != Constants.System.Root)
{
diff --git a/src/Umbraco.Web/Models/Mapping/UserGroupDefaultPermissionsResolver.cs b/src/Umbraco.Web/Models/Mapping/UserGroupDefaultPermissionsResolver.cs
index 89144084e2..b13b5cda10 100644
--- a/src/Umbraco.Web/Models/Mapping/UserGroupDefaultPermissionsResolver.cs
+++ b/src/Umbraco.Web/Models/Mapping/UserGroupDefaultPermissionsResolver.cs
@@ -6,8 +6,9 @@ using Umbraco.Core;
using Umbraco.Core.CodeAnnotations;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
+using Umbraco.Web.Actions;
using Umbraco.Web.Models.ContentEditing;
-using Umbraco.Web._Legacy.Actions;
+
namespace Umbraco.Web.Models.Mapping
{
@@ -37,13 +38,11 @@ namespace Umbraco.Web.Models.Mapping
private Permission GetPermission(IAction action, IUserGroup source)
{
var result = new Permission();
- var attribute = action.GetType().GetCustomAttribute(false);
- result.Category = attribute == null
+
+ result.Category = action.Category.IsNullOrWhiteSpace()
? _textService.Localize($"actionCategories/{Constants.Conventions.PermissionCategories.OtherCategory}")
- : _textService.Localize($"actionCategories/{attribute.Category}");
- result.Name = attribute == null || attribute.Name.IsNullOrWhiteSpace()
- ? _textService.Localize($"actions/{action.Alias}")
- : attribute.Name;
+ : _textService.Localize($"actionCategories/{action.Category}");
+ result.Name = _textService.Localize($"actions/{action.Alias}");
result.Description = _textService.Localize($"actionDescriptions/{action.Alias}");
result.Icon = action.Icon;
result.Checked = source.Permissions != null && source.Permissions.Contains(action.Letter.ToString(CultureInfo.InvariantCulture));
diff --git a/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs
index 213a1a5e3a..8261dda0d4 100644
--- a/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs
+++ b/src/Umbraco.Web/Models/Mapping/UserMapperProfile.cs
@@ -11,7 +11,8 @@ using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
-using Umbraco.Web._Legacy.Actions;
+using Umbraco.Web.Actions;
+
namespace Umbraco.Web.Models.Mapping
{
diff --git a/src/Umbraco.Web/Models/Trees/ActionMenuItem.cs b/src/Umbraco.Web/Models/Trees/ActionMenuItem.cs
index b2fb479771..9354417155 100644
--- a/src/Umbraco.Web/Models/Trees/ActionMenuItem.cs
+++ b/src/Umbraco.Web/Models/Trees/ActionMenuItem.cs
@@ -1,41 +1,55 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using Umbraco.Core;
+using Umbraco.Core.Services;
namespace Umbraco.Web.Models.Trees
{
- ///
- /// A menu item that represents some JS that needs to execute when the menu item is clicked.
- ///
- ///
- /// These types of menu items are rare but they do exist. Things like refresh node simply execute
- /// JS and don't launch a dialog.
- ///
- /// Each action menu item describes what angular service that it's method exists in and what the method name is.
- ///
- /// An action menu item must describe the angular service name for which it's method exists. It may also define what the
- /// method name is that will be called in this service but if one is not specified then we will assume the method name is the
- /// same as the Type name of the current action menu class.
- ///
+ ///
+ ///
+ /// A menu item that represents some JS that needs to execute when the menu item is clicked.
+ ///
+ ///
+ /// These types of menu items are rare but they do exist. Things like refresh node simply execute
+ /// JS and don't launch a dialog.
+ /// Each action menu item describes what angular service that it's method exists in and what the method name is.
+ /// An action menu item must describe the angular service name for which it's method exists. It may also define what the
+ /// method name is that will be called in this service but if one is not specified then we will assume the method name is the
+ /// same as the Type name of the current action menu class.
+ ///
public abstract class ActionMenuItem : MenuItem
{
- protected ActionMenuItem()
- : base()
- {
- var attribute = GetType().GetCustomAttribute(false);
- if (attribute == null)
- {
- throw new InvalidOperationException("All " + typeof (ActionMenuItem).FullName + " instances must be attributed with " + typeof (ActionMenuItemAttribute).FullName);
- }
+ ///
+ /// The angular service name containing the
+ ///
+ public abstract string AngularServiceName { get; }
+ ///
+ /// The angular service method name to call for this menu item
+ ///
+ public virtual string AngularServiceMethodName { get; } = null;
+
+ protected ActionMenuItem(string alias, string name) : base(alias, name)
+ {
+ Initialize();
+ }
+
+ protected ActionMenuItem(string alias, ILocalizedTextService textService) : base(alias, textService)
+ {
+ Initialize();
+ }
+
+ private void Initialize()
+ {
//add the current type to the metadata
- if (attribute.MethodName.IsNullOrWhiteSpace())
+ if (AngularServiceMethodName.IsNullOrWhiteSpace())
{
//if no method name is supplied we will assume that the menu action is the type name of the current menu class
- AdditionalData.Add("jsAction", string.Format("{0}.{1}", attribute.ServiceName, this.GetType().Name));
+ ExecuteJsMethod($"{AngularServiceName}.{this.GetType().Name}");
}
else
{
- AdditionalData.Add("jsAction", string.Format("{0}.{1}", attribute.ServiceName, attribute.MethodName));
+ ExecuteJsMethod($"{AngularServiceName}.{AngularServiceMethodName}");
}
}
}
diff --git a/src/Umbraco.Web/Models/Trees/ActionMenuItemAttribute.cs b/src/Umbraco.Web/Models/Trees/ActionMenuItemAttribute.cs
deleted file mode 100644
index 64558b8727..0000000000
--- a/src/Umbraco.Web/Models/Trees/ActionMenuItemAttribute.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using System;
-using Umbraco.Core.Exceptions;
-
-namespace Umbraco.Web.Models.Trees
-{
- ///
- /// The attribute to assign to any ActionMenuItem objects.
- ///
- [AttributeUsage(AttributeTargets.Class)]
- public sealed class ActionMenuItemAttribute : Attribute
- {
- ///
- /// This constructor defines both the angular service and method name to use
- ///
- ///
- ///
- public ActionMenuItemAttribute(string serviceName, string methodName)
- {
- if (string.IsNullOrWhiteSpace(serviceName)) throw new ArgumentNullOrEmptyException(nameof(serviceName));
- if (string.IsNullOrWhiteSpace(methodName)) throw new ArgumentNullOrEmptyException(nameof(methodName));
- MethodName = methodName;
- ServiceName = serviceName;
- }
-
- ///
- /// This constructor will assume that the method name equals the type name of the action menu class
- ///
- ///
- public ActionMenuItemAttribute(string serviceName)
- {
- if (string.IsNullOrWhiteSpace(serviceName)) throw new ArgumentNullOrEmptyException(nameof(serviceName));
- MethodName = "";
- ServiceName = serviceName;
- }
-
- public string MethodName { get; }
- public string ServiceName { get; }
- }
-}
diff --git a/src/Umbraco.Web/Models/Trees/CreateChildEntity.cs b/src/Umbraco.Web/Models/Trees/CreateChildEntity.cs
index ca89851beb..022056c35d 100644
--- a/src/Umbraco.Web/Models/Trees/CreateChildEntity.cs
+++ b/src/Umbraco.Web/Models/Trees/CreateChildEntity.cs
@@ -1,10 +1,27 @@
-namespace Umbraco.Web.Models.Trees
+using Umbraco.Core.Services;
+using Umbraco.Web.Actions;
+
+namespace Umbraco.Web.Models.Trees
{
///
/// Represents the refresh node menu item
///
- [ActionMenuItem("umbracoMenuActions")]
public sealed class CreateChildEntity : ActionMenuItem
{
+ public override string AngularServiceName => "umbracoMenuActions";
+
+ public CreateChildEntity(string name, bool seperatorBefore = false)
+ : base(ActionNew.ActionAlias, name)
+ {
+ Icon = "add"; Name = name;
+ SeperatorBefore = seperatorBefore;
+ }
+
+ public CreateChildEntity(ILocalizedTextService textService, bool seperatorBefore = false)
+ : base(ActionNew.ActionAlias, textService)
+ {
+ Icon = "add";
+ SeperatorBefore = seperatorBefore;
+ }
}
}
diff --git a/src/Umbraco.Web/Models/Trees/DisableUser.cs b/src/Umbraco.Web/Models/Trees/DisableUser.cs
deleted file mode 100644
index 3602897ac2..0000000000
--- a/src/Umbraco.Web/Models/Trees/DisableUser.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace Umbraco.Web.Models.Trees
-{
- ///
- /// Represents the disable user menu item
- ///
- [ActionMenuItem("umbracoMenuActions")]
- public sealed class DisableUser : ActionMenuItem
- {
- public DisableUser()
- {
- Alias = "disable";
- Icon = "remove";
- }
- }
-}
diff --git a/src/Umbraco.Web/Models/Trees/ExportMember.cs b/src/Umbraco.Web/Models/Trees/ExportMember.cs
index 66a10da007..558f7c1fa1 100644
--- a/src/Umbraco.Web/Models/Trees/ExportMember.cs
+++ b/src/Umbraco.Web/Models/Trees/ExportMember.cs
@@ -1,9 +1,17 @@
-namespace Umbraco.Web.Models.Trees
+using Umbraco.Core.Services;
+
+namespace Umbraco.Web.Models.Trees
{
///
/// Represents the export member menu item
///
- [ActionMenuItem("umbracoMenuActions")]
public sealed class ExportMember : ActionMenuItem
- { }
+ {
+ public override string AngularServiceName => "umbracoMenuActions";
+
+ public ExportMember(ILocalizedTextService textService) : base("export", textService)
+ {
+ Icon = "download-alt";
+ }
+ }
}
diff --git a/src/Umbraco.Web/Models/Trees/MenuItem.cs b/src/Umbraco.Web/Models/Trees/MenuItem.cs
index 412cd9106d..4170cdb73f 100644
--- a/src/Umbraco.Web/Models/Trees/MenuItem.cs
+++ b/src/Umbraco.Web/Models/Trees/MenuItem.cs
@@ -5,8 +5,9 @@ using System.Collections.Generic;
using Umbraco.Core;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
+using Umbraco.Web.Actions;
using Umbraco.Web.Composing;
-using Umbraco.Web._Legacy.Actions;
+
namespace Umbraco.Web.Models.Trees
{
@@ -30,15 +31,27 @@ namespace Umbraco.Web.Models.Trees
Name = name;
}
- public MenuItem(IAction legacyMenu, string name = "")
+
+ public MenuItem(string alias, ILocalizedTextService textService)
: this()
{
- Name = name.IsNullOrWhiteSpace() ? legacyMenu.Alias : name;
- Alias = legacyMenu.Alias;
+ Alias = alias;
+ Name = textService.Localize($"actions/{Alias}");
+ }
+
+ ///
+ /// Create a menu item based on an definition
+ ///
+ ///
+ ///
+ public MenuItem(IAction action, string name = "")
+ : this()
+ {
+ Name = name.IsNullOrWhiteSpace() ? action.Alias : name;
+ Alias = action.Alias;
SeperatorBefore = false;
- Icon = legacyMenu.Icon;
- Action = legacyMenu;
- OpensDialog = legacyMenu.OpensDialog;
+ Icon = action.Icon;
+ Action = action;
}
#endregion
@@ -73,6 +86,9 @@ namespace Umbraco.Web.Models.Trees
[DataMember(Name = "cssclass")]
public string Icon { get; set; }
+ ///
+ /// Used in the UI to inform the user that the menu item will open a dialog/confirmation
+ ///
[DataMember(Name = "opensDialog")]
public bool OpensDialog { get; set; }
@@ -128,7 +144,7 @@ namespace Umbraco.Web.Models.Trees
/// Adds the required meta data to the menu item so that angular knows to attempt to call the Js method.
///
///
- public void ExecuteLegacyJs(string jsToExecute)
+ public void ExecuteJsMethod(string jsToExecute)
{
SetJsAction(jsToExecute);
}
@@ -206,7 +222,7 @@ namespace Umbraco.Web.Models.Trees
}
}
}
-
+
#endregion
}
diff --git a/src/Umbraco.Web/Models/Trees/MenuItemList.cs b/src/Umbraco.Web/Models/Trees/MenuItemList.cs
index 170042b151..b34f0b4444 100644
--- a/src/Umbraco.Web/Models/Trees/MenuItemList.cs
+++ b/src/Umbraco.Web/Models/Trees/MenuItemList.cs
@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using Umbraco.Core;
+using Umbraco.Core.Services;
+using Umbraco.Web.Actions;
using Umbraco.Web.Composing;
-using Umbraco.Web._Legacy.Actions;
+
namespace Umbraco.Web.Models.Trees
{
@@ -24,7 +26,7 @@ namespace Umbraco.Web.Models.Trees
}
///
- /// Adds a menu item
+ /// Adds a menu item based on a
///
///
/// The text to display for the menu item, will default to the IAction alias if not specified
@@ -32,78 +34,20 @@ namespace Umbraco.Web.Models.Trees
{
var item = new MenuItem(action, name);
- DetectLegacyActionMenu(action.GetType(), item);
-
Add(item);
return item;
}
- ///
- /// Adds a menu item
- ///
- ///
- ///
- ///
- /// The text to display for the menu item, will default to the IAction alias if not specified
- ///
- ///
- public TMenuItem Add(string name, bool hasSeparator = false, IDictionary additionalData = null)
- where TAction : IAction
- where TMenuItem : MenuItem, new()
- {
- var item = CreateMenuItem(name, hasSeparator, additionalData);
- if (item == null) return null;
-
- var customMenuItem = new TMenuItem
- {
- Name = item.Name,
- Alias = item.Alias,
- SeperatorBefore = hasSeparator,
- Icon = item.Icon,
- Action = item.Action
- };
-
- Add(customMenuItem);
-
- return customMenuItem;
- }
-
- ///
- /// Adds a menu item
- ///
- /// The text to display for the menu item, will default to the IAction alias if not specified
- ///
- public MenuItem Add(string name)
- where T : IAction
- {
- return Add(name, false, null);
- }
-
- ///
- /// Adds a menu item with a key value pair which is merged to the AdditionalData bag
- ///
- ///
- ///
- ///
- /// The text to display for the menu item, will default to the IAction alias if not specified
- ///
- public MenuItem Add(string name, string key, string value, bool hasSeparator = false)
- where T : IAction
- {
- return Add(name, hasSeparator, new Dictionary { { key, value } });
- }
-
///
/// Adds a menu item with a dictionary which is merged to the AdditionalData bag
///
///
///
- /// /// The text to display for the menu item, will default to the IAction alias if not specified
- ///
- public MenuItem Add(string name, bool hasSeparator = false, IDictionary additionalData = null)
+ /// The text to display for the menu item, will default to the IAction alias if not specified
+ public MenuItem Add(string name, bool hasSeparator = false)
where T : IAction
{
- var item = CreateMenuItem(name, hasSeparator, additionalData);
+ var item = CreateMenuItem(name, hasSeparator);
if (item != null)
{
Add(item);
@@ -113,69 +57,51 @@ namespace Umbraco.Web.Models.Trees
}
///
- ///
+ /// Adds a menu item with a dictionary which is merged to the AdditionalData bag
///
///
///
- /// The text to display for the menu item, will default to the IAction alias if not specified
- ///
- ///
- internal MenuItem CreateMenuItem(string name, bool hasSeparator = false, IDictionary additionalData = null)
+ /// The used to localize the action name based on it's alias
+ ///
+ public MenuItem Add(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false)
where T : IAction
{
- var item = Current.Actions.GetAction();
+ var item = CreateMenuItem(textService, hasSeparator);
if (item != null)
{
- var menuItem = new MenuItem(item, name)
- {
- SeperatorBefore = hasSeparator
- };
-
- if (additionalData != null)
- {
- foreach (var i in additionalData)
- {
- menuItem.AdditionalData[i.Key] = i.Value;
- }
- }
-
- DetectLegacyActionMenu(typeof(T), menuItem);
-
- //TODO: Once we implement 'real' menu items, not just IActions we can implement this since
- // people may need to pass specific data to their menu items
-
- ////validate the data in the meta data bag
- //item.ValidateRequiredData(AdditionalData);
-
- return menuItem;
+ Add(item);
+ return item;
}
return null;
}
-
- ///
- /// Checks if the IAction type passed in is attributed with LegacyActionMenuItemAttribute and if so
- /// ensures that the correct action metadata is added.
- ///
- ///
- ///
- private void DetectLegacyActionMenu(Type actionType, MenuItem menuItem)
+
+ internal MenuItem CreateMenuItem(string name, bool hasSeparator = false)
+ where T : IAction
{
- //This checks for legacy IActions that have the LegacyActionMenuItemAttribute which is a legacy hack
- // to make old IAction actions work in v7 by mapping to the JS used by the new menu items
- var attribute = actionType.GetCustomAttribute(false);
- if (attribute != null)
+ var item = Current.Actions.GetAction();
+ if (item == null) return null;
+ var menuItem = new MenuItem(item, name)
{
- //add the current type to the metadata
- if (attribute.MethodName.IsNullOrWhiteSpace())
- {
- //if no method name is supplied we will assume that the menu action is the type name of the current menu class
- menuItem.AdditionalData.Add(MenuItem.JsActionKey, string.Format("{0}.{1}", attribute.ServiceName, this.GetType().Name));
- }
- else
- {
- menuItem.AdditionalData.Add(MenuItem.JsActionKey, string.Format("{0}.{1}", attribute.ServiceName, attribute.MethodName));
- }
- }
+ SeperatorBefore = hasSeparator
+ };
+
+ return menuItem;
}
+
+ internal MenuItem CreateMenuItem(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false)
+ where T : IAction
+ {
+ var item = Current.Actions.GetAction();
+ if (item == null) return null;
+
+ var menuItem = new MenuItem(item, textService.Localize($"actions/{item.Alias}"))
+ {
+ SeperatorBefore = hasSeparator,
+ OpensDialog = opensDialog
+ };
+
+ return menuItem;
+ }
+
}
}
diff --git a/src/Umbraco.Web/Models/Trees/RefreshNode.cs b/src/Umbraco.Web/Models/Trees/RefreshNode.cs
index 7f20562962..2641baa34f 100644
--- a/src/Umbraco.Web/Models/Trees/RefreshNode.cs
+++ b/src/Umbraco.Web/Models/Trees/RefreshNode.cs
@@ -1,10 +1,27 @@
-namespace Umbraco.Web.Models.Trees
+using Umbraco.Core.Services;
+
+namespace Umbraco.Web.Models.Trees
{
+ ///
///
/// Represents the refresh node menu item
///
- [ActionMenuItem("umbracoMenuActions")]
public sealed class RefreshNode : ActionMenuItem
{
+ public override string AngularServiceName => "umbracoMenuActions";
+
+ public RefreshNode(string name, bool seperatorBefore = false)
+ : base("refreshNode", name)
+ {
+ Icon = "refresh";
+ SeperatorBefore = seperatorBefore;
+ }
+
+ public RefreshNode(ILocalizedTextService textService, bool seperatorBefore = false)
+ : base("refreshNode", textService)
+ {
+ Icon = "refresh";
+ SeperatorBefore = seperatorBefore;
+ }
}
}
diff --git a/src/Umbraco.Web/NotificationServiceExtensions.cs b/src/Umbraco.Web/NotificationServiceExtensions.cs
index 1fb229a66e..4be7b4f091 100644
--- a/src/Umbraco.Web/NotificationServiceExtensions.cs
+++ b/src/Umbraco.Web/NotificationServiceExtensions.cs
@@ -6,9 +6,10 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Core.Models;
-using Umbraco.Web._Legacy.Actions;
+
using System.Collections.Generic;
using Umbraco.Core.Models.Entities;
+using Umbraco.Web.Actions;
using Umbraco.Web.Composing;
namespace Umbraco.Web
diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs
index 028f1bf728..1af24db636 100644
--- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs
+++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs
@@ -31,6 +31,7 @@ using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Core.Runtime;
using Umbraco.Core.Services;
using Umbraco.Examine;
+using Umbraco.Web.Actions;
using Umbraco.Web.Cache;
using Umbraco.Web.Composing.CompositionRoots;
using Umbraco.Web.ContentApps;
@@ -53,7 +54,7 @@ using Umbraco.Web.Tour;
using Umbraco.Web.Trees;
using Umbraco.Web.UI.JavaScript;
using Umbraco.Web.WebApi;
-using Umbraco.Web._Legacy.Actions;
+
using Current = Umbraco.Web.Composing.Current;
namespace Umbraco.Web.Runtime
@@ -139,7 +140,7 @@ namespace Umbraco.Web.Runtime
Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG!
composition.Container.RegisterCollectionBuilder()
- .SetProducer(() => typeLoader.GetActions());
+ .Add(() => typeLoader.GetTypes());
var surfaceControllerTypes = new SurfaceControllerTypeCollection(typeLoader.GetSurfaceControllers());
composition.Container.RegisterInstance(surfaceControllerTypes);
diff --git a/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs b/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs
index 5b45888dca..364c9c391f 100644
--- a/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs
+++ b/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs
@@ -4,10 +4,11 @@ using Umbraco.Core;
using Umbraco.Core.Services;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
+using Umbraco.Web.Actions;
using Umbraco.Web.Models.Trees;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi.Filters;
-using Umbraco.Web._Legacy.Actions;
+
using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.Trees
@@ -92,9 +93,8 @@ namespace Umbraco.Web.Trees
if (id == Constants.System.Root.ToInvariantString())
{
// root actions
- menu.Items.Add(Services.TextService.Localize($"actions/{ActionNew.Instance.Alias}"));
- menu.Items.Add(Services.TextService.Localize(
- $"actions/{ActionRefresh.Instance.Alias}"), true);
+ menu.Items.Add(Services.TextService, opensDialog: true);
+ menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;
}
var cte = Services.EntityService.Get(int.Parse(id), UmbracoObjectTypes.DocumentType);
@@ -102,15 +102,15 @@ namespace Umbraco.Web.Trees
if (cte != null)
{
var ct = Services.ContentTypeService.Get(cte.Id);
- var createItem = menu.Items.Add(Services.TextService.Localize($"actions/{ActionCreateBlueprintFromContent.Instance.Alias}"));
+ var createItem = menu.Items.Add(Services.TextService, opensDialog: true);
createItem.NavigateToRoute("/settings/contentBlueprints/edit/-1?create=true&doctype=" + ct.Alias);
- menu.Items.Add(Services.TextService.Localize($"actions/{ActionRefresh.Instance.Alias}"), true);
+ menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;
}
- menu.Items.Add(Services.TextService.Localize($"actions/{ActionDelete.Instance.Alias}"));
+ menu.Items.Add(Services.TextService, opensDialog: true);
return menu;
}
diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs
index 4a0589cce4..04c356a4fd 100644
--- a/src/Umbraco.Web/Trees/ContentTreeController.cs
+++ b/src/Umbraco.Web/Trees/ContentTreeController.cs
@@ -8,11 +8,12 @@ using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
+using Umbraco.Web.Actions;
using Umbraco.Web.Composing;
using Umbraco.Web.Models.Trees;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi.Filters;
-using Umbraco.Web._Legacy.Actions;
+
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Search;
using Constants = Umbraco.Core.Constants;
@@ -114,23 +115,21 @@ namespace Umbraco.Web.Trees
// if the user's start node is not the root then the only menu item to display is refresh
if (UserStartNodes.Contains(Constants.System.Root) == false)
{
- menu.Items.Add(
- Services.TextService.Localize(string.Concat("actions/", ActionRefresh.Instance.Alias)),
- true);
+ menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;
}
//set the default to create
- menu.DefaultMenuAlias = ActionNew.Instance.Alias;
+ menu.DefaultMenuAlias = ActionNew.ActionAlias;
// we need to get the default permissions as you can't set permissions on the very root node
var permission = Services.UserService.GetPermissions(Security.CurrentUser, Constants.System.Root).First();
- var nodeActions = global::Umbraco.Web._Legacy.Actions.Action.FromEntityPermission(permission)
+ var nodeActions = Current.Actions.FromEntityPermission(permission)
.Select(x => new MenuItem(x));
//these two are the standard items
- menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias));
- menu.Items.Add(Services.TextService.Localize("actions", ActionSort.Instance.Alias), true);
+ menu.Items.Add(Services.TextService, opensDialog: true);
+ menu.Items.Add(Services.TextService, true);
//filter the standard items
FilterUserAllowedMenuItems(menu, nodeActions);
@@ -143,7 +142,7 @@ namespace Umbraco.Web.Trees
// add default actions for *all* users
// fixme - temp disable RePublish as the page itself (republish.aspx) has been temp disabled
//menu.Items.Add(Services.TextService.Localize("actions", ActionRePublish.Instance.Alias)).ConvertLegacyMenuItem(null, "content", "content");
- menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true);
+ menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;
}
@@ -165,9 +164,7 @@ namespace Umbraco.Web.Trees
if (Security.CurrentUser.HasPathAccess(item, Services.EntityService, RecycleBinId) == false)
{
var menu = new MenuItemCollection();
- menu.Items.Add(
- Services.TextService.Localize(string.Concat("actions/", ActionRefresh.Instance.Alias)),
- true);
+ menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;
}
@@ -182,7 +179,7 @@ namespace Umbraco.Web.Trees
else
{
//set the default to create
- nodeMenu.DefaultMenuAlias = ActionNew.Instance.Alias;
+ nodeMenu.DefaultMenuAlias = ActionNew.ActionAlias;
}
var allowedMenuItems = GetAllowedUserMenuItemsForNode(item);
@@ -228,25 +225,25 @@ namespace Umbraco.Web.Trees
protected MenuItemCollection GetAllNodeMenuItems(IUmbracoEntity item)
{
var menu = new MenuItemCollection();
- AddActionNode(item, menu);
- AddActionNode(item, menu);
-
- AddActionNode(item, menu);
-
- //need to ensure some of these are converted to the legacy system - until we upgrade them all to be angularized.
- AddActionNode(item, menu, true);
- AddActionNode(item, menu);
-
+ AddActionNode(item, menu, opensDialog: true);
+ AddActionNode(item, menu, opensDialog: true);
+ AddActionNode(item, menu, opensDialog: true);
+ AddActionNode(item, menu, true, opensDialog: true);
+ AddActionNode(item, menu, opensDialog: true);
AddActionNode(item, menu, true);
+ AddActionNode(item, menu, opensDialog: true);
+ AddActionNode(item, menu, opensDialog: true);
+ //fixme - conver this editor to angular
+ AddActionNode(item, menu, true, convert: true, opensDialog: true);
- AddActionNode(item, menu, convert: true);
- AddActionNode(item, menu);
- AddActionNode(item, menu, convert: true);
- AddActionNode(item, menu, true, true);
-
- AddActionNode(item, menu, true);
+ menu.Items.Add(new MenuItem("notify", Services.TextService)
+ {
+ Icon = "megaphone",
+ SeperatorBefore = true,
+ OpensDialog = true
+ });
- AddActionNode(item, menu, true);
+ menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;
}
@@ -259,10 +256,10 @@ namespace Umbraco.Web.Trees
protected MenuItemCollection GetNodeMenuItemsForDeletedContent(IUmbracoEntity item)
{
var menu = new MenuItemCollection();
- menu.Items.Add(Services.TextService.Localize("actions", ActionRestore.Instance.Alias));
- menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias));
+ menu.Items.Add(Services.TextService, opensDialog: true);
+ menu.Items.Add(Services.TextService, opensDialog: true);
- menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true);
+ menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;
}
@@ -306,19 +303,14 @@ namespace Umbraco.Web.Trees
entity.Name = "[[" + entity.Id + "]]";
}
- private void AddActionNode(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool convert = false)
+ //fixme: Remove the need for converting to legacy
+ private void AddActionNode(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool convert = false, bool opensDialog = false)
where TAction : IAction
{
+ //fixme: Inject
var menuItem = menu.Items.Add(Services.TextService.Localize("actions", Current.Actions.GetAction().Alias), hasSeparator);
if (convert) menuItem.ConvertLegacyMenuItem(item, "content", "content");
- }
-
- private void AddActionNode(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool convert = false)
- where TItem : MenuItem, new()
- where TAction : IAction
- {
- var menuItem = menu.Items.Add(Services.TextService.Localize("actions", Current.Actions.GetAction().Alias), hasSeparator);
- if (convert) menuItem.ConvertLegacyMenuItem(item, "content", "content");
+ menuItem.OpensDialog = opensDialog;
}
public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null)
diff --git a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs
index 4d4f1be483..646f47068b 100644
--- a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs
+++ b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs
@@ -14,7 +14,9 @@ using Umbraco.Web.Models.Trees;
using Umbraco.Web.WebApi.Filters;
using System.Globalization;
using Umbraco.Core.Models.Entities;
-using Umbraco.Web._Legacy.Actions;
+using Umbraco.Web.Actions;
+using Umbraco.Web.Composing;
+
namespace Umbraco.Web.Trees
{
@@ -347,8 +349,12 @@ namespace Umbraco.Web.Trees
if (RecycleBinId.ToInvariantString() == id)
{
var menu = new MenuItemCollection();
- menu.Items.Add(Services.TextService.Localize("actions/emptyTrashcan"));
- menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true);
+ menu.Items.Add(new MenuItem("emptyRecycleBin", Services.TextService)
+ {
+ Icon = "trash",
+ OpensDialog = true
+ });
+ menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;
}
@@ -381,13 +387,16 @@ namespace Umbraco.Web.Trees
internal IEnumerable