From 9704c124eda16a4c2ffff869007c54b1ec498802 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 24 Oct 2018 15:20:28 +1100 Subject: [PATCH 01/16] Removes all old deprecated drop down editors, we only have one drop down editor now and it doesn't store IDs either in the db or in the cache, it just stores what is selected --- src/Umbraco.Core/Constants-PropertyEditors.cs | 20 --- .../Migrations/Install/DatabaseDataCreator.cs | 2 +- .../Migrations/Upgrade/UmbracoPlan.cs | 2 + .../Upgrade/V_8_0_0/DataTypeMigration.cs | 7 +- .../DropDownPropertyEditorsMigration.cs | 145 ++++++++++++++++++ .../Upgrade/V_8_0_0/DropPreValueTable.cs | 15 ++ .../DropdownListMultipleValueConverter.cs | 33 ---- ...pdownListMultipleWithKeysValueConverter.cs | 34 ---- .../DropdownListValueConverter.cs | 23 --- .../DropdownListWithKeysValueConverter.cs | 27 ---- src/Umbraco.Core/Umbraco.Core.csproj | 6 +- .../MultiValuePropertyEditorTests.cs | 27 +--- .../PropertyEditorValueConverterTests.cs | 41 ++--- .../Entities/MockedContentTypes.cs | 11 +- .../CheckBoxListPropertyEditor.cs | 2 +- .../DropDownFlexiblePropertyEditor.cs | 2 +- .../DropDownMultipleConfigurationEditor.cs | 73 --------- .../DropDownMultiplePropertyEditor.cs | 30 ---- .../DropDownMultipleWithKeysPropertyEditor.cs | 37 ----- .../PropertyEditors/DropDownPropertyEditor.cs | 37 ----- .../DropDownWithKeysPropertyEditor.cs | 36 ----- .../PublishValueValueEditor.cs | 57 ------- .../PublishValuesMultipleValueEditor.cs | 55 +------ .../RadioButtonsPropertyEditor.cs | 21 ++- .../FlexibleDropdownPropertyValueConverter.cs | 4 +- src/Umbraco.Web/Umbraco.Web.csproj | 6 - 26 files changed, 225 insertions(+), 528 deletions(-) create mode 100644 src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs create mode 100644 src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs delete mode 100644 src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleValueConverter.cs delete mode 100644 src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleWithKeysValueConverter.cs delete mode 100644 src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListValueConverter.cs delete mode 100644 src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListWithKeysValueConverter.cs delete mode 100644 src/Umbraco.Web/PropertyEditors/DropDownMultipleConfigurationEditor.cs delete mode 100644 src/Umbraco.Web/PropertyEditors/DropDownMultiplePropertyEditor.cs delete mode 100644 src/Umbraco.Web/PropertyEditors/DropDownMultipleWithKeysPropertyEditor.cs delete mode 100644 src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs delete mode 100644 src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs delete mode 100644 src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs index 126613cdb3..b09987ad90 100644 --- a/src/Umbraco.Core/Constants-PropertyEditors.cs +++ b/src/Umbraco.Core/Constants-PropertyEditors.cs @@ -44,26 +44,6 @@ namespace Umbraco.Core /// public const string DateTime = "Umbraco.DateTime"; - /// - /// DropDown List. - /// - public const string DropDownList = "Umbraco.DropDown"; - - /// - /// DropDown List, Publish Keys. - /// - public const string DropdownlistPublishKeys = "Umbraco.DropdownlistPublishingKeys"; - - /// - /// DropDown List Multiple. - /// - public const string DropDownListMultiple = "Umbraco.DropDownMultiple"; - - /// - /// DropDown List Multiple, Publish Keys. - /// - public const string DropdownlistMultiplePublishKeys = "Umbraco.DropdownlistMultiplePublishKeys"; - /// /// DropDown List. /// diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs index c4ebfb664b..eb7cafcb01 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs @@ -117,7 +117,7 @@ namespace Umbraco.Core.Migrations.Install _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownMultiple, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownMultiple}", SortOrder = 2, UniqueId = new Guid("0b6a45e7-44ba-430d-9da5-4e46060b9e03"), Text = "Dropdown", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = new Guid("5046194e-4237-453c-a547-15db3a07c4e1"), Text = "Date Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = new Guid("bb5f57c9-ce2b-4bb9-b697-4caca783a805"), Text = "Radiobox", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -39, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-39", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); + _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownSingle, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownSingle}", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = new Guid("0225af17-b302-49cb-9176-b9f35cab9c17"), Text = "Approved Color", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -36, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-36", SortOrder = 2, UniqueId = new Guid("e4d66c0f-b935-4200-81f0-025f7256b89a"), Text = "Date Picker with time", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultContentListView}", SortOrder = 2, UniqueId = new Guid("C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index 5b0838573e..9ad7ccb48e 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -138,6 +138,8 @@ namespace Umbraco.Core.Migrations.Upgrade Chain("{6A2C7C1B-A9DB-4EA9-B6AB-78E7D5B722A7}"); Chain("{77874C77-93E5-4488-A404-A630907CEEF0}"); + Chain("{23275462-446E-44C7-8C2C-3B8C1127B07D}"); + Chain("{6B251841-3069-4AD5-8AE9-861F9523E8DA}"); //FINAL diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs index eb39f37112..d7180385f0 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs @@ -7,10 +7,11 @@ using NPoco; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; -using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Persistence.Querying; namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 { + public class DataTypeMigration : MigrationBase { public DataTypeMigration(IMigrationContext context) @@ -79,10 +80,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 Database.Update(dataType); } - - // drop preValues table - // FIXME keep it around for now - //Delete.Table("cmsDataTypePreValues"); } [TableName("cmsDataTypePreValues")] diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs new file mode 100644 index 0000000000..c9eba205e8 --- /dev/null +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Dtos; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Logging; + +namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 +{ + public class DropDownPropertyEditorsMigration : MigrationBase + { + public DropDownPropertyEditorsMigration(IMigrationContext context) : base(context) + { + } + + public override void Migrate() + { + //need to convert the old drop down data types to use the new one + var oldDropDowns = Database.Fetch(Sql().Select().Where(x => x.EditorAlias.Contains(".DropDown"))); + foreach(var dd in oldDropDowns) + { + //nothing to change if there is no config + if (dd.Configuration.IsNullOrWhiteSpace()) continue; + + ValueListConfiguration config; + try + { + config = JsonConvert.DeserializeObject(dd.Configuration); + } + catch (Exception ex) + { + Logger.Error(ex, $"Invalid drop down configuration detected: \"{dd.Configuration}\", cannot convert editor, values will be cleared"); + dd.Configuration = null; + Database.Update(dd); + continue; + } + + var propDataSql = Sql().Select("*").From() + .InnerJoin().On(x => x.Id, x => x.PropertyTypeId) + .InnerJoin().On(x => x.NodeId, x => x.DataTypeId) + .Where(x => x.EditorAlias == dd.EditorAlias); + + var propDatas = Database.Query(propDataSql); + var toUpdate = new List(); + foreach (var propData in propDatas) + { + if (UpdatePropertyDataDto(propData, config)) + { + //update later, we are iterating all values right now so no SQL can be run inside of this iteration (i.e. Query) + toUpdate.Add(propData); + } + } + + //run the property data updates + foreach(var propData in toUpdate) + { + Database.Update(propData); + } + + var requiresCacheRebuild = false; + switch (dd.EditorAlias) + { + case "Umbraco.DropDown": + UpdateDataType(dd, config, false); + break; + case "Umbraco.DropdownlistPublishingKeys": + UpdateDataType(dd, config, false); + requiresCacheRebuild = true; + break; + case "Umbraco.DropDownMultiple": + UpdateDataType(dd, config, false); + break; + case "Umbraco.DropdownlistMultiplePublishKeys": + UpdateDataType(dd, config, true); + requiresCacheRebuild = true; + break; + } + + if (requiresCacheRebuild) + { + //TODO: How to force rebuild the cache? + } + } + } + + private void UpdateDataType(DataTypeDto dataType, ValueListConfiguration config, bool isMultiple) + { + dataType.EditorAlias = Constants.PropertyEditors.Aliases.DropDownListFlexible; + var flexConfig = new + { + multiple = isMultiple, + items = config.Items + }; + dataType.Configuration = JsonConvert.SerializeObject(flexConfig); + } + + private bool UpdatePropertyDataDto(PropertyDataDto propData, ValueListConfiguration config) + { + //Get the INT ids stored for this property/drop down + IEnumerable ids = null; + if (!propData.VarcharValue.IsNullOrWhiteSpace()) + { + ids = ConvertStringValues(propData.VarcharValue); + } + else if (!propData.TextValue.IsNullOrWhiteSpace()) + { + ids = ConvertStringValues(propData.TextValue); + } + else if (propData.IntegerValue.HasValue) + { + ids = new[] { propData.IntegerValue.Value }; + } + + //if there are INT ids, convert them to values based on the configured pre-values + if (ids != null) + { + //map the ids to values + var vals = new List(); + foreach (var id in ids) + { + var val = config.Items.FirstOrDefault(x => x.Id == id); + if (val != null) + vals.Add(val.Value); + } + + propData.VarcharValue = string.Join(",", vals); + propData.TextValue = null; + propData.IntegerValue = null; + return true; + } + + return false; + } + + private IEnumerable ConvertStringValues(string val) + { + return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) + .Select(x => int.TryParse(x, out var i) ? i : int.MinValue) + .Where(x => x != int.MinValue); + } + + } +} diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs new file mode 100644 index 0000000000..26402cc477 --- /dev/null +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs @@ -0,0 +1,15 @@ +namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 +{ + public class DropPreValueTable : MigrationBase + { + public DropPreValueTable(IMigrationContext context) : base(context) + { + } + + public override void Migrate() + { + // drop preValues table + Delete.Table("cmsDataTypePreValues").Do(); + } + } +} diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleValueConverter.cs deleted file mode 100644 index d91f45292c..0000000000 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleValueConverter.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Models.PublishedContent; - -namespace Umbraco.Core.PropertyEditors.ValueConverters -{ - [DefaultPropertyValueConverter] - public class DropdownListMultipleValueConverter : PropertyValueConverterBase - { - public override bool IsConverter(PublishedPropertyType propertyType) - => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropDownListMultiple); - - public override Type GetPropertyValueType(PublishedPropertyType propertyType) - => typeof (IEnumerable); - - public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType) - => PropertyCacheLevel.Element; - - public override object ConvertIntermediateToObject(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object source, bool preview) - { - var sourceString = (source ?? "").ToString(); - - if (string.IsNullOrEmpty(sourceString)) - return Enumerable.Empty(); - - var values = - sourceString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim()); - - return values; - } - } -} diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleWithKeysValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleWithKeysValueConverter.cs deleted file mode 100644 index bceebc232b..0000000000 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleWithKeysValueConverter.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Models.PublishedContent; - -namespace Umbraco.Core.PropertyEditors.ValueConverters -{ - [DefaultPropertyValueConverter] - public class DropdownListMultipleWithKeysValueConverter : PropertyValueConverterBase - { - public override bool IsConverter(PublishedPropertyType propertyType) - => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropdownlistMultiplePublishKeys); - - public override Type GetPropertyValueType(PublishedPropertyType propertyType) - => typeof (IEnumerable); - - public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType) - => PropertyCacheLevel.Element; - - public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview) - { - if (source == null) - return new int[] { }; - - var prevalueIds = source.ToString() - .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) - .Select(p => p.Trim()) - .Select(int.Parse) - .ToArray(); - - return prevalueIds; - } - } -} diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListValueConverter.cs deleted file mode 100644 index 5fe1967f32..0000000000 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListValueConverter.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using Umbraco.Core.Models.PublishedContent; - -namespace Umbraco.Core.PropertyEditors.ValueConverters -{ - [DefaultPropertyValueConverter] - public class DropdownListValueConverter : PropertyValueConverterBase - { - public override bool IsConverter(PublishedPropertyType propertyType) - => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropDownList); - - public override Type GetPropertyValueType(PublishedPropertyType propertyType) - => typeof (string); - - public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType) - => PropertyCacheLevel.Element; - - public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview) - { - return source?.ToString() ?? string.Empty; - } - } -} diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListWithKeysValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListWithKeysValueConverter.cs deleted file mode 100644 index 960cd4afa6..0000000000 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListWithKeysValueConverter.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using Umbraco.Core.Models.PublishedContent; - -namespace Umbraco.Core.PropertyEditors.ValueConverters -{ - [DefaultPropertyValueConverter] - public class DropdownListWithKeysValueConverter : PropertyValueConverterBase - { - public override bool IsConverter(PublishedPropertyType propertyType) - => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropdownlistPublishKeys); - - public override Type GetPropertyValueType(PublishedPropertyType propertyType) - => typeof (int); - - public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType) - => PropertyCacheLevel.Element; - - public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview) - { - var intAttempt = source.TryConvertTo(); - if (intAttempt.Success) - return intAttempt.Result; - - return null; - } - } -} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 6951a9e17a..4d4bbb32e2 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -356,6 +356,8 @@ + + @@ -1239,10 +1241,6 @@ - - - - diff --git a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs index 9ba5ccf6f2..129116bf61 100644 --- a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs @@ -21,28 +21,15 @@ namespace Umbraco.Tests.PropertyEditors /// Tests for the base classes of ValueEditors and PreValueEditors that are used for Property Editors that edit /// multiple values such as the drop down list, check box list, color picker, etc.... /// + /// + /// Mostly this used to test the we'd store INT Ids in the Db but publish STRING values or sometimes the INT values + /// to cache. Now we always just deal with strings and we'll keep the tests that show that. + /// [TestFixture] public class MultiValuePropertyEditorTests { - //TODO: Test the other formatting methods for the drop down classes - [Test] - public void DropDownMultipleValueEditor_With_Keys_Format_Data_For_Cache() - { - var dataTypeServiceMock = new Mock(); - var editor = new PublishValuesMultipleValueEditor(true, Mock.Of(), new DataEditorAttribute("key", "nam", "view")); - - var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of(), Mock.Of())); - var prop = new Property(1, new PropertyType(dataType)); - prop.SetValue("1234,4567,8910"); - - var result = editor.ConvertDbToString(prop.PropertyType, prop.GetValue(), new Mock().Object); - - Assert.AreEqual("1234,4567,8910", result); - } - - [Test] - public void DropDownMultipleValueEditor_No_Keys_Format_Data_For_Cache() + public void DropDownMultipleValueEditor_Format_Data_For_Cache() { var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of(), Mock.Of())) { @@ -61,7 +48,7 @@ namespace Umbraco.Tests.PropertyEditors var dataTypeService = new TestObjects.TestDataTypeService(dataType); var prop = new Property(1, new PropertyType(dataType)); - prop.SetValue("1234,4567,8910"); + prop.SetValue("Value 1,Value 2,Value 3"); var valueEditor = dataType.Editor.GetValueEditor(); ((DataValueEditor) valueEditor).Configuration = dataType.Configuration; @@ -90,7 +77,7 @@ namespace Umbraco.Tests.PropertyEditors var dataTypeService = new TestObjects.TestDataTypeService(dataType); var prop = new Property(1, new PropertyType(dataType)); - prop.SetValue("1234"); + prop.SetValue("Value 2"); var result = dataType.Editor.GetValueEditor().ConvertDbToString(prop.PropertyType, prop.GetValue(), dataTypeService); diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs index 2c3a2d1583..7ec23158f6 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs @@ -1,8 +1,14 @@ using System; using System.Collections.Generic; +using System.Linq; +using Moq; using NUnit.Framework; +using Umbraco.Core.Models; +using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; +using Umbraco.Web.PropertyEditors; +using Umbraco.Web.PropertyEditors.ValueConverters; namespace Umbraco.Tests.PropertyEditors { @@ -79,27 +85,26 @@ namespace Umbraco.Tests.PropertyEditors [TestCase(null, new string[] { })] public void CanConvertDropdownListMultiplePropertyEditor(object value, IEnumerable expected) { - var converter = new DropdownListMultipleValueConverter(); - var inter = converter.ConvertSourceToIntermediate(null, null, value, false); - var result = converter.ConvertIntermediateToObject(null, null, PropertyCacheLevel.Unknown, inter, false); + var mockPublishedContentTypeFactory = new Mock(); + mockPublishedContentTypeFactory.Setup(x => x.GetDataType(123)) + .Returns(new PublishedDataType(123, "test", new Lazy(() => new DropDownFlexibleConfiguration + { + Multiple = true + }))); + + var publishedPropType = new PublishedPropertyType( + new PublishedContentType(1234, "test", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Nothing), + new PropertyType("test", ValueStorageType.Nvarchar) { DataTypeId = 123 }, + new PropertyValueConverterCollection(Enumerable.Empty()), + Mock.Of(), mockPublishedContentTypeFactory.Object); + + var converter = new FlexibleDropdownPropertyValueConverter(); + var inter = converter.ConvertSourceToIntermediate(null, publishedPropType, value, false); + var result = converter.ConvertIntermediateToObject(null, publishedPropType, PropertyCacheLevel.Unknown, inter, false); Assert.AreEqual(expected, result); } - - [TestCase("100", new[] { 100 })] - [TestCase("100,200", new[] { 100, 200 })] - [TestCase("100 , 200, 300 ", new[] { 100, 200, 300 })] - [TestCase("", new int[] { })] - [TestCase(null, new int[] { })] - public void CanConvertDropdownListMultipleWithKeysPropertyEditor(object value, IEnumerable expected) - { - var converter = new DropdownListMultipleWithKeysValueConverter(); - var inter = converter.ConvertSourceToIntermediate(null, null, value, false); - var result = converter.ConvertIntermediateToObject(null, null, PropertyCacheLevel.Unknown, inter, false); - - Assert.AreEqual(expected, result); - } - + [TestCase("1", 1)] [TestCase("1", 1)] [TestCase("0", 0)] diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs index 752d0ac97e..42beea7df3 100644 --- a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs +++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs @@ -362,12 +362,10 @@ namespace Umbraco.Tests.TestHelpers.Entities contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.NoEdit, ValueStorageType.Nvarchar) { Alias = "label", Name = "Label", Mandatory = false, SortOrder = 7, DataTypeId = -92 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DateTime, ValueStorageType.Date) { Alias = "dateTime", Name = "Date Time", Mandatory = false, SortOrder = 8, DataTypeId = -36 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.ColorPicker, ValueStorageType.Nvarchar) { Alias = "colorPicker", Name = "Color Picker", Mandatory = false, SortOrder = 9, DataTypeId = -37 }); - //that one is gone in 7.4 - //contentCollection.Add(new PropertyType(Constants.PropertyEditors.FolderBrowserAlias, DataTypeDatabaseType.Nvarchar) { Alias = "folderBrowser", Name = "Folder Browser", Mandatory = false, SortOrder = 10, DataTypeDefinitionId = -38 }); - contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DropDownListMultiple, ValueStorageType.Nvarchar) { Alias = "ddlMultiple", Name = "Dropdown List Multiple", Mandatory = false, SortOrder = 11, DataTypeId = -39 }); + contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DropDownListFlexible, ValueStorageType.Nvarchar) { Alias = "ddlMultiple", Name = "Dropdown List Multiple", Mandatory = false, SortOrder = 11, DataTypeId = -39 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.RadioButtonList, ValueStorageType.Nvarchar) { Alias = "rbList", Name = "Radio Button List", Mandatory = false, SortOrder = 12, DataTypeId = -40 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Date, ValueStorageType.Date) { Alias = "date", Name = "Date", Mandatory = false, SortOrder = 13, DataTypeId = -41 }); - contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DropDownList, ValueStorageType.Integer) { Alias = "ddl", Name = "Dropdown List", Mandatory = false, SortOrder = 14, DataTypeId = -42 }); + contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DropDownListFlexible, ValueStorageType.Integer) { Alias = "ddl", Name = "Dropdown List", Mandatory = false, SortOrder = 14, DataTypeId = -42 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.CheckBoxList, ValueStorageType.Nvarchar) { Alias = "chklist", Name = "Checkbox List", Mandatory = false, SortOrder = 15, DataTypeId = -43 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.ContentPicker, ValueStorageType.Integer) { Alias = "contentPicker", Name = "Content Picker", Mandatory = false, SortOrder = 16, DataTypeId = 1046 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.MediaPicker, ValueStorageType.Integer) { Alias = "mediaPicker", Name = "Media Picker", Mandatory = false, SortOrder = 17, DataTypeId = 1048 }); @@ -375,11 +373,6 @@ namespace Umbraco.Tests.TestHelpers.Entities contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.RelatedLinks, ValueStorageType.Ntext) { Alias = "relatedLinks", Name = "Related Links", Mandatory = false, SortOrder = 21, DataTypeId = 1050 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Tags, ValueStorageType.Ntext) { Alias = "tags", Name = "Tags", Mandatory = false, SortOrder = 22, DataTypeId = 1041 }); - //contentCollection.Add(new PropertyType(Constants.PropertyEditors.UltraSimpleEditorAlias, DataTypeDatabaseType.Ntext) { Alias = "simpleEditor", Name = "Ultra Simple Editor", Mandatory = false, SortOrder = 19, DataTypeDefinitionId = 1038 }); - //contentCollection.Add(new PropertyType(Constants.PropertyEditors.UltimatePickerAlias, DataTypeDatabaseType.Ntext) { Alias = "ultimatePicker", Name = "Ultimate Picker", Mandatory = false, SortOrder = 20, DataTypeDefinitionId = 1039 }); - //contentCollection.Add(new PropertyType(Constants.PropertyEditors.MacroContainerAlias, DataTypeDatabaseType.Ntext) { Alias = "macroContainer", Name = "Macro Container", Mandatory = false, SortOrder = 23, DataTypeDefinitionId = 1042 }); - //contentCollection.Add(new PropertyType(Constants.PropertyEditors.ImageCropperAlias, DataTypeDatabaseType.Ntext) { Alias = "imgCropper", Name = "Image Cropper", Mandatory = false, SortOrder = 24, DataTypeDefinitionId = 1043 }); - contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 }); return contentType; diff --git a/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs index 53de8460f2..7f8dc3f03a 100644 --- a/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/CheckBoxListPropertyEditor.cs @@ -31,6 +31,6 @@ namespace Umbraco.Web.PropertyEditors protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService); /// - protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(false, Attribute); + protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(Logger, Attribute); } } diff --git a/src/Umbraco.Web/PropertyEditors/DropDownFlexiblePropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownFlexiblePropertyEditor.cs index 6acbedef63..4424e1d245 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownFlexiblePropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownFlexiblePropertyEditor.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.PropertyEditors protected override IDataValueEditor CreateValueEditor() { - return new PublishValuesMultipleValueEditor(false, Attribute); + return new PublishValuesMultipleValueEditor(Logger, Attribute); } protected override IConfigurationEditor CreateConfigurationEditor() => new DropDownFlexibleConfigurationEditor(_textService); diff --git a/src/Umbraco.Web/PropertyEditors/DropDownMultipleConfigurationEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownMultipleConfigurationEditor.cs deleted file mode 100644 index a8956f9c4f..0000000000 --- a/src/Umbraco.Web/PropertyEditors/DropDownMultipleConfigurationEditor.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; - -namespace Umbraco.Web.PropertyEditors -{ - /// - /// Represents a configuration editor for the "drop down list multiple" property editor. - /// - /// - /// Ensures that 'multiple' is saved for the config in the db but is not a configuration field. - /// This is mostly to maintain backwards compatibility with old property editors. Devs can now simply - /// use the "drop down" property editor and check the "multiple" configuration checkbox - /// fixme what is multiple exactly?! - /// - internal class DropDownMultipleConfigurationEditor : ValueListConfigurationEditor - { - public DropDownMultipleConfigurationEditor(ILocalizedTextService textService) - : base(textService) - { - Fields.Add(new ConfigurationField - { - Key = "multiple", - Name = "multiple", - View = "hidden", // so it does not show in the configuration editor - HideLabel = true - }); - } - - // editor... - // - // receives: - // "preValues":[ - // { - // "label":"Add prevalue", - // "description":"Add and remove values for the list", - // "hideLabel":false, - // "view":"multivalues", - // "config":{}, - // "key":"items", - // "value":{"169":{"value":"a","sortOrder":1},"170":{"value":"b","sortOrder":2},"171":{"value":"c","sortOrder":3}} - // }, - // { - // "label":"multiple", - // "description":null, - // "hideLabel":true, - // "view":"hidden", - // "config":{}, - // "key":"multiple", - // "value":"1" - // }] - // - // posts ('d' being a new value): - // [{key: "items", value: [{value: "a", sortOrder: 1, id: "169"}, {value: "c", sortOrder: 3, id: "171"}, {value: "d"}]}, {key: "multiple", value: "1"}] - // - // the 'multiple' thing never goes to DB - // values go to DB with alias 0, 1, 2 + their ID + value - // the sort order that comes back makes no sense - // - // FromEditor can totally ignore 'multiple' - - /// - public override Dictionary ToConfigurationEditor(ValueListConfiguration configuration) - { - var dictionary = base.ToConfigurationEditor(configuration); - - // always add the multiple field, as 'true' - dictionary["multiple"] = 1; - - return dictionary; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/PropertyEditors/DropDownMultiplePropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownMultiplePropertyEditor.cs deleted file mode 100644 index 5992090a62..0000000000 --- a/src/Umbraco.Web/PropertyEditors/DropDownMultiplePropertyEditor.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; - -namespace Umbraco.Web.PropertyEditors -{ - /// - /// A property editor to allow multiple selection of pre-defined items - /// - /// - /// Due to maintaining backwards compatibility this data type stores the value as a string which is a comma separated value of the - /// ids of the individual items so we have logic in here to deal with that. - /// - [DataEditor(Constants.PropertyEditors.Aliases.DropDownListMultiple, "Dropdown list multiple", "dropdown", Group = "lists", Icon="icon-bulleted-list", IsDeprecated = true)] - public class DropDownMultiplePropertyEditor : DropDownMultipleWithKeysPropertyEditor - { - /// - /// The constructor will setup the property editor based on the attribute if one is found - /// - public DropDownMultiplePropertyEditor(ILogger logger, ILocalizedTextService textService) - : base(logger, textService) - { } - - /// - protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(false, Attribute); - } -} diff --git a/src/Umbraco.Web/PropertyEditors/DropDownMultipleWithKeysPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownMultipleWithKeysPropertyEditor.cs deleted file mode 100644 index 0b882c6b8d..0000000000 --- a/src/Umbraco.Web/PropertyEditors/DropDownMultipleWithKeysPropertyEditor.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; - -namespace Umbraco.Web.PropertyEditors -{ - /// - /// Represents a property editor that allows multiple selection of pre-defined items. - /// - /// - /// Due to backwards compatibility, this editor stores the value as a CSV string listing - /// the ids of individual items. - /// - [DataEditor(Constants.PropertyEditors.Aliases.DropdownlistMultiplePublishKeys, "Dropdown list multiple, publish keys", "dropdown", Group = "lists", Icon = "icon-bulleted-list", IsDeprecated = true)] - public class DropDownMultipleWithKeysPropertyEditor : DropDownPropertyEditor - { - private readonly ILocalizedTextService _textService; - - /// - /// Initializes a new instance of the class. - /// - public DropDownMultipleWithKeysPropertyEditor(ILogger logger, ILocalizedTextService textService) - : base(logger, textService) - { - _textService = textService; - } - - /// - protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(true, Attribute); - - /// - protected override IConfigurationEditor CreateConfigurationEditor() => new DropDownMultipleConfigurationEditor(_textService); - } -} diff --git a/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs deleted file mode 100644 index f4736ab63f..0000000000 --- a/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Core.PropertyEditors; -using umbraco; -using ClientDependency.Core; -using Umbraco.Core.Services; -using Constants = Umbraco.Core.Constants; - -namespace Umbraco.Web.PropertyEditors -{ - /// - /// A property editor to allow the individual selection of pre-defined items. - /// - /// - /// Due to remaining backwards compatible, this stores the id of the drop down item in the database which is why it is marked - /// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the string value is published - /// in cache and not the int ID. - /// - [DataEditor(Constants.PropertyEditors.Aliases.DropDownList, "Dropdown list", "dropdown", ValueType = ValueTypes.String, Group = "lists", Icon = "icon-indent", IsDeprecated = true)] - public class DropDownPropertyEditor : DropDownWithKeysPropertyEditor - { - /// - /// The constructor will setup the property editor based on the attribute if one is found - /// - public DropDownPropertyEditor(ILogger logger, ILocalizedTextService textService) - : base(logger, textService) - { } - - /// - /// We need to override the value editor so that we can ensure the string value is published in cache and not the integer ID value. - /// - /// - protected override IDataValueEditor CreateValueEditor() => new PublishValueValueEditor(Attribute, Logger); - } -} diff --git a/src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs deleted file mode 100644 index 72d4b8c95f..0000000000 --- a/src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; - -namespace Umbraco.Web.PropertyEditors -{ - /// - /// A property editor to allow the individual selection of pre-defined items. - /// - /// - /// Due to remaining backwards compatible, this stores the id of the drop down item in the database which is why it is marked - /// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the INT ID value is published - /// in cache and not the string value. - /// - [DataEditor(Constants.PropertyEditors.Aliases.DropdownlistPublishKeys, "Dropdown list, publishing keys", "dropdown", ValueType = ValueTypes.Integer, Group = "lists", Icon = "icon-indent", IsDeprecated = true)] - public class DropDownWithKeysPropertyEditor : DataEditor - { - private readonly ILocalizedTextService _textService; - - /// - /// The constructor will setup the property editor based on the attribute if one is found - /// - public DropDownWithKeysPropertyEditor(ILogger logger, ILocalizedTextService textService) - : base(logger) - { - _textService = textService; - } - - /// - /// Return a custom pre-value editor - /// - /// - protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService); - } -} diff --git a/src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs b/src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs deleted file mode 100644 index 49ed34ffef..0000000000 --- a/src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.PropertyEditors -{ - /// - /// A custom value editor for any property editor that stores a pre-value int id so that we can ensure that the 'value' not the ID get's put into cache - /// - /// - /// This is required for legacy/backwards compatibility, otherwise we'd just store the string version and cache the string version without - /// needing additional lookups. - /// - internal class PublishValueValueEditor : DataValueEditor - { - private readonly ILogger _logger; - - internal PublishValueValueEditor(DataEditorAttribute attribute, ILogger logger) - : base(attribute) - { - _logger = logger; - } - - /// - public override string ConvertDbToString(PropertyType propertyType, object value, IDataTypeService dataTypeService) - { - if (value == null) - return null; - - // get the configuration items - // if none, fallback to base - var configuration = dataTypeService.GetDataType(propertyType.DataTypeId).ConfigurationAs(); - if (configuration == null) - return base.ConvertDbToString(propertyType, value, dataTypeService); - - var items = configuration.Items; - - var idAttempt = value.TryConvertTo(); - if (idAttempt.Success) - { - var itemId = idAttempt.Result; - var item = items.FirstOrDefault(x => x.Id == itemId); - if (item != null) return item.Value; - - _logger.Warn("Could not find a configuration item with ID " + itemId + " for property alias " + propertyType.Alias); - } - - // fallback to default - return base.ConvertDbToString(propertyType, value, dataTypeService); - } - } -} diff --git a/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs b/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs index 0276bdc0a4..6aea6edba5 100644 --- a/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs @@ -11,60 +11,21 @@ using Umbraco.Web.Composing; namespace Umbraco.Web.PropertyEditors { /// - /// Custom value editor to handle posted json data and to return json data for the multiple selected items as well as ensuring - /// that the multiple selected int IDs are published to cache as a delimited string (values) + /// Custom value editor to handle posted json data and to return json data for the multiple selected items /// /// /// This is re-used by editors such as the multiple drop down list or check box list /// - internal class PublishValuesMultipleValueEditor : PublishValueValueEditor + internal class PublishValuesMultipleValueEditor : DataValueEditor { - private readonly bool _publishIds; + private readonly ILogger _logger; - internal PublishValuesMultipleValueEditor(bool publishIds, ILogger logger, DataEditorAttribute attribute) - : base(attribute, logger) + internal PublishValuesMultipleValueEditor(ILogger logger, DataEditorAttribute attribute) + : base(attribute) { - _publishIds = publishIds; + _logger = logger; } - - public PublishValuesMultipleValueEditor(bool publishIds, DataEditorAttribute attribute) - : this(publishIds, Current.Logger, attribute) - { } - - /// - /// If publishing ids, we don't need to do anything, otherwise we need to look up the pre-values and get the string values - /// - /// - /// - /// - /// - public override string ConvertDbToString(PropertyType propertyType, object propertyValue, IDataTypeService dataTypeService) - { - if (propertyValue == null) - return null; - - //publishing ids, so just need to return the value as-is - if (_publishIds) - { - return propertyValue.ToString(); - } - - // get the multiple ids - // if none, fallback to base - var selectedIds = propertyValue.ToString().Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries); - if (selectedIds.Any() == false) - return base.ConvertDbToString(propertyType, propertyValue, dataTypeService); - - // get the configuration items - // if none, fallback to base - var configuration = dataTypeService.GetDataType(propertyType.DataTypeId).ConfigurationAs(); - if (configuration == null) - return base.ConvertDbToString(propertyType, propertyValue, dataTypeService); - - var items = configuration.Items.Where(x => selectedIds.Contains(x.Id.ToInvariantString())).Select(x => x.Value); - return string.Join(",", items); - } - + /// /// Override so that we can return a json array to the editor for multi-select values /// @@ -81,7 +42,7 @@ namespace Umbraco.Web.PropertyEditors /// /// When multiple values are selected a json array will be posted back so we need to format for storage in - /// the database which is a comma separated ID value + /// the database which is a comma separated string value /// /// /// diff --git a/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs index e5d9e4d4e8..46069fec79 100644 --- a/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs @@ -8,19 +8,24 @@ namespace Umbraco.Web.PropertyEditors /// /// A property editor to allow the individual selection of pre-defined items. /// - /// - /// Due to remaining backwards compatible, this stores the id of the item in the database which is why it is marked - /// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the INT ID value is published - /// in cache and not the string value. - /// [DataEditor(Constants.PropertyEditors.Aliases.RadioButtonList, "Radio button list", "radiobuttons", ValueType = ValueTypes.Integer, Group="lists", Icon="icon-target")] - public class RadioButtonsPropertyEditor : DropDownWithKeysPropertyEditor + public class RadioButtonsPropertyEditor : DataEditor { + private readonly ILocalizedTextService _textService; + /// /// The constructor will setup the property editor based on the attribute if one is found /// public RadioButtonsPropertyEditor(ILogger logger, ILocalizedTextService textService) - : base(logger, textService) - { } + : base(logger) + { + _textService = textService; + } + + /// + /// Return a custom pre-value editor + /// + /// + protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService); } } diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs index 521817a7de..d470f54662 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Umbraco.Core; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; @@ -16,7 +17,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview) { - return source?.ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + return source?.ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim()).ToArray() + ?? Enumerable.Empty(); } public override object ConvertIntermediateToObject(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 6f122719d0..313b82de29 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -360,7 +360,6 @@ - @@ -814,11 +813,9 @@ - - @@ -828,9 +825,6 @@ - - - From f332e9a07e13b9a27cb4516cc5efefadb1909a74 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 24 Oct 2018 15:45:24 +1100 Subject: [PATCH 02/16] Fix sql and table check --- .../Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs | 7 +++++-- .../Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs index c9eba205e8..2f50b9cd72 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs @@ -18,7 +18,10 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 public override void Migrate() { //need to convert the old drop down data types to use the new one - var oldDropDowns = Database.Fetch(Sql().Select().Where(x => x.EditorAlias.Contains(".DropDown"))); + var oldDropDowns = Database.Fetch(Sql() + .Select() + .From() + .Where(x => x.EditorAlias.Contains(".DropDown"))); foreach(var dd in oldDropDowns) { //nothing to change if there is no config @@ -37,7 +40,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 continue; } - var propDataSql = Sql().Select("*").From() + var propDataSql = Sql().Select().From() .InnerJoin().On(x => x.Id, x => x.PropertyTypeId) .InnerJoin().On(x => x.NodeId, x => x.DataTypeId) .Where(x => x.EditorAlias == dd.EditorAlias); diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs index 26402cc477..fa6e47fac7 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs @@ -9,7 +9,8 @@ public override void Migrate() { // drop preValues table - Delete.Table("cmsDataTypePreValues").Do(); + if (TableExists("cmsDataTypePreValues")) + Delete.Table("cmsDataTypePreValues").Do(); } } } From df7623e6a7be9d6dfa5056b1b29c81b07ff3cd7c Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 24 Oct 2018 16:32:13 +1100 Subject: [PATCH 03/16] Fixes migration, ensure's that if it runs again it won't corrupt data, fixes flexible drop down angular editor to post string vals, not the int ids, removes old angular drop down prop editor --- .../DropDownPropertyEditorsMigration.cs | 49 +++++++++---- .../dropdown/dropdown.controller.js | 70 ------------------- .../propertyeditors/dropdown/dropdown.html | 20 ------ .../dropdownFlexible.controller.js | 2 +- .../dropdownFlexible/dropdownFlexible.html | 4 +- .../PublishValuesMultipleValueEditor.cs | 2 +- 6 files changed, 38 insertions(+), 109 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.controller.js delete mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.html diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs index 2f50b9cd72..accb755020 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs @@ -22,7 +22,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 .Select() .From() .Where(x => x.EditorAlias.Contains(".DropDown"))); - foreach(var dd in oldDropDowns) + foreach (var dd in oldDropDowns) { //nothing to change if there is no config if (dd.Configuration.IsNullOrWhiteSpace()) continue; @@ -30,7 +30,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 ValueListConfiguration config; try { - config = JsonConvert.DeserializeObject(dd.Configuration); + config = JsonConvert.DeserializeObject(dd.Configuration); } catch (Exception ex) { @@ -43,7 +43,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 var propDataSql = Sql().Select().From() .InnerJoin().On(x => x.Id, x => x.PropertyTypeId) .InnerJoin().On(x => x.NodeId, x => x.DataTypeId) - .Where(x => x.EditorAlias == dd.EditorAlias); + .Where(x => x.DataTypeId == dd.NodeId); var propDatas = Database.Query(propDataSql); var toUpdate = new List(); @@ -57,7 +57,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 } //run the property data updates - foreach(var propData in toUpdate) + foreach (var propData in toUpdate) { Database.Update(propData); } @@ -97,12 +97,13 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 items = config.Items }; dataType.Configuration = JsonConvert.SerializeObject(flexConfig); + Database.Update(dataType); } private bool UpdatePropertyDataDto(PropertyDataDto propData, ValueListConfiguration config) { //Get the INT ids stored for this property/drop down - IEnumerable ids = null; + int[] ids = null; if (!propData.VarcharValue.IsNullOrWhiteSpace()) { ids = ConvertStringValues(propData.VarcharValue); @@ -117,31 +118,49 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 } //if there are INT ids, convert them to values based on the configured pre-values - if (ids != null) + if (ids != null && ids.Length > 0) { //map the ids to values var vals = new List(); + var canConvert = true; foreach (var id in ids) { var val = config.Items.FirstOrDefault(x => x.Id == id); if (val != null) vals.Add(val.Value); + else + { + Logger.Warn($"Could not find associated data type configuration for stored Id {id}"); + canConvert = false; + } } - - propData.VarcharValue = string.Join(",", vals); - propData.TextValue = null; - propData.IntegerValue = null; - return true; + if (canConvert) + { + propData.VarcharValue = string.Join(",", vals); + propData.TextValue = null; + propData.IntegerValue = null; + return true; + } + } return false; } - private IEnumerable ConvertStringValues(string val) + private int[] ConvertStringValues(string val) { - return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) - .Select(x => int.TryParse(x, out var i) ? i : int.MinValue) - .Where(x => x != int.MinValue); + var splitVals = val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + var intVals = splitVals + .Select(x => int.TryParse(x, out var i) ? i : int.MinValue) + .Where(x => x != int.MinValue) + .ToArray(); + + //only return if the number of values are the same (i.e. All INTs) + if (splitVals.Length == intVals.Length) + return intVals; + + return null; } } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.controller.js deleted file mode 100644 index bcbd13f860..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.controller.js +++ /dev/null @@ -1,70 +0,0 @@ -angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownController", - function($scope) { - - //setup the default config - var config = { - items: [], - multiple: false - }; - - //map the user config - angular.extend(config, $scope.model.config); - - //map back to the model - $scope.model.config = config; - - function convertArrayToDictionaryArray(model){ - //now we need to format the items in the dictionary because we always want to have an array - var newItems = []; - for (var i = 0; i < model.length; i++) { - newItems.push({ id: model[i], sortOrder: 0, value: model[i] }); - } - - return newItems; - } - - - function convertObjectToDictionaryArray(model){ - //now we need to format the items in the dictionary because we always want to have an array - var newItems = []; - var vals = _.values($scope.model.config.items); - var keys = _.keys($scope.model.config.items); - - for (var i = 0; i < vals.length; i++) { - var label = vals[i].value ? vals[i].value : vals[i]; - newItems.push({ id: keys[i], sortOrder: vals[i].sortOrder, value: label }); - } - - return newItems; - } - - if (angular.isArray($scope.model.config.items)) { - //PP: I dont think this will happen, but we have tests that expect it to happen.. - //if array is simple values, convert to array of objects - if(!angular.isObject($scope.model.config.items[0])){ - $scope.model.config.items = convertArrayToDictionaryArray($scope.model.config.items); - } - } - else if (angular.isObject($scope.model.config.items)) { - $scope.model.config.items = convertObjectToDictionaryArray($scope.model.config.items); - } - else { - throw "The items property must be either an array or a dictionary"; - } - - - //sort the values - $scope.model.config.items.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); }); - - //now we need to check if the value is null/undefined, if it is we need to set it to "" so that any value that is set - // to "" gets selected by default - if ($scope.model.value === null || $scope.model.value === undefined) { - if ($scope.model.config.multiple) { - $scope.model.value = []; - } - else { - $scope.model.value = ""; - } - } - - }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.html deleted file mode 100644 index 663373c8eb..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.html +++ /dev/null @@ -1,20 +0,0 @@ -
- - - - - - -
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js index c7a472d80e..1ea77ee035 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js @@ -74,7 +74,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo // if we run in single mode we'll store the value in a local variable // so we can pass an array as the model as our PropertyValueEditor expects that $scope.model.singleDropdownValue = ""; - if ($scope.model.config.multiple === "0") { + if (Object.toBoolean($scope.model.config.multiple)) { $scope.model.singleDropdownValue = Array.isArray($scope.model.value) ? $scope.model.value[0] : $scope.model.value; } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html index 5edbab4f30..7c55f0bda9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html @@ -5,7 +5,7 @@ ng-switch-default ng-change="updateSingleDropdownValue()" ng-model="model.singleDropdownValue" - ng-options="item.id as item.value for item in model.config.items"> + ng-options="item.value as item.value for item in model.config.items"> @@ -15,5 +15,5 @@ ng-switch-when="1" multiple ng-model="model.value" - ng-options="item.id as item.value for item in model.config.items"> + ng-options="item.value as item.value for item in model.config.items"> diff --git a/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs b/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs index 6aea6edba5..8e0737dedd 100644 --- a/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.PropertyEditors { _logger = logger; } - + /// /// Override so that we can return a json array to the editor for multi-select values /// From b199b7346b107c77ad180c691cfed7ffe52d15e0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 24 Oct 2018 16:35:30 +1100 Subject: [PATCH 04/16] Fixes multiple selection with drop down --- .../dropdownFlexible/dropdownFlexible.controller.js | 5 ++++- .../propertyeditors/dropdownFlexible/dropdownFlexible.html | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js index 1ea77ee035..23bd2c9a42 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js @@ -12,7 +12,10 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo //map back to the model $scope.model.config = config; - + + //ensure this is a bool, old data could store zeros/ones or string versions + $scope.model.config.multiple = Object.toBoolean($scope.model.config.multiple); + function convertArrayToDictionaryArray(model){ //now we need to format the items in the dictionary because we always want to have an array var newItems = []; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html index 7c55f0bda9..3239e64acc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html @@ -12,7 +12,7 @@ From 9347e6205fe5be3a8d1638d5a9626db5555dc416 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 24 Oct 2018 16:36:13 +1100 Subject: [PATCH 05/16] fixes test --- src/Umbraco.Tests/Composing/TypeLoaderTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs index 9b23ec3d6b..1199b37cdb 100644 --- a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs +++ b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs @@ -279,7 +279,7 @@ AnotherContentFinder public void GetDataEditors() { var types = _typeLoader.GetDataEditors(); - Assert.AreEqual(43, types.Count()); + Assert.AreEqual(39, types.Count()); } /// From bae9bb6108157b42bfd5daaceda789c075f1759c Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 29 Oct 2018 17:27:33 +1100 Subject: [PATCH 06/16] Initial cleanup of IActions, menu items, etc... --- .../ActionMetadataAttribute.cs | 35 ---- src/Umbraco.Core/Umbraco.Core.csproj | 1 - .../Composing/ActionCollectionTests.cs | 73 ------- .../Composing/TypeLoaderTests.cs | 7 - .../Services/UserServiceTests.cs | 71 +++---- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 7 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 1 - .../BackOfficeControllerUnitTests.cs | 15 -- .../Web/Controllers/ContentControllerTests.cs | 11 +- .../lib/umbraco/LegacyUmbClientMgr.js | 6 +- .../src/common/services/tree.service.js | 33 ++- .../common/dialogs/legacydelete.controller.js | 34 ++++ .../views/common/dialogs/legacydelete.html | 14 ++ src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 2 - .../TreeMenu/ActionDeleteRelationType.js | 21 -- .../TreeMenu/ActionNewRelationType.js | 3 - src/Umbraco.Web/Actions/ActionAssignDomain.cs | 21 ++ src/Umbraco.Web/Actions/ActionBrowse.cs | 27 +++ .../Actions/ActionChangeDocType.cs | 20 ++ .../{_Legacy => }/Actions/ActionCollection.cs | 14 +- .../Actions/ActionCollectionBuilder.cs | 18 ++ src/Umbraco.Web/Actions/ActionCopy.cs | 20 ++ .../ActionCreateBlueprintFromContent.cs | 16 ++ src/Umbraco.Web/Actions/ActionDelete.cs | 23 +++ .../Actions/ActionEmptyTranscan.cs | 16 ++ src/Umbraco.Web/Actions/ActionExport.cs | 15 ++ src/Umbraco.Web/Actions/ActionImport.cs | 15 ++ src/Umbraco.Web/Actions/ActionMove.cs | 22 ++ src/Umbraco.Web/Actions/ActionNew.cs | 23 +++ src/Umbraco.Web/Actions/ActionNotify.cs | 16 ++ src/Umbraco.Web/Actions/ActionProtect.cs | 20 ++ src/Umbraco.Web/Actions/ActionPublish.cs | 21 ++ src/Umbraco.Web/Actions/ActionRePublish.cs | 16 ++ src/Umbraco.Web/Actions/ActionRefresh.cs | 23 +++ src/Umbraco.Web/Actions/ActionRestore.cs | 20 ++ src/Umbraco.Web/Actions/ActionRights.cs | 20 ++ src/Umbraco.Web/Actions/ActionRollback.cs | 20 ++ src/Umbraco.Web/Actions/ActionSort.cs | 19 ++ src/Umbraco.Web/Actions/ActionToPublish.cs | 22 ++ src/Umbraco.Web/Actions/ActionUnpublish.cs | 21 ++ src/Umbraco.Web/Actions/ActionUpdate.cs | 22 ++ src/Umbraco.Web/Actions/IAction.cs | 46 +++++ .../Components/NotificationsComponent.cs | 17 +- src/Umbraco.Web/Composing/Current.cs | 3 +- src/Umbraco.Web/CompositionExtensions.cs | 2 +- .../Editors/BackOfficeController.cs | 60 +----- src/Umbraco.Web/Editors/ContentController.cs | 17 +- .../Filters/ContentSaveValidationAttribute.cs | 19 +- .../UserGroupDefaultPermissionsResolver.cs | 13 +- .../Models/Mapping/UserMapperProfile.cs | 3 +- .../Models/Trees/ActionMenuItem.cs | 49 +++-- .../Models/Trees/ActionMenuItemAttribute.cs | 39 ---- .../Models/Trees/CreateChildEntity.cs | 22 +- src/Umbraco.Web/Models/Trees/DisableUser.cs | 15 -- src/Umbraco.Web/Models/Trees/ExportMember.cs | 5 +- src/Umbraco.Web/Models/Trees/MenuItem.cs | 22 +- src/Umbraco.Web/Models/Trees/MenuItemList.cs | 142 ++++--------- src/Umbraco.Web/Models/Trees/RefreshNode.cs | 23 ++- .../NotificationServiceExtensions.cs | 3 +- .../Runtime/WebRuntimeComponent.cs | 5 +- .../Trees/ContentBlueprintTreeController.cs | 14 +- .../Trees/ContentTreeController.cs | 53 ++--- .../Trees/ContentTreeControllerBase.cs | 15 +- .../Trees/ContentTypeTreeController.cs | 36 ++-- .../Trees/DataTypeTreeController.cs | 22 +- .../Trees/DictionaryTreeController.cs | 11 +- .../Trees/FileSystemTreeController.cs | 19 +- .../Trees/LegacyTreeDataConverter.cs | 66 +----- src/Umbraco.Web/Trees/MacrosTreeController.cs | 9 +- src/Umbraco.Web/Trees/MediaTreeController.cs | 37 ++-- .../Trees/MediaTypeTreeController.cs | 34 ++-- src/Umbraco.Web/Trees/MemberTreeController.cs | 18 +- .../MemberTypeAndGroupTreeControllerBase.cs | 9 +- .../Trees/PackagesTreeController.cs | 12 +- .../Trees/RelationTypeTreeController.cs | 13 +- .../Trees/TemplatesTreeController.cs | 11 +- .../Trees/UserPermissionsTreeController.cs | 5 +- src/Umbraco.Web/Trees/UserTreeController.cs | 2 +- src/Umbraco.Web/TypeLoaderExtensions.cs | 21 +- .../UI/Pages/UmbracoEnsuredPage.cs | 3 +- src/Umbraco.Web/Umbraco.Web.csproj | 68 +++---- ...EnsureUserPermissionForContentAttribute.cs | 5 +- .../FilterAllowedOutgoingContentAttribute.cs | 11 +- src/Umbraco.Web/_Legacy/Actions/Action.cs | 191 ------------------ .../_Legacy/Actions/ActionAssignDomain.cs | 74 ------- .../_Legacy/Actions/ActionBrowse.cs | 65 ------ .../_Legacy/Actions/ActionChangeDocType.cs | 88 -------- .../Actions/ActionCollectionBuilder.cs | 71 ------- src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs | 88 -------- .../ActionCreateBlueprintFromContent.cs | 32 --- .../_Legacy/Actions/ActionDelete.cs | 82 -------- .../_Legacy/Actions/ActionEmptyTranscan.cs | 78 ------- .../_Legacy/Actions/ActionExport.cs | 76 ------- .../_Legacy/Actions/ActionImport.cs | 77 ------- src/Umbraco.Web/_Legacy/Actions/ActionMove.cs | 88 -------- src/Umbraco.Web/_Legacy/Actions/ActionNew.cs | 75 ------- .../_Legacy/Actions/ActionNotify.cs | 81 -------- src/Umbraco.Web/_Legacy/Actions/ActionNull.cs | 56 ----- .../_Legacy/Actions/ActionPackage.cs | 80 -------- .../_Legacy/Actions/ActionPackageCreate.cs | 80 -------- .../_Legacy/Actions/ActionProtect.cs | 88 -------- .../_Legacy/Actions/ActionPublish.cs | 82 -------- .../_Legacy/Actions/ActionRePublish.cs | 79 -------- .../_Legacy/Actions/ActionRefresh.cs | 86 -------- .../_Legacy/Actions/ActionRestore.cs | 32 --- .../_Legacy/Actions/ActionRights.cs | 88 -------- .../_Legacy/Actions/ActionRollback.cs | 87 -------- src/Umbraco.Web/_Legacy/Actions/ActionSort.cs | 88 -------- .../_Legacy/Actions/ActionToPublish.cs | 83 -------- .../_Legacy/Actions/ActionTranslate.cs | 82 -------- .../_Legacy/Actions/ActionUnPublish.cs | 30 --- .../_Legacy/Actions/ActionUpdate.cs | 82 -------- .../_Legacy/Actions/ContextMenuSeperator.cs | 51 ----- src/Umbraco.Web/_Legacy/Actions/IAction.cs | 18 -- .../Actions/LegacyActionMenuItemAttribute.cs | 46 ----- .../RelationTypesWebService.asmx | 1 - .../RelationTypesWebService.asmx.cs | 35 ---- .../TreeMenu/ActionDeleteRelationType.cs | 83 -------- .../TreeMenu/ActionNewRelationType.cs | 83 -------- .../umbraco/dialogs/SendPublish.aspx.cs | 6 +- .../umbraco/templateControls/Item.cs | 5 +- .../umbraco/webservices/nodeSorter.asmx.cs | 5 +- 122 files changed, 1052 insertions(+), 3393 deletions(-) delete mode 100644 src/Umbraco.Core/CodeAnnotations/ActionMetadataAttribute.cs delete mode 100644 src/Umbraco.Tests/Composing/ActionCollectionTests.cs create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.html delete mode 100644 src/Umbraco.Web.UI/Umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.js delete mode 100644 src/Umbraco.Web.UI/Umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.js create mode 100644 src/Umbraco.Web/Actions/ActionAssignDomain.cs create mode 100644 src/Umbraco.Web/Actions/ActionBrowse.cs create mode 100644 src/Umbraco.Web/Actions/ActionChangeDocType.cs rename src/Umbraco.Web/{_Legacy => }/Actions/ActionCollection.cs (61%) create mode 100644 src/Umbraco.Web/Actions/ActionCollectionBuilder.cs create mode 100644 src/Umbraco.Web/Actions/ActionCopy.cs create mode 100644 src/Umbraco.Web/Actions/ActionCreateBlueprintFromContent.cs create mode 100644 src/Umbraco.Web/Actions/ActionDelete.cs create mode 100644 src/Umbraco.Web/Actions/ActionEmptyTranscan.cs create mode 100644 src/Umbraco.Web/Actions/ActionExport.cs create mode 100644 src/Umbraco.Web/Actions/ActionImport.cs create mode 100644 src/Umbraco.Web/Actions/ActionMove.cs create mode 100644 src/Umbraco.Web/Actions/ActionNew.cs create mode 100644 src/Umbraco.Web/Actions/ActionNotify.cs create mode 100644 src/Umbraco.Web/Actions/ActionProtect.cs create mode 100644 src/Umbraco.Web/Actions/ActionPublish.cs create mode 100644 src/Umbraco.Web/Actions/ActionRePublish.cs create mode 100644 src/Umbraco.Web/Actions/ActionRefresh.cs create mode 100644 src/Umbraco.Web/Actions/ActionRestore.cs create mode 100644 src/Umbraco.Web/Actions/ActionRights.cs create mode 100644 src/Umbraco.Web/Actions/ActionRollback.cs create mode 100644 src/Umbraco.Web/Actions/ActionSort.cs create mode 100644 src/Umbraco.Web/Actions/ActionToPublish.cs create mode 100644 src/Umbraco.Web/Actions/ActionUnpublish.cs create mode 100644 src/Umbraco.Web/Actions/ActionUpdate.cs create mode 100644 src/Umbraco.Web/Actions/IAction.cs delete mode 100644 src/Umbraco.Web/Models/Trees/ActionMenuItemAttribute.cs delete mode 100644 src/Umbraco.Web/Models/Trees/DisableUser.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/Action.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionEmptyTranscan.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionExport.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionImport.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionMove.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionNew.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionNotify.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionNull.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionPackage.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionPackageCreate.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionRePublish.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionRefresh.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionRestore.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionRights.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionSort.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionUnPublish.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/ContextMenuSeperator.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/IAction.cs delete mode 100644 src/Umbraco.Web/_Legacy/Actions/LegacyActionMenuItemAttribute.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/RelationTypesWebService.asmx delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/RelationTypesWebService.asmx.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.cs 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 e0aa93efec..18711bf8de 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 04bd0a2e1e..0000000000 --- a/src/Umbraco.Tests/Composing/ActionCollectionTests.cs +++ /dev/null @@ -1,73 +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 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; - } - - #endregion - } -} diff --git a/src/Umbraco.Tests/Composing/TypeLoaderTests.cs b/src/Umbraco.Tests/Composing/TypeLoaderTests.cs index a7b3d0f446..1240b5acb2 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 61% rename from src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs rename to src/Umbraco.Web/Actions/ActionCollection.cs index 849fb3b619..70a3b67b02 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 { @@ -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..71b1ef48a5 --- /dev/null +++ b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +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; + } +} 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/ActionEmptyTranscan.cs b/src/Umbraco.Web/Actions/ActionEmptyTranscan.cs new file mode 100644 index 0000000000..db70e2d2b2 --- /dev/null +++ b/src/Umbraco.Web/Actions/ActionEmptyTranscan.cs @@ -0,0 +1,16 @@ +using Umbraco.Web.UI.Pages; + + +namespace Umbraco.Web.Actions +{ + //fixme: not needed, remove this + public class ActionEmptyTranscan : IAction + { + public char Letter => 'N'; + public string Alias => "emptyRecycleBin"; + public string Category => null; + public string Icon => "trash"; + public bool ShowInNotifier => false; + public bool CanBePermissionAssigned => false; + } +} diff --git a/src/Umbraco.Web/Actions/ActionExport.cs b/src/Umbraco.Web/Actions/ActionExport.cs new file mode 100644 index 0000000000..8843bee5ea --- /dev/null +++ b/src/Umbraco.Web/Actions/ActionExport.cs @@ -0,0 +1,15 @@ + + +namespace Umbraco.Web.Actions +{ + //fixme: not needed, remove this + public class ActionExport : IAction + { + public char Letter => '9'; + public string Alias => "export"; + public string Category => null; + public string Icon => "download-alt"; + public bool ShowInNotifier => false; + public bool CanBePermissionAssigned => false; + } +} diff --git a/src/Umbraco.Web/Actions/ActionImport.cs b/src/Umbraco.Web/Actions/ActionImport.cs new file mode 100644 index 0000000000..1cd8682735 --- /dev/null +++ b/src/Umbraco.Web/Actions/ActionImport.cs @@ -0,0 +1,15 @@ + + +namespace Umbraco.Web.Actions +{ + //fixme: not needed, remove this + public class ActionImport : IAction + { + public char Letter => '8'; + public string Alias => "importDocumentType"; + public string Category => null; + public string Icon => "page-up"; + public bool ShowInNotifier => false; + public bool CanBePermissionAssigned => false; + } +} 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/ActionNotify.cs b/src/Umbraco.Web/Actions/ActionNotify.cs new file mode 100644 index 0000000000..218345a678 --- /dev/null +++ b/src/Umbraco.Web/Actions/ActionNotify.cs @@ -0,0 +1,16 @@ +using Umbraco.Web.UI.Pages; + + +namespace Umbraco.Web.Actions +{ + //fixme: not needed, remove this + public class ActionNotify : IAction + { + public char Letter => 'T'; + public string Alias => "notify"; + public string Category => null; + public string Icon => "megaphone"; + public bool ShowInNotifier => false; + public bool CanBePermissionAssigned => false; + } +} 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/ActionRePublish.cs b/src/Umbraco.Web/Actions/ActionRePublish.cs new file mode 100644 index 0000000000..c0af369370 --- /dev/null +++ b/src/Umbraco.Web/Actions/ActionRePublish.cs @@ -0,0 +1,16 @@ +using Umbraco.Web.UI.Pages; + + +namespace Umbraco.Web.Actions +{ + //fixme: not needed, remove this + public class ActionRePublish : IAction + { + public char Letter => 'B'; + public string Alias => "republish"; + public string Category => null; + public string Icon => "globe"; + public bool ShowInNotifier => false; + public bool CanBePermissionAssigned => false; + } +} diff --git a/src/Umbraco.Web/Actions/ActionRefresh.cs b/src/Umbraco.Web/Actions/ActionRefresh.cs new file mode 100644 index 0000000000..38247f4e4b --- /dev/null +++ b/src/Umbraco.Web/Actions/ActionRefresh.cs @@ -0,0 +1,23 @@ +using Umbraco.Web.Models.Trees; +using Umbraco.Web.UI.Pages; + + +namespace Umbraco.Web.Actions +{ + ///// + ///// This action is invoked when a node reloads its children + ///// Concerns only the tree itself and thus you should not handle + ///// this action from without umbraco. + ///// + //public class ActionRefresh : IAction + //{ + // public static string ActionAlias => "refreshNode"; + + // public char Letter => 'L'; + // public string Alias => ActionAlias; + // public string Icon => "refresh"; + // public bool ShowInNotifier => false; + // public bool CanBePermissionAssigned => false; + // public string Category => null; + //} +} 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..adfdd752cf --- /dev/null +++ b/src/Umbraco.Web/Actions/ActionRollback.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 is being rolled back + /// + public class ActionRollback : IAction + { + public char Letter => 'K'; + 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..4a68ca1d91 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,25 +932,25 @@ 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. /// /// [EnsureUserPermissionForContent("id", 'U')] - public HttpResponseMessage PostPublishById(int id) + public HttpResponseMessage PostPublishById(ContentPublish model) { - var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(id)); + var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(model.Id)); if (foundContent == null) { - return HandleContentNotFound(id, false); + return HandleContentNotFound(model.Id, false); } var publishResult = Services.ContentService.SavePublishing(foundContent, Security.GetUserId().ResultOr(0)); @@ -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."); 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..ed15b82b16 100644 --- a/src/Umbraco.Web/Models/Trees/ActionMenuItem.cs +++ b/src/Umbraco.Web/Models/Trees/ActionMenuItem.cs @@ -1,41 +1,46 @@ using System; +using System.Diagnostics.CodeAnalysis; using Umbraco.Core; 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 { + /// + /// 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; + + [SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")] 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); - } - //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..90d0e9e1cb 100644 --- a/src/Umbraco.Web/Models/Trees/CreateChildEntity.cs +++ b/src/Umbraco.Web/Models/Trees/CreateChildEntity.cs @@ -1,10 +1,28 @@ -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) + { + Alias = ActionNew.ActionAlias; + Icon = "add"; Name = name; + SeperatorBefore = seperatorBefore; + } + + public CreateChildEntity(ILocalizedTextService textService, bool seperatorBefore = false) + { + Alias = ActionNew.ActionAlias; + Icon = "add"; + Name = textService.Localize($"actions/{Alias}"); + 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..5f3eaebd45 100644 --- a/src/Umbraco.Web/Models/Trees/ExportMember.cs +++ b/src/Umbraco.Web/Models/Trees/ExportMember.cs @@ -3,7 +3,8 @@ /// /// Represents the export member menu item /// - [ActionMenuItem("umbracoMenuActions")] public sealed class ExportMember : ActionMenuItem - { } + { + public override string AngularServiceName => "umbracoMenuActions"; + } } diff --git a/src/Umbraco.Web/Models/Trees/MenuItem.cs b/src/Umbraco.Web/Models/Trees/MenuItem.cs index 88d772b939..fb586e02d6 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,14 +31,19 @@ namespace Umbraco.Web.Models.Trees Name = name; } - public MenuItem(IAction legacyMenu, string name = "") + /// + /// Create a menu item based on an definition + /// + /// + /// + public MenuItem(IAction action, string name = "") : this() { - Name = name.IsNullOrWhiteSpace() ? legacyMenu.Alias : name; - Alias = legacyMenu.Alias; + Name = name.IsNullOrWhiteSpace() ? action.Alias : name; + Alias = action.Alias; SeperatorBefore = false; - Icon = legacyMenu.Icon; - Action = legacyMenu; + Icon = action.Icon; + Action = action; } #endregion @@ -123,7 +129,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); } @@ -201,7 +207,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..1a8a2dd88c 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,65 +34,30 @@ 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 + /// Adds a menu item based on an /// /// 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); + return Add(name, false); } /// - /// Adds a menu item with a key value pair which is merged to the AdditionalData bag + /// Adds a menu item based on an /// + /// The used to localize the action name based on it's alias /// - /// - /// - /// 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) + public MenuItem Add(ILocalizedTextService textService) where T : IAction { - return Add(name, hasSeparator, new Dictionary { { key, value } }); + return Add(textService, false); } /// @@ -98,12 +65,11 @@ namespace Umbraco.Web.Models.Trees /// /// /// - /// /// 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 +79,49 @@ 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) 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) + 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 + }; + + return menuItem; + } + } } diff --git a/src/Umbraco.Web/Models/Trees/RefreshNode.cs b/src/Umbraco.Web/Models/Trees/RefreshNode.cs index 7f20562962..587c51b887 100644 --- a/src/Umbraco.Web/Models/Trees/RefreshNode.cs +++ b/src/Umbraco.Web/Models/Trees/RefreshNode.cs @@ -1,10 +1,29 @@ -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) + { + Alias = "refreshNode"; + Icon = "refresh"; + Name = name; + SeperatorBefore = seperatorBefore; + } + + public RefreshNode(ILocalizedTextService textService, bool seperatorBefore = false) + { + Alias = "refreshNode"; + Icon = "refresh"; + Name = textService.Localize($"actions/{Alias}"); + 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..01df73f4af 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.Localize($"actions/{ActionNew.ActionAlias}")); + 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); 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); return menu; } diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index 4a0589cce4..a759382854 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,22 @@ 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); + //fixme: inject + menu.Items.Add(Services.TextService.Localize("actions", ActionNew.ActionAlias)); + menu.Items.Add(Services.TextService.Localize("actions", Current.Actions.GetAction().Alias), true); //filter the standard items FilterUserAllowedMenuItems(menu, nodeActions); @@ -143,7 +143,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 +165,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 +180,7 @@ namespace Umbraco.Web.Trees else { //set the default to create - nodeMenu.DefaultMenuAlias = ActionNew.Instance.Alias; + nodeMenu.DefaultMenuAlias = ActionNew.ActionAlias; } var allowedMenuItems = GetAllowedUserMenuItemsForNode(item); @@ -239,14 +237,13 @@ namespace Umbraco.Web.Trees AddActionNode(item, menu, true); - AddActionNode(item, menu, convert: true); AddActionNode(item, menu); - AddActionNode(item, menu, convert: true); + AddActionNode(item, menu); AddActionNode(item, menu, true, true); AddActionNode(item, menu, 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.Localize("actions", ActionRestore.ActionAlias)); + menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.ActionAlias)); - menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } @@ -306,20 +303,24 @@ namespace Umbraco.Web.Trees entity.Name = "[[" + entity.Id + "]]"; } + //fixme: Remove the need for converting to legacy private void AddActionNode(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool convert = 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"); - } + ////fixme: Remove the need for converting to legacy + //private void AddActionNode(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool convert = false) + // where TItem : MenuItem, new() + // 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"); + //} 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..c02f691f14 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 { @@ -348,7 +350,7 @@ namespace Umbraco.Web.Trees { 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 RefreshNode(Services.TextService, true)); return menu; } @@ -381,13 +383,16 @@ namespace Umbraco.Web.Trees internal IEnumerable GetAllowedUserMenuItemsForNode(IUmbracoEntity dd) { var permission = Services.UserService.GetPermissions(Security.CurrentUser, dd.Path); - var actions = global::Umbraco.Web._Legacy.Actions.Action.FromEntityPermission(permission) + //fixme: inject + var actions = Current.Actions.FromEntityPermission(permission) .ToList(); + var actionDelete = Current.Actions.GetAction(); + // A user is allowed to delete their own stuff var tryGetCurrentUserId = Security.GetUserId(); - if (tryGetCurrentUserId && dd.CreatorId == tryGetCurrentUserId.Result && actions.Contains(ActionDelete.Instance) == false) - actions.Add(ActionDelete.Instance); + if (tryGetCurrentUserId && dd.CreatorId == tryGetCurrentUserId.Result && actions.Contains(actionDelete) == false) + actions.Add(actionDelete); return actions.Select(x => new MenuItem(x)); } diff --git a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs index a2179be75f..673c5f4168 100644 --- a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs @@ -7,7 +7,8 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Models; using Umbraco.Core.Services; -using Umbraco.Web._Legacy.Actions; +using Umbraco.Web.Actions; + using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi.Filters; @@ -77,12 +78,13 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { //set the default to create - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + menu.DefaultMenuAlias = ActionNew.ActionAlias; // root actions - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionImport.Instance.Alias)), true); - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true); + menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); + return menu; } @@ -90,11 +92,11 @@ namespace Umbraco.Web.Trees if (container != null) { //set the default to create - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + menu.DefaultMenuAlias = ActionNew.ActionAlias; - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); + menu.Items.Add(Services.TextService); - menu.Items.Add(new MenuItem("rename", Services.TextService.Localize(String.Format("actions/{0}", "rename"))) + menu.Items.Add(new MenuItem("rename", Services.TextService.Localize("actions/rename")) { Icon = "icon icon-edit" }); @@ -102,11 +104,9 @@ namespace Umbraco.Web.Trees if (container.HasChildren == false) { //can delete doc type - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)), true); + menu.Items.Add(Services.TextService, true); } - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true); - - + menu.Items.Add(new RefreshNode(Services.TextService, true)); } else { @@ -115,18 +115,18 @@ namespace Umbraco.Web.Trees if (enableInheritedDocumentTypes) { - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); + menu.Items.Add(Services.TextService); } //no move action if this is a child doc type if (parent == null) { - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionMove.Instance.Alias)), true); + menu.Items.Add(Services.TextService, true); } - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionCopy.Instance.Alias))); - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionExport.Instance.Alias)), true); - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)), true); + menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, true); + menu.Items.Add(Services.TextService, true); if (enableInheritedDocumentTypes) - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); } return menu; diff --git a/src/Umbraco.Web/Trees/DataTypeTreeController.cs b/src/Umbraco.Web/Trees/DataTypeTreeController.cs index 3087808f10..4f9f93f110 100644 --- a/src/Umbraco.Web/Trees/DataTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/DataTypeTreeController.cs @@ -9,9 +9,10 @@ using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Services; +using Umbraco.Web.Actions; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Search; -using Umbraco.Web._Legacy.Actions; + using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -100,11 +101,11 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { //set the default to create - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + menu.DefaultMenuAlias = ActionNew.ActionAlias; // 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); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } @@ -112,9 +113,9 @@ namespace Umbraco.Web.Trees if (container != null) { //set the default to create - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + menu.DefaultMenuAlias = ActionNew.ActionAlias; - menu.Items.Add(Services.TextService.Localize($"actions/{ActionNew.Instance.Alias}")); + menu.Items.Add(Services.TextService); menu.Items.Add(new MenuItem("rename", Services.TextService.Localize("actions/rename")) { @@ -124,19 +125,18 @@ namespace Umbraco.Web.Trees if (container.HasChildren == false) { //can delete data type - menu.Items.Add(Services.TextService.Localize($"actions/{ActionDelete.Instance.Alias}")); + menu.Items.Add(Services.TextService); } - menu.Items.Add(Services.TextService.Localize( - $"actions/{ActionRefresh.Instance.Alias}"), hasSeparator: true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); } else { var nonDeletableSystemDataTypeIds = GetNonDeletableSystemDataTypeIds(); if (nonDeletableSystemDataTypeIds.Contains(int.Parse(id)) == false) - menu.Items.Add(Services.TextService.Localize($"actions/{ActionDelete.Instance.Alias}")); + menu.Items.Add(Services.TextService); - menu.Items.Add(Services.TextService.Localize($"actions/{ActionMove.Instance.Alias}"), hasSeparator: true); + menu.Items.Add(Services.TextService, hasSeparator: true); } return menu; diff --git a/src/Umbraco.Web/Trees/DictionaryTreeController.cs b/src/Umbraco.Web/Trees/DictionaryTreeController.cs index 3043377d65..a0510acd3e 100644 --- a/src/Umbraco.Web/Trees/DictionaryTreeController.cs +++ b/src/Umbraco.Web/Trees/DictionaryTreeController.cs @@ -3,7 +3,8 @@ using System.Linq; using System.Net.Http.Formatting; using Umbraco.Core; using Umbraco.Core.Services; -using Umbraco.Web._Legacy.Actions; +using Umbraco.Web.Actions; + using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi.Filters; @@ -95,14 +96,12 @@ namespace Umbraco.Web.Trees { var menu = new MenuItemCollection(); - menu.Items.Add(Services.TextService.Localize($"actions/{ActionNew.Instance.Alias}")); + menu.Items.Add(Services.TextService); if (id != Constants.System.Root.ToInvariantString()) - menu.Items.Add(Services.TextService.Localize( - $"actions/{ActionDelete.Instance.Alias}"), true); + menu.Items.Add(Services.TextService, true); - menu.Items.Add(Services.TextService.Localize( - $"actions/{ActionRefresh.Instance.Alias}"), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } diff --git a/src/Umbraco.Web/Trees/FileSystemTreeController.cs b/src/Umbraco.Web/Trees/FileSystemTreeController.cs index 21e81a58af..a517cd45c2 100644 --- a/src/Umbraco.Web/Trees/FileSystemTreeController.cs +++ b/src/Umbraco.Web/Trees/FileSystemTreeController.cs @@ -7,8 +7,9 @@ using System.Web; using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Services; +using Umbraco.Web.Actions; using Umbraco.Web.Models.Trees; -using Umbraco.Web._Legacy.Actions; + using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -79,11 +80,11 @@ namespace Umbraco.Web.Trees var menu = new MenuItemCollection(); //set the default to create - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + menu.DefaultMenuAlias = ActionNew.ActionAlias; //create action - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); + menu.Items.Add(Services.TextService); //refresh action - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } @@ -93,9 +94,9 @@ namespace Umbraco.Web.Trees var menu = new MenuItemCollection(); //set the default to create - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + menu.DefaultMenuAlias = ActionNew.ActionAlias; //create action - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); + menu.Items.Add(Services.TextService); var hasChildren = FileSystem.GetFiles(path).Any() || FileSystem.GetDirectories(path).Any(); @@ -103,11 +104,11 @@ namespace Umbraco.Web.Trees if (hasChildren == false) { //delete action - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)), true); + menu.Items.Add(Services.TextService, true); } //refresh action - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } @@ -117,7 +118,7 @@ namespace Umbraco.Web.Trees var menu = new MenuItemCollection(); //if it's not a directory then we only allow to delete the item - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias))); + menu.Items.Add(Services.TextService); return menu; } diff --git a/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs b/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs index 131c7954c8..d0bfa360fa 100644 --- a/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs +++ b/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs @@ -6,7 +6,8 @@ using System.Web.Http.Routing; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Services; -using Umbraco.Web._Legacy.Actions; +using Umbraco.Web.Actions; + using Umbraco.Web.Composing; using Umbraco.Web.Models.Trees; @@ -17,6 +18,8 @@ namespace Umbraco.Web.Trees /// internal class LegacyTreeDataConverter { + //fixme: remove this whole class when everything is angularized + /// /// This will look at the legacy IAction's JsFunctionName and convert it to a confirmation dialog view if possible /// @@ -24,14 +27,9 @@ namespace Umbraco.Web.Trees /// internal static Attempt GetLegacyConfirmView(IAction action) { - if (action.JsFunctionName.IsNullOrWhiteSpace()) + switch (action) { - return Attempt.Fail(); - } - - switch (action.JsFunctionName) - { - case "UmbClientMgr.appActions().actionDelete()": + case ActionDelete actionDelete: return Attempt.Succeed( UmbracoConfig.For.GlobalSettings().Path.EnsureEndsWith('/') + "views/common/dialogs/legacydelete.html"); } @@ -49,64 +47,18 @@ namespace Umbraco.Web.Trees /// internal static Attempt GetUrlAndTitleFromLegacyAction(IAction action, string nodeId, string nodeType, string nodeName, string currentSection) { - if (action.JsFunctionName.IsNullOrWhiteSpace()) + switch (action) { - return Attempt.Fail(); - } - - switch (action.JsFunctionName) - { - case "UmbClientMgr.appActions().actionNew()": + case ActionNew actionNew: return Attempt.Succeed( new LegacyUrlAction( "create.aspx?nodeId=" + nodeId + "&nodeType=" + nodeType + "&nodeName=" + nodeName + "&rnd=" + DateTime.UtcNow.Ticks, Current.Services.TextService.Localize("actions/create"))); - case "UmbClientMgr.appActions().actionNewFolder()": - return Attempt.Succeed( - new LegacyUrlAction( - "createFolder.aspx?nodeId=" + nodeId + "&nodeType=" + nodeType + "&nodeName=" + nodeName + "&rnd=" + DateTime.UtcNow.Ticks, - Current.Services.TextService.Localize("actions/create"))); - case "UmbClientMgr.appActions().actionProtect()": + case ActionProtect actionProtect: return Attempt.Succeed( new LegacyUrlAction( "dialogs/protectPage.aspx?mode=cut&nodeId=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, Current.Services.TextService.Localize("actions/protect"))); - case "UmbClientMgr.appActions().actionRollback()": - return Attempt.Succeed( - new LegacyUrlAction( - "dialogs/rollback.aspx?nodeId=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - Current.Services.TextService.Localize("actions/rollback"))); - case "UmbClientMgr.appActions().actionNotify()": - return Attempt.Succeed( - new LegacyUrlAction( - "dialogs/notifications.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - Current.Services.TextService.Localize("actions/notify"))); - case "UmbClientMgr.appActions().actionPublish()": - return Attempt.Succeed( - new LegacyUrlAction( - "dialogs/publish.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - Current.Services.TextService.Localize("actions/publish"))); - case "UmbClientMgr.appActions().actionChangeDocType()": - return Attempt.Succeed( - new LegacyUrlAction( - "dialogs/ChangeDocType.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - Current.Services.TextService.Localize("actions/changeDocType"))); - case "UmbClientMgr.appActions().actionToPublish()": - return Attempt.Succeed( - new LegacyUrlAction( - "dialogs/SendPublish.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - Current.Services.TextService.Localize("actions/sendtopublish"))); - case "UmbClientMgr.appActions().actionRePublish()": - return Attempt.Succeed( - new LegacyUrlAction( - "dialogs/republish.aspx?rnd=" + DateTime.UtcNow.Ticks, - Current.Services.TextService.Localize("actions/republish"))); - case "UmbClientMgr.appActions().actionSendToTranslate()": - return Attempt.Succeed( - new LegacyUrlAction( - "dialogs/sendToTranslation.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - Current.Services.TextService.Localize("actions/sendToTranslate"))); - } return Attempt.Fail(); } diff --git a/src/Umbraco.Web/Trees/MacrosTreeController.cs b/src/Umbraco.Web/Trees/MacrosTreeController.cs index a4f486661e..0faa1ce75d 100644 --- a/src/Umbraco.Web/Trees/MacrosTreeController.cs +++ b/src/Umbraco.Web/Trees/MacrosTreeController.cs @@ -8,7 +8,8 @@ using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Services; -using Umbraco.Web._Legacy.Actions; +using Umbraco.Web.Actions; + using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -58,13 +59,13 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { //Create the normal create action - menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) + menu.Items.Add(Services.TextService) //Since we haven't implemented anything for macros in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(null, "initmacros", queryStrings.GetValue("application")); //refresh action - menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } @@ -74,7 +75,7 @@ namespace Umbraco.Web.Trees if (macro == null) return new MenuItemCollection(); //add delete option for all macros - menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)) + menu.Items.Add(Services.TextService) //Since we haven't implemented anything for macros in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(new EntitySlim diff --git a/src/Umbraco.Web/Trees/MediaTreeController.cs b/src/Umbraco.Web/Trees/MediaTreeController.cs index 8eb37e6224..d260253218 100644 --- a/src/Umbraco.Web/Trees/MediaTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTreeController.cs @@ -8,10 +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; @@ -81,28 +83,25 @@ namespace Umbraco.Web.Trees var menu = new MenuItemCollection(); //set the default - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + menu.DefaultMenuAlias = ActionNew.ActionAlias; if (id == Constants.System.Root.ToInvariantString()) { // 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; } // root actions - 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.Localize("actions", ActionRefresh.Instance.Alias), true); + menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } - int iid; - if (int.TryParse(id, out iid) == false) + if (int.TryParse(id, out var iid) == false) { throw new HttpResponseException(HttpStatusCode.NotFound); } @@ -115,29 +114,27 @@ namespace Umbraco.Web.Trees //if the user has no path access for this node, all they can do is refresh if (Security.CurrentUser.HasPathAccess(item, Services.EntityService, RecycleBinId) == false) { - menu.Items.Add( - Services.TextService.Localize(string.Concat("actions/", ActionRefresh.Instance.Alias)), - true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } //return a normal node menu: - menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)); - menu.Items.Add(Services.TextService.Localize("actions", ActionMove.Instance.Alias)); - menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)); - menu.Items.Add(Services.TextService.Localize("actions", ActionSort.Instance.Alias)); - menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService); + menu.Items.Add(new RefreshNode(Services.TextService, true)); //if the media item is in the recycle bin, don't have a default menu, just show the regular menu if (item.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Contains(RecycleBinId.ToInvariantString())) { menu.DefaultMenuAlias = null; - menu.Items.Insert(2, new MenuItem(ActionRestore.Instance, Services.TextService.Localize("actions", ActionRestore.Instance.Alias))); + menu.Items.Insert(2, new MenuItem(Current.Actions.GetAction(), Services.TextService.Localize("actions", ActionRestore.ActionAlias))); } else { //set the default to create - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + menu.DefaultMenuAlias = ActionNew.ActionAlias; } return menu; diff --git a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs index 7b346c6871..a679cefa32 100644 --- a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs @@ -9,8 +9,9 @@ using Umbraco.Core.Models; using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Services; +using Umbraco.Web.Actions; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web._Legacy.Actions; + using Umbraco.Web.Search; namespace Umbraco.Web.Trees @@ -70,12 +71,11 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { //set the default to create - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + menu.DefaultMenuAlias = ActionNew.ActionAlias; // root actions - menu.Items.Add(Services.TextService.Localize($"actions/{ActionNew.Instance.Alias}")); - menu.Items.Add(Services.TextService.Localize( - $"actions/{ActionRefresh.Instance.Alias}")); + menu.Items.Add(Services.TextService); + menu.Items.Add(new RefreshNode(Services.TextService)); return menu; } @@ -83,9 +83,9 @@ namespace Umbraco.Web.Trees if (container != null) { //set the default to create - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + menu.DefaultMenuAlias = ActionNew.ActionAlias; - menu.Items.Add(Services.TextService.Localize($"actions/{ActionNew.Instance.Alias}")); + menu.Items.Add(Services.TextService); menu.Items.Add(new MenuItem("rename", Services.TextService.Localize("actions/rename")) { @@ -95,10 +95,9 @@ namespace Umbraco.Web.Trees if (container.HasChildren == false) { //can delete doc type - menu.Items.Add(Services.TextService.Localize($"actions/{ActionDelete.Instance.Alias}")); + menu.Items.Add(Services.TextService); } - menu.Items.Add(Services.TextService.Localize( - $"actions/{ActionRefresh.Instance.Alias}"), hasSeparator: true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); } else { @@ -107,29 +106,28 @@ namespace Umbraco.Web.Trees if (enableInheritedMediaTypes) { - menu.Items.Add(Services.TextService.Localize($"actions/{ActionNew.Instance.Alias}")); + menu.Items.Add(Services.TextService); //no move action if this is a child doc type if (parent == null) { - menu.Items.Add(Services.TextService.Localize($"actions/{ActionMove.Instance.Alias}"), true); + menu.Items.Add(Services.TextService, true); } } else { - menu.Items.Add(Services.TextService.Localize($"actions/{ActionMove.Instance.Alias}")); + menu.Items.Add(Services.TextService); //no move action if this is a child doc type if (parent == null) { - menu.Items.Add(Services.TextService.Localize($"actions/{ActionMove.Instance.Alias}"), true); + menu.Items.Add(Services.TextService, true); } } - menu.Items.Add(Services.TextService.Localize($"actions/{ActionCopy.Instance.Alias}")); - menu.Items.Add(Services.TextService.Localize($"actions/{ActionDelete.Instance.Alias}")); + menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService); if (enableInheritedMediaTypes) - menu.Items.Add(Services.TextService.Localize( - $"actions/{ActionRefresh.Instance.Alias}"), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); } return menu; diff --git a/src/Umbraco.Web/Trees/MemberTreeController.cs b/src/Umbraco.Web/Trees/MemberTreeController.cs index f3ca0c9a02..f8bcb47b56 100644 --- a/src/Umbraco.Web/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web/Trees/MemberTreeController.cs @@ -10,10 +10,11 @@ using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Core.Security; +using Umbraco.Web.Actions; 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; @@ -155,27 +156,32 @@ namespace Umbraco.Web.Trees if (_provider.IsUmbracoMembershipProvider()) { //set default - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + menu.DefaultMenuAlias = ActionNew.ActionAlias; //Create the normal create action - menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)); + menu.Items.Add(Services.TextService); } else { //Create a custom create action - this does not launch a dialog, it just navigates to the create screen // we'll create it based on the ActionNew so it maintains the same icon properties, name, etc... - var createMenuItem = new MenuItem(ActionNew.Instance); + var createMenuItem = new MenuItem + { + Name = Services.TextService.Localize($"actions/{ActionNew.ActionAlias}"), + Alias = ActionNew.ActionAlias, + Icon = "add" + }; //we want to go to this route: /member/member/edit/-1?create=true createMenuItem.NavigateToRoute("/member/member/edit/-1?create=true"); menu.Items.Add(createMenuItem); } - menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } //add delete option for all members - menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)); + menu.Items.Add(Services.TextService); if (Security.CurrentUser.HasAccessToSensitiveData()) { diff --git a/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs b/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs index a710b52595..484ea1e2a9 100644 --- a/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs @@ -2,7 +2,8 @@ using System.Net.Http.Formatting; using Umbraco.Core; using Umbraco.Core.Services; -using Umbraco.Web._Legacy.Actions; +using Umbraco.Web.Actions; + using Umbraco.Web.Models.Trees; namespace Umbraco.Web.Trees @@ -25,14 +26,14 @@ 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(new CreateChildEntity(Services.TextService)); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } else { //delete member type/group - menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)); + menu.Items.Add(Services.TextService); } return menu; diff --git a/src/Umbraco.Web/Trees/PackagesTreeController.cs b/src/Umbraco.Web/Trees/PackagesTreeController.cs index 31f577ad85..8f62047941 100644 --- a/src/Umbraco.Web/Trees/PackagesTreeController.cs +++ b/src/Umbraco.Web/Trees/PackagesTreeController.cs @@ -8,7 +8,8 @@ using Umbraco.Web.WebApi.Filters; using umbraco; using umbraco.cms.businesslogic.packager; using Umbraco.Core.Services; -using Umbraco.Web._Legacy.Actions; +using Umbraco.Web.Actions; + using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -83,21 +84,20 @@ namespace Umbraco.Web.Trees // Root actions if (id == "-1") { - menu.Items.Add(Services.TextService.Localize($"actions/{ActionNew.Instance.Alias}")) + menu.Items.Add(Services.TextService) .ConvertLegacyMenuItem(null, Constants.Trees.Packages, queryStrings.GetValue("application")); } else if (id == "created") { - menu.Items.Add(Services.TextService.Localize($"actions/{ActionNew.Instance.Alias}")) + menu.Items.Add(Services.TextService) .ConvertLegacyMenuItem(null, Constants.Trees.Packages, queryStrings.GetValue("application")); - menu.Items.Add( - Services.TextService.Localize($"actions/{ActionRefresh.Instance.Alias}"), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); } else { //it's a package node - menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)); + menu.Items.Add(Services.TextService); } return menu; diff --git a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs index 4930b4dc5e..ab6e9e2dd7 100644 --- a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs @@ -4,10 +4,11 @@ using System.Net.Http.Formatting; using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi.Filters; using Umbraco.Core; -using Umbraco.Web._Legacy.Actions; + using Umbraco.Core.Services; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; +using Umbraco.Web.Actions; namespace Umbraco.Web.Trees { @@ -24,12 +25,10 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { //Create the normal create action - menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) - //Since we haven't implemented anything for relationtypes in angular, this needs to be converted to - //use the legacy format - .ConvertLegacyMenuItem(null, "initrelationTypes", queryStrings.GetValue("application")); + var addMenuItem = menu.Items.Add(Services.TextService); + addMenuItem.LaunchDialogUrl("developer/RelationTypes/NewRelationType.aspx", "Create New RelationType"); //refresh action - menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } @@ -38,7 +37,7 @@ namespace Umbraco.Web.Trees if (relationType == null) return new MenuItemCollection(); //add delete option for all macros - menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)) + menu.Items.Add(Services.TextService) //Since we haven't implemented anything for relationtypes in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(new EntitySlim diff --git a/src/Umbraco.Web/Trees/TemplatesTreeController.cs b/src/Umbraco.Web/Trees/TemplatesTreeController.cs index 768768f888..3ae45a072e 100644 --- a/src/Umbraco.Web/Trees/TemplatesTreeController.cs +++ b/src/Umbraco.Web/Trees/TemplatesTreeController.cs @@ -8,12 +8,13 @@ using Umbraco.Core; using Umbraco.Core.Services; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; +using Umbraco.Web.Actions; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.Search; using Umbraco.Web.WebApi.Filters; -using Umbraco.Web._Legacy.Actions; + using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Trees @@ -69,13 +70,13 @@ namespace Umbraco.Web.Trees var menu = new MenuItemCollection(); //Create the normal create action - var item = menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)); + var item = menu.Items.Add(Services.TextService); item.NavigateToRoute($"{queryStrings.GetValue("application")}/templates/edit/{id}?create=true"); if (id == Constants.System.Root.ToInvariantString()) { //refresh action - menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } @@ -88,11 +89,11 @@ namespace Umbraco.Web.Trees if (template.IsMasterTemplate == false) { //add delete option if it doesn't have children - menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias), true); + menu.Items.Add(Services.TextService, true); } //add refresh - menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; diff --git a/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs b/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs index e381c7ec0f..479cc20083 100644 --- a/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs +++ b/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs @@ -3,10 +3,11 @@ using System.Linq; using System.Net.Http.Formatting; using Umbraco.Core; using Umbraco.Core.Services; +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 @@ -43,7 +44,7 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { // root actions - menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); + menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } diff --git a/src/Umbraco.Web/Trees/UserTreeController.cs b/src/Umbraco.Web/Trees/UserTreeController.cs index 8ae5b002c6..f029a929de 100644 --- a/src/Umbraco.Web/Trees/UserTreeController.cs +++ b/src/Umbraco.Web/Trees/UserTreeController.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Services; 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 diff --git a/src/Umbraco.Web/TypeLoaderExtensions.cs b/src/Umbraco.Web/TypeLoaderExtensions.cs index 710c342115..4d09783ca9 100644 --- a/src/Umbraco.Web/TypeLoaderExtensions.cs +++ b/src/Umbraco.Web/TypeLoaderExtensions.cs @@ -5,7 +5,7 @@ using Umbraco.Web.Mvc; using Umbraco.Web.Trees; using Umbraco.Web.WebApi; using Umbraco.Core.Composing; -using Umbraco.Web._Legacy.Actions; + namespace Umbraco.Web { @@ -14,15 +14,6 @@ namespace Umbraco.Web /// public static class TypeLoaderExtensions { - /// - /// Returns all available IAction in application - /// - /// - internal static IEnumerable GetActions(this TypeLoader mgr) - { - return mgr.GetTypes(); - } - /// /// Returns all available TreeApiController's in application that are attribute with TreeAttribute /// @@ -43,15 +34,5 @@ namespace Umbraco.Web return mgr.GetTypes(); } - /// - /// Returns all available ISearchableTrees in application - /// - /// - /// - internal static IEnumerable GetSearchableTrees(this TypeLoader mgr) - { - return mgr.GetTypes(); - } - } } diff --git a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs index 30adf2cc3d..9f13939bac 100644 --- a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs +++ b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs @@ -11,9 +11,10 @@ using Umbraco.Core.Exceptions; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Security; +using Umbraco.Web.Actions; using Umbraco.Web.Composing; using Umbraco.Web.Security; -using Umbraco.Web._Legacy.Actions; + namespace Umbraco.Web.UI.Pages { diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 656bbd29c5..f7317939dd 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -428,7 +428,6 @@ - @@ -531,39 +530,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -953,7 +945,6 @@ - @@ -1269,12 +1260,6 @@ NewRelationType.aspx - - RelationTypesWebService.asmx - Component - - - insertMasterpageContent.aspx ASPXCodeBehind @@ -1378,7 +1363,6 @@ ASPXCodeBehind - ASPXCodeBehind diff --git a/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs b/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs index 4d9a6db129..5d71992b74 100644 --- a/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs @@ -5,9 +5,10 @@ using System.Web.Http.Filters; using Umbraco.Core.Exceptions; using Umbraco.Web.Composing; using Umbraco.Web.Editors; -using Umbraco.Web._Legacy.Actions; + using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Web.Actions; namespace Umbraco.Web.WebApi.Filters { @@ -39,7 +40,7 @@ namespace Umbraco.Web.WebApi.Filters { if (string.IsNullOrEmpty(paramName)) throw new ArgumentNullOrEmptyException(nameof(paramName)); _paramName = paramName; - _permissionToCheck = ActionBrowse.Instance.Letter; + _permissionToCheck = ActionBrowse.ActionLetter; } public EnsureUserPermissionForContentAttribute(string paramName, char permissionToCheck) diff --git a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs index 748e0e8a7d..31e0b22ce1 100644 --- a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs @@ -8,7 +8,8 @@ using Umbraco.Core.Services; using Umbraco.Core; using Umbraco.Web.Composing; using Umbraco.Core.Models; -using Umbraco.Web._Legacy.Actions; +using Umbraco.Web.Actions; + namespace Umbraco.Web.WebApi.Filters { @@ -25,7 +26,7 @@ namespace Umbraco.Web.WebApi.Filters public FilterAllowedOutgoingContentAttribute(Type outgoingType) : this(outgoingType, Current.Services.UserService, Current.Services.EntityService) { - _permissionToCheck = ActionBrowse.Instance.Letter; + _permissionToCheck = ActionBrowse.ActionLetter; } public FilterAllowedOutgoingContentAttribute(Type outgoingType, char permissionToCheck) @@ -37,7 +38,7 @@ namespace Umbraco.Web.WebApi.Filters public FilterAllowedOutgoingContentAttribute(Type outgoingType, string propertyName) : this(outgoingType, propertyName, Current.Services.UserService, Current.Services.EntityService) { - _permissionToCheck = ActionBrowse.Instance.Letter; + _permissionToCheck = ActionBrowse.ActionLetter; } public FilterAllowedOutgoingContentAttribute(Type outgoingType, IUserService userService, IEntityService entityService) @@ -45,7 +46,7 @@ namespace Umbraco.Web.WebApi.Filters { _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); - _permissionToCheck = ActionBrowse.Instance.Letter; + _permissionToCheck = ActionBrowse.ActionLetter; } public FilterAllowedOutgoingContentAttribute(Type outgoingType, char permissionToCheck, IUserService userService, IEntityService entityService) @@ -65,7 +66,7 @@ namespace Umbraco.Web.WebApi.Filters _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _userService = userService; _entityService = entityService; - _permissionToCheck = ActionBrowse.Instance.Letter; + _permissionToCheck = ActionBrowse.ActionLetter; } protected override void FilterItems(IUser user, IList items) diff --git a/src/Umbraco.Web/_Legacy/Actions/Action.cs b/src/Umbraco.Web/_Legacy/Actions/Action.cs deleted file mode 100644 index 388a5735fd..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/Action.cs +++ /dev/null @@ -1,191 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text.RegularExpressions; -using Umbraco.Core.Logging; -using Umbraco.Core.Models.Membership; -using Umbraco.Web.Composing; -using Umbraco.Core.Services; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// Actions and Actionhandlers are a key concept to umbraco and a developer whom wish to apply - /// businessrules whenever data is changed within umbraco, by implementing the IActionHandler - /// interface it's possible to invoke methods (foreign to umbraco) - this can be used whenever - /// there is a specific rule which needs to be applied to content. - /// - /// The Action class itself has responsibility for registering actions and actionhandlers, - /// and contains methods which will be invoked whenever a change is made to ex. a document, media or member - /// - /// An action/actionhandler will automatically be registered, using reflection - /// which is enabling thirdparty developers to extend the core functionality of - /// umbraco without changing the codebase. - /// - [Obsolete("Actions and ActionHandlers are obsolete and should no longer be used")] - public class Action - { - private static readonly Dictionary ActionJs = new Dictionary(); - - /// - /// Jacascript for the contextmenu - /// Suggestion: this method should be moved to the presentation layer. - /// - /// - /// String representation - public string ReturnJavascript(string language) - { - return findActions(language); - } - - /// - /// Returns a list of JavaScript file paths. - /// - /// - public static List GetJavaScriptFileReferences() - { - return Current.Actions - .Where(x => !string.IsNullOrWhiteSpace(x.JsSource)) - .Select(x => x.JsSource).ToList(); - //return ActionJsReference; - } - - /// - /// Javascript menuitems - tree contextmenu - /// Umbraco console - /// - /// Suggestion: this method should be moved to the presentation layer. - /// - /// - /// - private static string findActions(string language) - { - if (!ActionJs.ContainsKey(language)) - { - string _actionJsList = ""; - - foreach (IAction action in Current.Actions) - { - // Adding try/catch so this rutine doesn't fail if one of the actions fail - // Add to language JsList - try - { - // NH: Add support for css sprites - string icon = action.Icon; - if (!string.IsNullOrEmpty(icon) && icon.StartsWith(".")) - icon = icon.Substring(1, icon.Length - 1); - else - icon = "images/" + icon; - - _actionJsList += string.Format(",\n\tmenuItem(\"{0}\", \"{1}\", \"{2}\", \"{3}\")", - action.Letter, icon, Current.Services.TextService.Localize("actions/"+ action.Alias, new[] { language }), action.JsFunctionName); - } - catch (Exception ex) - { - Current.Logger.Error(ex, "Error registrering action to javascript"); - } - } - - if (_actionJsList.Length > 0) - _actionJsList = _actionJsList.Substring(2, _actionJsList.Length - 2); - - _actionJsList = "\nvar menuMethods = new Array(\n" + _actionJsList + "\n)\n"; - ActionJs.Add(language, _actionJsList); - } - - return ActionJs[language]; - - } - - internal static List FromEntityPermission(EntityPermission entityPermission) - { - List list = new List(); - foreach (var c in entityPermission.AssignedPermissions.Where(x => x.Length == 1).Select(x => x.ToCharArray()[0])) - { - IAction action = Current.Actions.ToList().Find( - delegate (IAction a) - { - return a.Letter == c; - } - ); - if (action != null) - list.Add(action); - } - return list; - } - - /// - /// Returns a list of IActions that are permission assignable - /// - /// - public static List GetPermissionAssignable() - { - return Current.Actions.ToList().FindAll(x => x.CanBePermissionAssigned); - } - - /// - /// Check if the current IAction is using legacy javascript methods - /// - /// - /// false if the Iaction is incompatible with 4.5 - public static bool ValidateActionJs(IAction action) - { - return !action.JsFunctionName.Contains("+"); - } - - /// - /// Method to convert the old modal calls to the new ones - /// - /// - /// - public static string ConvertLegacyJs(string javascript) - { - MatchCollection tags = - Regex.Matches(javascript, "openModal[^;]*;", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - foreach (Match tag in tags) - { - string[] function = tag.Value.Split(','); - if (function.Length > 0) - { - string newFunction = "UmbClientMgr.openModalWindow" + function[0].Substring(9).Replace("parent.nodeID", "UmbClientMgr.mainTree().getActionNode().nodeId").Replace("nodeID", "UmbClientMgr.mainTree().getActionNode().nodeId").Replace("parent.returnRandom()", "'" + Guid.NewGuid().ToString() + "'"); - newFunction += ", " + function[1]; - newFunction += ", true"; - newFunction += ", " + function[2]; - newFunction += ", " + function[3]; - javascript = javascript.Replace(tag.Value, newFunction); - } - } - - return javascript; - } - } - - /// - /// This class is used to manipulate IActions that are implemented in a wrong way - /// For instance incompatible trees with 4.0 vs 4.5 - /// - public class PlaceboAction : IAction - { - public char Letter { get; set; } - public bool ShowInNotifier { get; set; } - public bool CanBePermissionAssigned { get; set; } - public string Icon { get; set; } - public string Alias { get; set; } - public string JsFunctionName { get; set; } - public string JsSource { get; set; } - - public PlaceboAction() { } - public PlaceboAction(IAction legacyAction) - { - Letter = legacyAction.Letter; - ShowInNotifier = legacyAction.ShowInNotifier; - CanBePermissionAssigned = legacyAction.CanBePermissionAssigned; - Icon = legacyAction.Icon; - Alias = legacyAction.Alias; - JsFunctionName = legacyAction.JsFunctionName; - JsSource = legacyAction.JsSource; - } - } - -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs b/src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs deleted file mode 100644 index 37de1f8e0f..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when a domain is being assigned to a document - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.AdministrationCategory)] - public class ActionAssignDomain : IAction - { - public static ActionAssignDomain Instance { get; } = new ActionAssignDomain(); - - #region IAction Members - - public char Letter - { - get - { - return 'I'; - } - } - - public string JsFunctionName - { - get - { - return null; - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "assignDomain"; - } - } - - public string Icon - { - get - { - return "home"; - } - } - - public bool ShowInNotifier - { - get - { - return false; - } - } - public bool CanBePermissionAssigned - { - get - { - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs b/src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs deleted file mode 100644 index 1425b27917..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs +++ /dev/null @@ -1,65 +0,0 @@ -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.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. - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] - public class ActionBrowse : IAction - { - //create singleton - private static readonly ActionBrowse instance = new ActionBrowse(); - private ActionBrowse() { } - public static ActionBrowse Instance - { - get { return instance; } - } - - #region IAction Members - - public char Letter - { - get { return 'F'; } - } - - public bool ShowInNotifier - { - get { return false; } - } - - public bool CanBePermissionAssigned - { - get { return true; } - } - - public string Icon - { - get { return ""; } - } - - public string Alias - { - get { return "browse"; } - } - - public string JsFunctionName - { - get { return ""; } - } - - public string JsSource - { - get { return ""; } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs b/src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs deleted file mode 100644 index 9c31c172ab..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when the document type of a piece of content is changed - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.AdministrationCategory)] - public class ActionChangeDocType : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionChangeDocType m_instance = new ActionChangeDocType(); -#pragma warning restore 612,618 - - public static ActionChangeDocType Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - - return '7'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionChangeDocType()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - - return null; - } - } - - public string Alias - { - get - { - - return "changeDocType"; - } - } - - public string Icon - { - get - { - - return "axis-rotation-2"; - } - } - - public bool ShowInNotifier - { - get - { - - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs deleted file mode 100644 index 39058d6836..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using LightInject; -using Umbraco.Core.Composing; - -namespace Umbraco.Web._Legacy.Actions -{ - internal class ActionCollectionBuilder : ICollectionBuilder - { - private static Func> _producer; - - // for tests only - does not register the collection - public ActionCollectionBuilder() - { } - - public ActionCollectionBuilder(IServiceContainer container) - { - var collectionLifetime = CollectionLifetime; - - // register the collection - special lifetime - // the lifetime here is custom ResettablePerContainerLifetime which will manage one - // single instance of the collection (much alike PerContainerLifetime) but can be resetted - // to force a new collection to be created. - // this is needed because of the weird things we do during install, where we'd use the - // infamous DirtyBackdoorToConfiguration to reset the ActionResolver way after Resolution - // had frozen. This has been replaced by the possibility here to set the producer at any - // time - but the builder is internal - and all this will be gone eventually. - container.Register(factory => factory.GetInstance().CreateCollection(), collectionLifetime); - } - - public ActionCollection CreateCollection() - { - var actions = new List(); - foreach (var type in _producer()) - { - var getter = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static); - var instance = getter == null - ? Activator.CreateInstance(type) as IAction - : getter.GetValue(null, null) as IAction; - if (instance == null) continue; - actions.Add(instance); - } - return new ActionCollection(actions); - } - - public void SetProducer(Func> producer) - { - _producer = producer; - CollectionLifetime.Reset(); - } - - private ResettablePerContainerLifetime CollectionLifetime { get; } = new ResettablePerContainerLifetime(); - - private class ResettablePerContainerLifetime : ILifetime - { - private object _instance; - - public object GetInstance(Func createInstance, Scope scope) - { - // not dealing with disposable instances, actions are not disposable - return _instance ?? (_instance = createInstance()); - } - - public void Reset() - { - _instance = null; - } - } - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs deleted file mode 100644 index a489f1d280..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when copying a document, media, member - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.StructureCategory)] - public class ActionCopy : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionCopy m_instance = new ActionCopy(); -#pragma warning restore 612,618 - - public static ActionCopy Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - - return 'O'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionCopy()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - - return null; - } - } - - public string Alias - { - get - { - - return "copy"; - } - } - - public string Icon - { - get - { - - return "documents"; - } - } - - public bool ShowInNotifier - { - get - { - - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs deleted file mode 100644 index e00de39aea..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] - public class ActionCreateBlueprintFromContent : IAction - { - private static readonly ActionCreateBlueprintFromContent instance = new ActionCreateBlueprintFromContent(); - - public static ActionCreateBlueprintFromContent Instance - { - get { return instance; } - } - - public char Letter { get; private set; } - public bool ShowInNotifier { get; private set; } - public bool CanBePermissionAssigned { get; private set; } - public string Icon { get; private set; } - public string Alias { get; private set; } - public string JsFunctionName { get; private set; } - public string JsSource { get; private set; } - - public ActionCreateBlueprintFromContent() - { - Letter = 'ï'; - CanBePermissionAssigned = true; - Icon = "blueprint"; - Alias = "createblueprint"; - } - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs b/src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs deleted file mode 100644 index 09ce4d8602..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when a document, media, member is deleted - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] - public class ActionDelete : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionDelete m_instance = new ActionDelete(); -#pragma warning restore 612,618 - - public static ActionDelete Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - return 'D'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionDelete()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "delete"; - } - } - - public string Icon - { - get - { - return "delete"; - } - } - - public bool ShowInNotifier - { - get - { - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionEmptyTranscan.cs b/src/Umbraco.Web/_Legacy/Actions/ActionEmptyTranscan.cs deleted file mode 100644 index 7f8dd6b03c..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionEmptyTranscan.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when the trash can is emptied - /// - public class ActionEmptyTranscan : IAction - { - //create singleton - private static readonly ActionEmptyTranscan InnerInstance = new ActionEmptyTranscan(); - - public static ActionEmptyTranscan Instance - { - get { return InnerInstance; } - } - - #region IAction Members - - public char Letter - { - get - { - return 'N'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionEmptyTranscan()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "emptyRecycleBin"; - } - } - - public string Icon - { - get - { - return "trash"; - } - } - - public bool ShowInNotifier - { - get - { - return false; - } - } - public bool CanBePermissionAssigned - { - get - { - return false; - } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionExport.cs b/src/Umbraco.Web/_Legacy/Actions/ActionExport.cs deleted file mode 100644 index df78026ea0..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionExport.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when exporting a document type - /// - public class ActionExport : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionExport m_instance = new ActionExport(); -#pragma warning restore 612,618 - - public static ActionExport Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - return '9'; - } - } - - public string JsFunctionName - { - get { return ""; } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "export"; - } - } - - public string Icon - { - get - { - return "download-alt"; - } - } - - public bool ShowInNotifier - { - get - { - return false; - } - } - public bool CanBePermissionAssigned - { - get - { - return false; - } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionImport.cs b/src/Umbraco.Web/_Legacy/Actions/ActionImport.cs deleted file mode 100644 index 42947cf36e..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionImport.cs +++ /dev/null @@ -1,77 +0,0 @@ -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when importing a document type - /// - public class ActionImport : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionImport m_instance = new ActionImport(); -#pragma warning restore 612,618 - - public static ActionImport Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - return '8'; - } - } - - public string JsFunctionName - { - get - { - return ""; - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "importDocumentType"; - } - } - - public string Icon - { - get - { - return "page-up"; - } - } - - public bool ShowInNotifier - { - get - { - return false; - } - } - public bool CanBePermissionAssigned - { - get - { - return false; - } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionMove.cs b/src/Umbraco.Web/_Legacy/Actions/ActionMove.cs deleted file mode 100644 index 80aff5736a..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionMove.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked upon creation of a document, media, member - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.StructureCategory)] - public class ActionMove : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionMove m_instance = new ActionMove(); -#pragma warning restore 612,618 - - public static ActionMove Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - - return 'M'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionMove()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - - return null; - } - } - - public string Alias - { - get - { - - return "move"; - } - } - - public string Icon - { - get - { - - return "enter"; - } - } - - public bool ShowInNotifier - { - get - { - - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionNew.cs b/src/Umbraco.Web/_Legacy/Actions/ActionNew.cs deleted file mode 100644 index 72e863e38b..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionNew.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked upon creation of a document - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] - public class ActionNew : IAction - { - public static ActionNew Instance { get; } = new ActionNew(); - - #region IAction Members - - public char Letter - { - get - { - return 'C'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionNew()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "create"; - } - } - - public string Icon - { - get - { - return "add"; - } - } - - public bool ShowInNotifier - { - get - { - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - return true; - } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionNotify.cs b/src/Umbraco.Web/_Legacy/Actions/ActionNotify.cs deleted file mode 100644 index ef281eecbe..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionNotify.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when a notification is sent - /// - public class ActionNotify : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionNotify m_instance = new ActionNotify(); -#pragma warning restore 612,618 - - public static ActionNotify Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - - return 'T'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionNotify()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - - return null; - } - } - - public string Alias - { - get - { - return "notify"; - } - } - - public string Icon - { - get - { - return "megaphone"; - } - } - - public bool ShowInNotifier - { - get - { - return false; - } - } - public bool CanBePermissionAssigned - { - get - { - return false; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionNull.cs b/src/Umbraco.Web/_Legacy/Actions/ActionNull.cs deleted file mode 100644 index 78c5175fb6..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionNull.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This permission is assigned to a node when there are no permissions assigned to the node. - /// This is used internally to assign no permissions to a node for a user and shouldn't be used in code. - /// - public class ActionNull : IAction - { - //create singleton - private static readonly ActionNull instance = new ActionNull(); - private ActionNull() { } - public static ActionNull Instance - { - get { return instance; } - } - - #region IAction Members - - public char Letter - { - get { return '-'; } - } - - public bool ShowInNotifier - { - get { return false; } - } - - public bool CanBePermissionAssigned - { - get { return false; } - } - - public string Icon - { - get { return string.Empty; } - } - - public string Alias - { - get { return string.Empty; } - } - - public string JsFunctionName - { - get { return string.Empty; } - } - - public string JsSource - { - get { return string.Empty; } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionPackage.cs b/src/Umbraco.Web/_Legacy/Actions/ActionPackage.cs deleted file mode 100644 index 832e691b48..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionPackage.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked upon creation of a document, media, member - /// - public class ActionPackage : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionPackage m_instance = new ActionPackage(); -#pragma warning restore 612,618 - - public static ActionPackage Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - return 'X'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionPackage()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - return ""; - } - } - - public string Alias - { - get - { - return "importPackage"; - } - } - - public string Icon - { - get - { - return "gift"; - } - } - - public bool ShowInNotifier - { - get - { - return false; - } - } - public bool CanBePermissionAssigned - { - get - { - return false; - } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionPackageCreate.cs b/src/Umbraco.Web/_Legacy/Actions/ActionPackageCreate.cs deleted file mode 100644 index f0ccb03d8e..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionPackageCreate.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked upon creation of a document, media, member - /// - public class ActionPackageCreate : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionPackageCreate m_instance = new ActionPackageCreate(); -#pragma warning restore 612,618 - - public static ActionPackageCreate Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - return 'Y'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionPackageCreate()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "createPackage"; - } - } - - public string Icon - { - get - { - return "gift"; - } - } - - public bool ShowInNotifier - { - get - { - return false; - } - } - public bool CanBePermissionAssigned - { - get - { - return false; - } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs b/src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs deleted file mode 100644 index 357dfe89a4..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when a document is protected or unprotected - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.AdministrationCategory)] - public class ActionProtect : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionProtect m_instance = new ActionProtect(); -#pragma warning restore 612,618 - - public static ActionProtect Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - - return 'P'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionProtect()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - - return null; - } - } - - public string Alias - { - get - { - - return "protect"; - } - } - - public string Icon - { - get - { - - return "lock"; - } - } - - public bool ShowInNotifier - { - get - { - - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs b/src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs deleted file mode 100644 index 6b54873c43..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when a document is being published - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] - public class ActionPublish : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionPublish m_instance = new ActionPublish(); -#pragma warning restore 612,618 - - public static ActionPublish Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - return 'U'; - } - } - - public string JsFunctionName - { - get - { - return string.Empty; - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "publish"; - } - } - - public string Icon - { - get - { - return string.Empty; - } - } - - public bool ShowInNotifier - { - get - { - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRePublish.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRePublish.cs deleted file mode 100644 index b78af779e4..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRePublish.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when all documents are being republished - /// - public class ActionRePublish : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionRePublish m_instance = new ActionRePublish(); -#pragma warning restore 612,618 - - public static ActionRePublish Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - return 'B'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionRePublish()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "republish"; - } - } - - public string Icon - { - get - { - return "globe"; - } - } - - public bool ShowInNotifier - { - get - { - return false; - } - } - public bool CanBePermissionAssigned - { - get - { - return false; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRefresh.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRefresh.cs deleted file mode 100644 index 07133b4030..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRefresh.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when a node reloads its children - /// Concerns only the tree itself and thus you should not handle - /// this action from without umbraco. - /// - [LegacyActionMenuItem("umbracoMenuActions", "RefreshNode")] - public class ActionRefresh : IAction - { - //create singleton - private static readonly ActionRefresh InnerInstance = new ActionRefresh(); - - public static ActionRefresh Instance - { - get { return InnerInstance; } - } - - #region IAction Members - - public char Letter - { - get - { - - return 'L'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionRefresh()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - - return null; - } - } - - public string Alias - { - get - { - - return "refreshNode"; - } - } - - public string Icon - { - get - { - - return "refresh"; - } - } - - public bool ShowInNotifier - { - get - { - - return false; - } - } - public bool CanBePermissionAssigned - { - get - { - - return false; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRestore.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRestore.cs deleted file mode 100644 index da70eb1409..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRestore.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when the content/media item is to be restored from the recycle bin - /// - public class ActionRestore : IAction - { - //create singleton - - private ActionRestore() { } - - public static ActionRestore Instance { get; } = new ActionRestore(); - - #region IAction Members - - public char Letter => 'V'; - - public string JsFunctionName => null; - - public string JsSource => null; - - public string Alias => "restore"; - - public string Icon => "undo"; - - public bool ShowInNotifier => true; - - public bool CanBePermissionAssigned => false; - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRights.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRights.cs deleted file mode 100644 index e1ee74e61c..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRights.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when rights are changed on a document - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] - public class ActionRights : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionRights m_instance = new ActionRights(); -#pragma warning restore 612,618 - - public static ActionRights Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - - return 'R'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionRights()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - - return null; - } - } - - public string Alias - { - get - { - - return "rights"; - } - } - - public string Icon - { - get - { - - return "vcard"; - } - } - - public bool ShowInNotifier - { - get - { - - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs deleted file mode 100644 index 59044666f7..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when copying a document is being rolled back - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.AdministrationCategory)] - public class ActionRollback : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionRollback m_instance = new ActionRollback(); -#pragma warning restore 612,618 - - public static ActionRollback Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - - return 'K'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionRollback()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - return ""; - } - } - - public string Alias - { - get - { - - return "rollback"; - } - } - - public string Icon - { - get - { - - return "undo"; - } - } - - public bool ShowInNotifier - { - get - { - - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionSort.cs b/src/Umbraco.Web/_Legacy/Actions/ActionSort.cs deleted file mode 100644 index b813dcbc8c..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionSort.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when children to a document, media, member is being sorted - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.StructureCategory)] - public class ActionSort : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionSort m_instance = new ActionSort(); -#pragma warning restore 612,618 - - public static ActionSort Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - - return 'S'; - } - } - - public string JsFunctionName - { - get - { - return null; - } - } - - public string JsSource - { - get - { - - return null; - } - } - - public string Alias - { - get - { - - return "sort"; - } - } - - public string Icon - { - get - { - - return "navigation-vertical"; - } - } - - public bool ShowInNotifier - { - get - { - - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs b/src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs deleted file mode 100644 index ff471bc198..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when children to a document is being sent to published (by an editor without publishrights) - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] - public class ActionToPublish : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionToPublish m_instance = new ActionToPublish(); -#pragma warning restore 612,618 - - public static ActionToPublish Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - return 'H'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionToPublish()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "sendtopublish"; - } - } - - public string Icon - { - get - { - return "outbox"; - } - } - - public bool ShowInNotifier - { - get - { - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - //SD: Changed this to true so that any user may be able to perform this action, not just a writer - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs b/src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs deleted file mode 100644 index 0cc5120fd0..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when a translation occurs - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.AdministrationCategory)] - public class ActionTranslate : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionTranslate m_instance = new ActionTranslate(); -#pragma warning restore 612,618 - - public static ActionTranslate Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - return '4'; - } - } - - public string JsFunctionName - { - get - { - return ""; - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "translate"; - } - } - - public string Icon - { - get - { - return "comments"; - } - } - - public bool ShowInNotifier - { - get - { - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - return true; - } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionUnPublish.cs b/src/Umbraco.Web/_Legacy/Actions/ActionUnPublish.cs deleted file mode 100644 index a61b805859..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionUnPublish.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - - /// - /// This action is invoked when a document is being unpublished - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] - public class ActionUnpublish : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionUnpublish m_instance = new ActionUnpublish(); -#pragma warning restore 612,618 - - public static ActionUnpublish Instance => m_instance; - - public char Letter => 'Z'; - public string JsFunctionName => ""; - public string JsSource => null; - public string Alias => "unpublish"; - public string Icon => "circle-dotted"; - public bool ShowInNotifier => false; - public bool CanBePermissionAssigned => true; - } - -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs b/src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs deleted file mode 100644 index 15458e83ad..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using Umbraco.Web.UI.Pages; -using Umbraco.Core; -using Umbraco.Core.CodeAnnotations; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// This action is invoked when copying a document or media - /// - [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] - public class ActionUpdate : IAction - { - //create singleton -#pragma warning disable 612,618 - private static readonly ActionUpdate m_instance = new ActionUpdate(); -#pragma warning restore 612,618 - - public static ActionUpdate Instance - { - get { return m_instance; } - } - - #region IAction Members - - public char Letter - { - get - { - return 'A'; - } - } - - public string JsFunctionName - { - get - { - return string.Format("{0}.actionUpdate()", ClientTools.Scripts.GetAppActions); - } - } - - public string JsSource - { - get - { - return null; - } - } - - public string Alias - { - get - { - return "update"; - } - } - - public string Icon - { - get - { - return "save"; - } - } - - public bool ShowInNotifier - { - get - { - return true; - } - } - public bool CanBePermissionAssigned - { - get - { - return true; - } - } - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/ContextMenuSeperator.cs b/src/Umbraco.Web/_Legacy/Actions/ContextMenuSeperator.cs deleted file mode 100644 index 2c66932a04..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/ContextMenuSeperator.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// Used simply to define context menu seperator items. - /// This should not be used directly in any code except for creating menus. - /// - public class ContextMenuSeperator : IAction - { - //create singleton - private static readonly ContextMenuSeperator instance = new ContextMenuSeperator(); - private ContextMenuSeperator() { } - public static ContextMenuSeperator Instance - { - get { return instance; } - } - - #region IAction Members - - public char Letter - { - get { return ','; } - } - - public string JsFunctionName - { - get { return string.Empty; } - } - public string JsSource - { - get { return string.Empty; } - } - public string Alias - { - get { return string.Empty; } - } - public string Icon - { - get { return string.Empty; } - } - public bool ShowInNotifier - { - get { return false; } - } - public bool CanBePermissionAssigned - { - get { return false; } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/IAction.cs b/src/Umbraco.Web/_Legacy/Actions/IAction.cs deleted file mode 100644 index 410a407517..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/IAction.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Umbraco.Core.Composing; - -namespace Umbraco.Web._Legacy.Actions -{ - public interface IAction : IDiscoverable - { - char Letter { get; } - bool ShowInNotifier { get; } - bool CanBePermissionAssigned { get; } - string Icon { get; } - string Alias { get; } - string JsFunctionName { get; } - /// - /// A path to a supporting JavaScript file for the IAction. A script tag will be rendered out with the reference to the JavaScript file. - /// - string JsSource { get; } - } -} diff --git a/src/Umbraco.Web/_Legacy/Actions/LegacyActionMenuItemAttribute.cs b/src/Umbraco.Web/_Legacy/Actions/LegacyActionMenuItemAttribute.cs deleted file mode 100644 index ca9ace9630..0000000000 --- a/src/Umbraco.Web/_Legacy/Actions/LegacyActionMenuItemAttribute.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using Umbraco.Core; -using Umbraco.Core.Exceptions; - -namespace Umbraco.Web._Legacy.Actions -{ - /// - /// The attribute to assign to any IAction objects. - /// - /// - /// This is purely used for compatibility reasons for old IActions used in v7 that haven't been upgraded to - /// the new format. - /// - [AttributeUsage(AttributeTargets.Class)] - internal sealed class LegacyActionMenuItemAttribute : Attribute - { - /// - /// This constructor defines both the angular service and method name to use - /// - /// - /// - public LegacyActionMenuItemAttribute(string serviceName, string methodName) - { - if (string.IsNullOrEmpty(serviceName)) throw new ArgumentNullOrEmptyException(nameof(serviceName)); - if (string.IsNullOrEmpty(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 LegacyActionMenuItemAttribute(string serviceName) - { - if (string.IsNullOrEmpty(serviceName)) throw new ArgumentNullOrEmptyException(nameof(serviceName)); - - MethodName = ""; - ServiceName = serviceName; - } - - public string MethodName { get; } - public string ServiceName { get; } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/RelationTypesWebService.asmx b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/RelationTypesWebService.asmx deleted file mode 100644 index 160745ca2d..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/RelationTypesWebService.asmx +++ /dev/null @@ -1 +0,0 @@ -<%@ WebService Language="C#" CodeBehind="RelationTypesWebService.asmx.cs" Class="umbraco.cms.presentation.developer.RelationTypes.RelationTypesWebService" %> diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/RelationTypesWebService.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/RelationTypesWebService.asmx.cs deleted file mode 100644 index 0f8ca29c94..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/RelationTypesWebService.asmx.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Web.Services; -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Web; -using Umbraco.Web.Composing; - -namespace umbraco.cms.presentation.developer.RelationTypes -{ - /// - /// Webservice to delete relation types, this allows deletion via a javacscript call hooked into the tree UI - /// - [WebService(Namespace = "http://tempuri.org/")] - [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] - [System.ComponentModel.ToolboxItem(false)] - [System.Web.Script.Services.ScriptService] // Allows this Web Service to be called from script, using ASP.NET AJAX - public class RelationTypesWebService : WebService - { - /// - /// Delete an Umbraco RelationType and all it's associated Relations - /// - /// database id of the relation type to delete - [WebMethod] - public void DeleteRelationType(int relationTypeId) - { - var user = UmbracoContext.Current.Security.CurrentUser; - - if (user.IsAdmin()) - { - var relationService = Current.Services.RelationService; - var relationType = relationService.GetRelationTypeById(relationTypeId); - relationService.Delete(relationType); - } - } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.cs deleted file mode 100644 index cf39b17e55..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Umbraco.Web._Legacy.Actions; - -namespace umbraco.cms.presentation.developer.RelationTypes.TreeMenu -{ - /// - /// Delete a Relation Type - an Umbraco tree context menu action - /// - public class ActionDeleteRelationType : IAction - { - /// - /// Private field for the singleton instance - /// - private static readonly ActionDeleteRelationType instance = new ActionDeleteRelationType(); - - /// - /// Gets a singleton instance of this action - /// - public static ActionDeleteRelationType Instance - { - get { return instance; } - } - - #region IAction Members - - /// - /// Gets a string alias used to identify this action - /// - public string Alias - { - get { return "delete"; } - } - - /// - /// Gets a unique char to associate with this action - /// - public char Letter - { - get { return '¤'; } - } - - /// - /// Gets a value indicating whether the Umbraco notification area is used ? - /// - public bool ShowInNotifier - { - get { return false; } - } - - /// - /// Gets a value indicating whether this action can be configured for use only by specific members - /// - public bool CanBePermissionAssigned - { - get { return false; } // Since this tree is in the developer section, no further granular permissions are required - } - - /// - /// Gets an icon to be used for the right click action - /// - public string Icon - { - get { return "delete"; } // delete refers to an existing sprite - } - - /// - /// Gets a string for the javascript source - /// - public string JsSource - { - get { return "developer/RelationTypes/TreeMenu/ActionDeleteRelationType.js"; } - } - - /// - /// Gets a javascript string to execute when this action is fired - /// - public string JsFunctionName - { - get { return "javascript:actionDeleteRelationType(UmbClientMgr.mainTree().getActionNode().nodeId,UmbClientMgr.mainTree().getActionNode().nodeName);"; } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.cs deleted file mode 100644 index 6018539983..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Umbraco.Web._Legacy.Actions; - -namespace umbraco.cms.presentation.developer.RelationTypes.TreeMenu -{ - /// - /// Create new Relation Type - an Umbraco tree context menu action - /// - public class ActionNewRelationType : IAction - { - /// - /// Private field for the singleton instance - /// - private static readonly ActionNewRelationType instance = new ActionNewRelationType(); - - /// - /// Gets a singleton instance of this action - /// - public static ActionNewRelationType Instance - { - get { return instance; } - } - - #region IAction Members - - /// - /// Gets a string alias used to identify this action - /// - public string Alias - { - get { return "create"; } - } - - /// - /// Gets a unique char to associate with this action - /// - public char Letter - { - get { return '®'; } - } - - /// - /// Gets a value indicating whether the Umbraco notification area is used ? - /// - public bool ShowInNotifier - { - get { return false; } - } - - /// - /// Gets a value indicating whether this action can be configured for use only by specific members - /// - public bool CanBePermissionAssigned - { - get { return false; } // Since this tree is in the developer section, no further granular permissions are required - } - - /// - /// Gets an icon to be used for the right click action - /// - public string Icon - { - get { return "add"; } // add refers to an existing sprite - } - - /// - /// Gets a string for the javascript source - /// - public string JsSource - { - get { return "developer/RelationTypes/TreeMenu/ActionNewRelationType.js"; } - } - - /// - /// Gets a javascript string to execute when this action is fired - /// - public string JsFunctionName - { - get { return "javascript:actionNewRelationType();"; } - } - - #endregion - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/SendPublish.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/SendPublish.aspx.cs index 727af897ca..1f4ba277b5 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/SendPublish.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/SendPublish.aspx.cs @@ -1,7 +1,9 @@ using System; using Umbraco.Web; using Umbraco.Core; -using Umbraco.Web._Legacy.Actions; +using Umbraco.Web.Actions; +using Umbraco.Web.Composing; + namespace umbraco.dialogs { @@ -25,7 +27,7 @@ namespace umbraco.dialogs { //send notifications! TODO: This should be put somewhere centralized instead of hard coded directly here Services.NotificationService.SendNotification( - Services.ContentService.GetById(docId), ActionToPublish.Instance); + Services.ContentService.GetById(docId), Current.Actions.GetAction()); } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/Item.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/Item.cs index 89a03a1437..8473341ca8 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/Item.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/Item.cs @@ -11,9 +11,10 @@ using Umbraco.Core.Services; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web; +using Umbraco.Web.Actions; using Umbraco.Web.Composing; using Umbraco.Web.Macros; -using Umbraco.Web._Legacy.Actions; + namespace umbraco.presentation.templateControls { @@ -276,7 +277,7 @@ namespace umbraco.presentation.templateControls if (u == null) return false; var permission = Current.Services.UserService.GetPermissions(u, PageElements["path"].ToString()); - return permission.AssignedPermissions.Contains(ActionUpdate.Instance.Letter.ToString(CultureInfo.InvariantCulture), StringComparer.Ordinal); + return permission.AssignedPermissions.Contains(ActionUpdate.ActionLetter.ToString(CultureInfo.InvariantCulture), StringComparer.Ordinal); } #endregion diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs index f82587a413..5e0cb289f0 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs @@ -9,8 +9,9 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Web; +using Umbraco.Web.Actions; using Umbraco.Web.Composing; -using Umbraco.Web._Legacy.Actions; + namespace umbraco.presentation.webservices { @@ -186,7 +187,7 @@ namespace umbraco.presentation.webservices //send notifications! TODO: This should be put somewhere centralized instead of hard coded directly here if (parentId > 0) { - Services.NotificationService.SendNotification(contentService.GetById(parentId), ActionSort.Instance, UmbracoContext, Services.TextService, GlobalSettings); + Services.NotificationService.SendNotification(contentService.GetById(parentId), Current.Actions.GetAction(), UmbracoContext, Services.TextService, GlobalSettings); } } From cb9843b023ce9ef3afbd58b3973ed76c0bc73b35 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 29 Oct 2018 23:23:21 +1100 Subject: [PATCH 07/16] Removes IActions that shouldn't be IActions --- src/Umbraco.Web/Actions/ActionCollection.cs | 2 +- .../Actions/ActionCollectionBuilder.cs | 13 +++++++++++ .../Actions/ActionEmptyTranscan.cs | 16 ------------- src/Umbraco.Web/Actions/ActionExport.cs | 15 ------------ src/Umbraco.Web/Actions/ActionImport.cs | 15 ------------ src/Umbraco.Web/Actions/ActionNotify.cs | 16 ------------- src/Umbraco.Web/Actions/ActionRePublish.cs | 16 ------------- src/Umbraco.Web/Actions/ActionRefresh.cs | 23 ------------------- .../Models/Trees/ActionMenuItem.cs | 15 +++++++++--- .../Models/Trees/CreateChildEntity.cs | 5 ++-- src/Umbraco.Web/Models/Trees/ExportMember.cs | 9 +++++++- src/Umbraco.Web/Models/Trees/MenuItem.cs | 8 +++++++ src/Umbraco.Web/Models/Trees/MenuItemList.cs | 22 ------------------ src/Umbraco.Web/Models/Trees/RefreshNode.cs | 6 ++--- .../Trees/ContentTreeController.cs | 8 +++++-- .../Trees/ContentTreeControllerBase.cs | 5 +++- .../Trees/ContentTypeTreeController.cs | 12 ++++++++-- src/Umbraco.Web/Trees/MemberTreeController.cs | 7 +----- src/Umbraco.Web/Umbraco.Web.csproj | 6 ----- 19 files changed, 67 insertions(+), 152 deletions(-) delete mode 100644 src/Umbraco.Web/Actions/ActionEmptyTranscan.cs delete mode 100644 src/Umbraco.Web/Actions/ActionExport.cs delete mode 100644 src/Umbraco.Web/Actions/ActionImport.cs delete mode 100644 src/Umbraco.Web/Actions/ActionNotify.cs delete mode 100644 src/Umbraco.Web/Actions/ActionRePublish.cs delete mode 100644 src/Umbraco.Web/Actions/ActionRefresh.cs diff --git a/src/Umbraco.Web/Actions/ActionCollection.cs b/src/Umbraco.Web/Actions/ActionCollection.cs index 70a3b67b02..64cf950c60 100644 --- a/src/Umbraco.Web/Actions/ActionCollection.cs +++ b/src/Umbraco.Web/Actions/ActionCollection.cs @@ -17,7 +17,7 @@ namespace Umbraco.Web.Actions internal T GetAction() where T : IAction { - return this.OfType().SingleOrDefault(); + return this.OfType().FirstOrDefault(); } internal IEnumerable GetByLetters(IEnumerable letters) diff --git a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs index 71b1ef48a5..6002c8d2b0 100644 --- a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs +++ b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using LightInject; using Umbraco.Core.Composing; @@ -14,5 +15,17 @@ namespace Umbraco.Web.Actions { } 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/ActionEmptyTranscan.cs b/src/Umbraco.Web/Actions/ActionEmptyTranscan.cs deleted file mode 100644 index db70e2d2b2..0000000000 --- a/src/Umbraco.Web/Actions/ActionEmptyTranscan.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Umbraco.Web.UI.Pages; - - -namespace Umbraco.Web.Actions -{ - //fixme: not needed, remove this - public class ActionEmptyTranscan : IAction - { - public char Letter => 'N'; - public string Alias => "emptyRecycleBin"; - public string Category => null; - public string Icon => "trash"; - public bool ShowInNotifier => false; - public bool CanBePermissionAssigned => false; - } -} diff --git a/src/Umbraco.Web/Actions/ActionExport.cs b/src/Umbraco.Web/Actions/ActionExport.cs deleted file mode 100644 index 8843bee5ea..0000000000 --- a/src/Umbraco.Web/Actions/ActionExport.cs +++ /dev/null @@ -1,15 +0,0 @@ - - -namespace Umbraco.Web.Actions -{ - //fixme: not needed, remove this - public class ActionExport : IAction - { - public char Letter => '9'; - public string Alias => "export"; - public string Category => null; - public string Icon => "download-alt"; - public bool ShowInNotifier => false; - public bool CanBePermissionAssigned => false; - } -} diff --git a/src/Umbraco.Web/Actions/ActionImport.cs b/src/Umbraco.Web/Actions/ActionImport.cs deleted file mode 100644 index 1cd8682735..0000000000 --- a/src/Umbraco.Web/Actions/ActionImport.cs +++ /dev/null @@ -1,15 +0,0 @@ - - -namespace Umbraco.Web.Actions -{ - //fixme: not needed, remove this - public class ActionImport : IAction - { - public char Letter => '8'; - public string Alias => "importDocumentType"; - public string Category => null; - public string Icon => "page-up"; - public bool ShowInNotifier => false; - public bool CanBePermissionAssigned => false; - } -} diff --git a/src/Umbraco.Web/Actions/ActionNotify.cs b/src/Umbraco.Web/Actions/ActionNotify.cs deleted file mode 100644 index 218345a678..0000000000 --- a/src/Umbraco.Web/Actions/ActionNotify.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Umbraco.Web.UI.Pages; - - -namespace Umbraco.Web.Actions -{ - //fixme: not needed, remove this - public class ActionNotify : IAction - { - public char Letter => 'T'; - public string Alias => "notify"; - public string Category => null; - public string Icon => "megaphone"; - public bool ShowInNotifier => false; - public bool CanBePermissionAssigned => false; - } -} diff --git a/src/Umbraco.Web/Actions/ActionRePublish.cs b/src/Umbraco.Web/Actions/ActionRePublish.cs deleted file mode 100644 index c0af369370..0000000000 --- a/src/Umbraco.Web/Actions/ActionRePublish.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Umbraco.Web.UI.Pages; - - -namespace Umbraco.Web.Actions -{ - //fixme: not needed, remove this - public class ActionRePublish : IAction - { - public char Letter => 'B'; - public string Alias => "republish"; - public string Category => null; - public string Icon => "globe"; - public bool ShowInNotifier => false; - public bool CanBePermissionAssigned => false; - } -} diff --git a/src/Umbraco.Web/Actions/ActionRefresh.cs b/src/Umbraco.Web/Actions/ActionRefresh.cs deleted file mode 100644 index 38247f4e4b..0000000000 --- a/src/Umbraco.Web/Actions/ActionRefresh.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Umbraco.Web.Models.Trees; -using Umbraco.Web.UI.Pages; - - -namespace Umbraco.Web.Actions -{ - ///// - ///// This action is invoked when a node reloads its children - ///// Concerns only the tree itself and thus you should not handle - ///// this action from without umbraco. - ///// - //public class ActionRefresh : IAction - //{ - // public static string ActionAlias => "refreshNode"; - - // public char Letter => 'L'; - // public string Alias => ActionAlias; - // public string Icon => "refresh"; - // public bool ShowInNotifier => false; - // public bool CanBePermissionAssigned => false; - // public string Category => null; - //} -} diff --git a/src/Umbraco.Web/Models/Trees/ActionMenuItem.cs b/src/Umbraco.Web/Models/Trees/ActionMenuItem.cs index ed15b82b16..9354417155 100644 --- a/src/Umbraco.Web/Models/Trees/ActionMenuItem.cs +++ b/src/Umbraco.Web/Models/Trees/ActionMenuItem.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics.CodeAnalysis; using Umbraco.Core; +using Umbraco.Core.Services; namespace Umbraco.Web.Models.Trees { @@ -28,9 +29,17 @@ namespace Umbraco.Web.Models.Trees /// public virtual string AngularServiceMethodName { get; } = null; - [SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")] - protected ActionMenuItem() - : base() + 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 (AngularServiceMethodName.IsNullOrWhiteSpace()) diff --git a/src/Umbraco.Web/Models/Trees/CreateChildEntity.cs b/src/Umbraco.Web/Models/Trees/CreateChildEntity.cs index 90d0e9e1cb..022056c35d 100644 --- a/src/Umbraco.Web/Models/Trees/CreateChildEntity.cs +++ b/src/Umbraco.Web/Models/Trees/CreateChildEntity.cs @@ -11,17 +11,16 @@ namespace Umbraco.Web.Models.Trees public override string AngularServiceName => "umbracoMenuActions"; public CreateChildEntity(string name, bool seperatorBefore = false) + : base(ActionNew.ActionAlias, name) { - Alias = ActionNew.ActionAlias; Icon = "add"; Name = name; SeperatorBefore = seperatorBefore; } public CreateChildEntity(ILocalizedTextService textService, bool seperatorBefore = false) + : base(ActionNew.ActionAlias, textService) { - Alias = ActionNew.ActionAlias; Icon = "add"; - Name = textService.Localize($"actions/{Alias}"); SeperatorBefore = seperatorBefore; } } diff --git a/src/Umbraco.Web/Models/Trees/ExportMember.cs b/src/Umbraco.Web/Models/Trees/ExportMember.cs index 5f3eaebd45..558f7c1fa1 100644 --- a/src/Umbraco.Web/Models/Trees/ExportMember.cs +++ b/src/Umbraco.Web/Models/Trees/ExportMember.cs @@ -1,4 +1,6 @@ -namespace Umbraco.Web.Models.Trees +using Umbraco.Core.Services; + +namespace Umbraco.Web.Models.Trees { /// /// Represents the export member menu item @@ -6,5 +8,10 @@ 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 fb586e02d6..3e8a43e03e 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItem.cs +++ b/src/Umbraco.Web/Models/Trees/MenuItem.cs @@ -31,6 +31,14 @@ namespace Umbraco.Web.Models.Trees Name = name; } + + public MenuItem(string alias, ILocalizedTextService textService) + : this() + { + Alias = alias; + Name = textService.Localize($"actions/{Alias}"); + } + /// /// Create a menu item based on an definition /// diff --git a/src/Umbraco.Web/Models/Trees/MenuItemList.cs b/src/Umbraco.Web/Models/Trees/MenuItemList.cs index 1a8a2dd88c..672750825c 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItemList.cs +++ b/src/Umbraco.Web/Models/Trees/MenuItemList.cs @@ -38,28 +38,6 @@ namespace Umbraco.Web.Models.Trees return item; } - /// - /// Adds a menu item based on an - /// - /// 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); - } - - /// - /// Adds a menu item based on an - /// - /// The used to localize the action name based on it's alias - /// - public MenuItem Add(ILocalizedTextService textService) - where T : IAction - { - return Add(textService, false); - } - /// /// Adds a menu item with a dictionary which is merged to the AdditionalData bag /// diff --git a/src/Umbraco.Web/Models/Trees/RefreshNode.cs b/src/Umbraco.Web/Models/Trees/RefreshNode.cs index 587c51b887..2641baa34f 100644 --- a/src/Umbraco.Web/Models/Trees/RefreshNode.cs +++ b/src/Umbraco.Web/Models/Trees/RefreshNode.cs @@ -11,18 +11,16 @@ namespace Umbraco.Web.Models.Trees public override string AngularServiceName => "umbracoMenuActions"; public RefreshNode(string name, bool seperatorBefore = false) + : base("refreshNode", name) { - Alias = "refreshNode"; Icon = "refresh"; - Name = name; SeperatorBefore = seperatorBefore; } public RefreshNode(ILocalizedTextService textService, bool seperatorBefore = false) + : base("refreshNode", textService) { - Alias = "refreshNode"; Icon = "refresh"; - Name = textService.Localize($"actions/{Alias}"); SeperatorBefore = seperatorBefore; } } diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index a759382854..a7598e5d3a 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -240,8 +240,12 @@ namespace Umbraco.Web.Trees AddActionNode(item, menu); AddActionNode(item, menu); AddActionNode(item, menu, true, true); - - AddActionNode(item, menu, true); + + menu.Items.Add(new MenuItem("notify", Services.TextService) + { + Icon = "megaphone", + SeperatorBefore = true + }); menu.Items.Add(new RefreshNode(Services.TextService, true)); diff --git a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs index c02f691f14..1398903cfc 100644 --- a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs @@ -349,7 +349,10 @@ namespace Umbraco.Web.Trees if (RecycleBinId.ToInvariantString() == id) { var menu = new MenuItemCollection(); - menu.Items.Add(Services.TextService.Localize("actions/emptyTrashcan")); + menu.Items.Add(new MenuItem("emptyRecycleBin", Services.TextService) + { + Icon = "trash" + }); menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } diff --git a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs index 673c5f4168..32367ad02c 100644 --- a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs @@ -82,7 +82,11 @@ namespace Umbraco.Web.Trees // root actions menu.Items.Add(Services.TextService); - menu.Items.Add(Services.TextService, true); + menu.Items.Add(new MenuItem("importDocumentType", Services.TextService) + { + Icon = "page-up", + SeperatorBefore = true + }); menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; @@ -123,7 +127,11 @@ namespace Umbraco.Web.Trees menu.Items.Add(Services.TextService, true); } menu.Items.Add(Services.TextService); - menu.Items.Add(Services.TextService, true); + menu.Items.Add(new MenuItem("export", Services.TextService) + { + Icon = "download-alt", + SeperatorBefore = true + }); menu.Items.Add(Services.TextService, true); if (enableInheritedDocumentTypes) menu.Items.Add(new RefreshNode(Services.TextService, true)); diff --git a/src/Umbraco.Web/Trees/MemberTreeController.cs b/src/Umbraco.Web/Trees/MemberTreeController.cs index f8bcb47b56..24fc624110 100644 --- a/src/Umbraco.Web/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web/Trees/MemberTreeController.cs @@ -185,12 +185,7 @@ namespace Umbraco.Web.Trees if (Security.CurrentUser.HasAccessToSensitiveData()) { - menu.Items.Add(new ExportMember - { - Name = Services.TextService.Localize("actions/export"), - Icon = "download-alt", - Alias = "export" - }); + menu.Items.Add(new ExportMember(Services.TextService)); } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index f7317939dd..ff48b7ab9e 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -538,16 +538,10 @@ - - - - - - From 77f4f0bbad2622a495c6674cb7983ae6a2d56753 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 30 Oct 2018 00:34:43 +1100 Subject: [PATCH 08/16] Refactors how the 'OpensDialog' gets assigned to menu items, fixes permission check on rollback --- src/Umbraco.Web/Actions/ActionRollback.cs | 4 +- src/Umbraco.Web/Editors/ContentController.cs | 1 + src/Umbraco.Web/Models/Trees/MenuItem.cs | 4 +- src/Umbraco.Web/Models/Trees/MenuItemList.cs | 8 ++-- .../Trees/ContentBlueprintTreeController.cs | 6 +-- .../Trees/ContentTreeController.cs | 37 +++++++++---------- .../Trees/ContentTreeControllerBase.cs | 3 +- .../Trees/ContentTypeTreeController.cs | 22 ++++++----- .../Trees/DataTypeTreeController.cs | 10 ++--- .../Trees/DictionaryTreeController.cs | 4 +- .../Trees/FileSystemTreeController.cs | 8 ++-- src/Umbraco.Web/Trees/MacrosTreeController.cs | 4 +- src/Umbraco.Web/Trees/MediaTreeController.cs | 13 ++++--- .../Trees/MediaTypeTreeController.cs | 18 ++++----- src/Umbraco.Web/Trees/MemberTreeController.cs | 11 +++--- .../MemberTypeAndGroupTreeControllerBase.cs | 2 +- .../Trees/PackagesTreeController.cs | 6 +-- .../Trees/RelationTypeTreeController.cs | 4 +- .../Trees/TemplatesTreeController.cs | 4 +- 19 files changed, 89 insertions(+), 80 deletions(-) diff --git a/src/Umbraco.Web/Actions/ActionRollback.cs b/src/Umbraco.Web/Actions/ActionRollback.cs index adfdd752cf..96ce1e7767 100644 --- a/src/Umbraco.Web/Actions/ActionRollback.cs +++ b/src/Umbraco.Web/Actions/ActionRollback.cs @@ -10,7 +10,9 @@ namespace Umbraco.Web.Actions /// public class ActionRollback : IAction { - public char Letter => 'K'; + public const char ActionLetter = 'K'; + + public char Letter => ActionLetter; public string Alias => "rollback"; public string Category => Constants.Conventions.PermissionCategories.AdministrationCategory; public string Icon => "undo"; diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 4a68ca1d91..c1ed76dbc8 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -1761,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/Models/Trees/MenuItem.cs b/src/Umbraco.Web/Models/Trees/MenuItem.cs index dfafa7ce41..4170cdb73f 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItem.cs +++ b/src/Umbraco.Web/Models/Trees/MenuItem.cs @@ -52,7 +52,6 @@ namespace Umbraco.Web.Models.Trees SeperatorBefore = false; Icon = action.Icon; Action = action; - OpensDialog = legacyMenu.OpensDialog; } #endregion @@ -87,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; } diff --git a/src/Umbraco.Web/Models/Trees/MenuItemList.cs b/src/Umbraco.Web/Models/Trees/MenuItemList.cs index 672750825c..b34f0b4444 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItemList.cs +++ b/src/Umbraco.Web/Models/Trees/MenuItemList.cs @@ -62,7 +62,8 @@ namespace Umbraco.Web.Models.Trees /// /// /// The used to localize the action name based on it's alias - public MenuItem Add(ILocalizedTextService textService, bool hasSeparator = false) + /// + public MenuItem Add(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false) where T : IAction { var item = CreateMenuItem(textService, hasSeparator); @@ -87,7 +88,7 @@ namespace Umbraco.Web.Models.Trees return menuItem; } - internal MenuItem CreateMenuItem(ILocalizedTextService textService, bool hasSeparator = false) + internal MenuItem CreateMenuItem(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false) where T : IAction { var item = Current.Actions.GetAction(); @@ -95,7 +96,8 @@ namespace Umbraco.Web.Models.Trees var menuItem = new MenuItem(item, textService.Localize($"actions/{item.Alias}")) { - SeperatorBefore = hasSeparator + SeperatorBefore = hasSeparator, + OpensDialog = opensDialog }; return menuItem; diff --git a/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs b/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs index 01df73f4af..364c9c391f 100644 --- a/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentBlueprintTreeController.cs @@ -93,7 +93,7 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { // root actions - menu.Items.Add(Services.TextService.Localize($"actions/{ActionNew.ActionAlias}")); + menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } @@ -102,7 +102,7 @@ namespace Umbraco.Web.Trees if (cte != null) { var ct = Services.ContentTypeService.Get(cte.Id); - var createItem = menu.Items.Add(Services.TextService); + var createItem = menu.Items.Add(Services.TextService, opensDialog: true); createItem.NavigateToRoute("/settings/contentBlueprints/edit/-1?create=true&doctype=" + ct.Alias); menu.Items.Add(new RefreshNode(Services.TextService, true)); @@ -110,7 +110,7 @@ namespace Umbraco.Web.Trees return menu; } - menu.Items.Add(Services.TextService); + 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 a7598e5d3a..1667299436 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -128,9 +128,8 @@ namespace Umbraco.Web.Trees .Select(x => new MenuItem(x)); //these two are the standard items - //fixme: inject - menu.Items.Add(Services.TextService.Localize("actions", ActionNew.ActionAlias)); - menu.Items.Add(Services.TextService.Localize("actions", Current.Actions.GetAction().Alias), true); + menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(Services.TextService, true); //filter the standard items FilterUserAllowedMenuItems(menu, nodeActions); @@ -226,25 +225,22 @@ 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); - AddActionNode(item, menu); - AddActionNode(item, menu, true, 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); menu.Items.Add(new MenuItem("notify", Services.TextService) { Icon = "megaphone", - SeperatorBefore = true + SeperatorBefore = true, + OpensDialog = true }); menu.Items.Add(new RefreshNode(Services.TextService, true)); @@ -260,8 +256,8 @@ namespace Umbraco.Web.Trees protected MenuItemCollection GetNodeMenuItemsForDeletedContent(IUmbracoEntity item) { var menu = new MenuItemCollection(); - menu.Items.Add(Services.TextService.Localize("actions", ActionRestore.ActionAlias)); - menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.ActionAlias)); + menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(new RefreshNode(Services.TextService, true)); @@ -308,12 +304,13 @@ namespace Umbraco.Web.Trees } //fixme: Remove the need for converting to legacy - private void AddActionNode(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool convert = false) + 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"); + menuItem.OpensDialog = opensDialog; } ////fixme: Remove the need for converting to legacy diff --git a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs index 1398903cfc..646f47068b 100644 --- a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs @@ -351,7 +351,8 @@ namespace Umbraco.Web.Trees var menu = new MenuItemCollection(); menu.Items.Add(new MenuItem("emptyRecycleBin", Services.TextService) { - Icon = "trash" + Icon = "trash", + OpensDialog = true }); menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; diff --git a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs index 32367ad02c..43e5b03f2f 100644 --- a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs @@ -81,11 +81,12 @@ namespace Umbraco.Web.Trees menu.DefaultMenuAlias = ActionNew.ActionAlias; // root actions - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(new MenuItem("importDocumentType", Services.TextService) { Icon = "page-up", - SeperatorBefore = true + SeperatorBefore = true, + OpensDialog = true }); menu.Items.Add(new RefreshNode(Services.TextService, true)); @@ -98,9 +99,9 @@ namespace Umbraco.Web.Trees //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(new MenuItem("rename", Services.TextService.Localize("actions/rename")) + menu.Items.Add(new MenuItem("rename", Services.TextService) { Icon = "icon icon-edit" }); @@ -108,7 +109,7 @@ namespace Umbraco.Web.Trees if (container.HasChildren == false) { //can delete doc type - menu.Items.Add(Services.TextService, true); + menu.Items.Add(Services.TextService, true, opensDialog: true); } menu.Items.Add(new RefreshNode(Services.TextService, true)); } @@ -119,20 +120,21 @@ namespace Umbraco.Web.Trees if (enableInheritedDocumentTypes) { - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); } //no move action if this is a child doc type if (parent == null) { - menu.Items.Add(Services.TextService, true); + menu.Items.Add(Services.TextService, true, opensDialog: true); } - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(new MenuItem("export", Services.TextService) { Icon = "download-alt", - SeperatorBefore = true + SeperatorBefore = true, + OpensDialog = true }); - menu.Items.Add(Services.TextService, true); + menu.Items.Add(Services.TextService, true, opensDialog: true); if (enableInheritedDocumentTypes) menu.Items.Add(new RefreshNode(Services.TextService, true)); } diff --git a/src/Umbraco.Web/Trees/DataTypeTreeController.cs b/src/Umbraco.Web/Trees/DataTypeTreeController.cs index 4f9f93f110..6c89f4a1dc 100644 --- a/src/Umbraco.Web/Trees/DataTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/DataTypeTreeController.cs @@ -104,7 +104,7 @@ namespace Umbraco.Web.Trees menu.DefaultMenuAlias = ActionNew.ActionAlias; // root actions - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; } @@ -115,7 +115,7 @@ namespace Umbraco.Web.Trees //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(new MenuItem("rename", Services.TextService.Localize("actions/rename")) { @@ -125,7 +125,7 @@ namespace Umbraco.Web.Trees if (container.HasChildren == false) { //can delete data type - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); } menu.Items.Add(new RefreshNode(Services.TextService, true)); } @@ -134,9 +134,9 @@ namespace Umbraco.Web.Trees var nonDeletableSystemDataTypeIds = GetNonDeletableSystemDataTypeIds(); if (nonDeletableSystemDataTypeIds.Contains(int.Parse(id)) == false) - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); - menu.Items.Add(Services.TextService, hasSeparator: true); + menu.Items.Add(Services.TextService, hasSeparator: true, opensDialog: true); } return menu; diff --git a/src/Umbraco.Web/Trees/DictionaryTreeController.cs b/src/Umbraco.Web/Trees/DictionaryTreeController.cs index a0510acd3e..d0a7fce3ad 100644 --- a/src/Umbraco.Web/Trees/DictionaryTreeController.cs +++ b/src/Umbraco.Web/Trees/DictionaryTreeController.cs @@ -96,10 +96,10 @@ namespace Umbraco.Web.Trees { var menu = new MenuItemCollection(); - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); if (id != Constants.System.Root.ToInvariantString()) - menu.Items.Add(Services.TextService, true); + menu.Items.Add(Services.TextService, true, opensDialog: true); menu.Items.Add(new RefreshNode(Services.TextService, true)); diff --git a/src/Umbraco.Web/Trees/FileSystemTreeController.cs b/src/Umbraco.Web/Trees/FileSystemTreeController.cs index a517cd45c2..f1e53ed5d4 100644 --- a/src/Umbraco.Web/Trees/FileSystemTreeController.cs +++ b/src/Umbraco.Web/Trees/FileSystemTreeController.cs @@ -82,7 +82,7 @@ namespace Umbraco.Web.Trees //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; //create action - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); //refresh action menu.Items.Add(new RefreshNode(Services.TextService, true)); @@ -96,7 +96,7 @@ namespace Umbraco.Web.Trees //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; //create action - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); var hasChildren = FileSystem.GetFiles(path).Any() || FileSystem.GetDirectories(path).Any(); @@ -104,7 +104,7 @@ namespace Umbraco.Web.Trees if (hasChildren == false) { //delete action - menu.Items.Add(Services.TextService, true); + menu.Items.Add(Services.TextService, true, opensDialog: true); } //refresh action @@ -118,7 +118,7 @@ namespace Umbraco.Web.Trees var menu = new MenuItemCollection(); //if it's not a directory then we only allow to delete the item - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); return menu; } diff --git a/src/Umbraco.Web/Trees/MacrosTreeController.cs b/src/Umbraco.Web/Trees/MacrosTreeController.cs index 0faa1ce75d..3f925eef8d 100644 --- a/src/Umbraco.Web/Trees/MacrosTreeController.cs +++ b/src/Umbraco.Web/Trees/MacrosTreeController.cs @@ -59,7 +59,7 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { //Create the normal create action - menu.Items.Add(Services.TextService) + menu.Items.Add(Services.TextService, opensDialog: true) //Since we haven't implemented anything for macros in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(null, "initmacros", queryStrings.GetValue("application")); @@ -75,7 +75,7 @@ namespace Umbraco.Web.Trees if (macro == null) return new MenuItemCollection(); //add delete option for all macros - menu.Items.Add(Services.TextService) + menu.Items.Add(Services.TextService, opensDialog: true) //Since we haven't implemented anything for macros in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(new EntitySlim diff --git a/src/Umbraco.Web/Trees/MediaTreeController.cs b/src/Umbraco.Web/Trees/MediaTreeController.cs index d260253218..0292a907fc 100644 --- a/src/Umbraco.Web/Trees/MediaTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTreeController.cs @@ -95,7 +95,7 @@ namespace Umbraco.Web.Trees } // root actions - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(Services.TextService, true); menu.Items.Add(new RefreshNode(Services.TextService, true)); return menu; @@ -119,9 +119,9 @@ namespace Umbraco.Web.Trees } //return a normal node menu: - menu.Items.Add(Services.TextService); - menu.Items.Add(Services.TextService); - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(Services.TextService); menu.Items.Add(new RefreshNode(Services.TextService, true)); @@ -129,7 +129,10 @@ namespace Umbraco.Web.Trees if (item.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Contains(RecycleBinId.ToInvariantString())) { menu.DefaultMenuAlias = null; - menu.Items.Insert(2, new MenuItem(Current.Actions.GetAction(), Services.TextService.Localize("actions", ActionRestore.ActionAlias))); + menu.Items.Insert(2, new MenuItem(ActionRestore.ActionAlias, Services.TextService) + { + OpensDialog = true + }); } else { diff --git a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs index a679cefa32..547199676a 100644 --- a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs @@ -74,7 +74,7 @@ namespace Umbraco.Web.Trees menu.DefaultMenuAlias = ActionNew.ActionAlias; // root actions - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(new RefreshNode(Services.TextService)); return menu; } @@ -85,7 +85,7 @@ namespace Umbraco.Web.Trees //set the default to create menu.DefaultMenuAlias = ActionNew.ActionAlias; - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); menu.Items.Add(new MenuItem("rename", Services.TextService.Localize("actions/rename")) { @@ -95,7 +95,7 @@ namespace Umbraco.Web.Trees if (container.HasChildren == false) { //can delete doc type - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); } menu.Items.Add(new RefreshNode(Services.TextService, true)); } @@ -106,26 +106,26 @@ namespace Umbraco.Web.Trees if (enableInheritedMediaTypes) { - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); //no move action if this is a child doc type if (parent == null) { - menu.Items.Add(Services.TextService, true); + menu.Items.Add(Services.TextService, true, opensDialog: true); } } else { - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); //no move action if this is a child doc type if (parent == null) { - menu.Items.Add(Services.TextService, true); + menu.Items.Add(Services.TextService, true, opensDialog: true); } } - menu.Items.Add(Services.TextService); - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); + menu.Items.Add(Services.TextService, opensDialog: true); if (enableInheritedMediaTypes) menu.Items.Add(new RefreshNode(Services.TextService, true)); } diff --git a/src/Umbraco.Web/Trees/MemberTreeController.cs b/src/Umbraco.Web/Trees/MemberTreeController.cs index 24fc624110..68819351c0 100644 --- a/src/Umbraco.Web/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web/Trees/MemberTreeController.cs @@ -159,17 +159,16 @@ namespace Umbraco.Web.Trees menu.DefaultMenuAlias = ActionNew.ActionAlias; //Create the normal create action - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); } else { //Create a custom create action - this does not launch a dialog, it just navigates to the create screen // we'll create it based on the ActionNew so it maintains the same icon properties, name, etc... - var createMenuItem = new MenuItem + var createMenuItem = new MenuItem(ActionNew.ActionAlias, Services.TextService) { - Name = Services.TextService.Localize($"actions/{ActionNew.ActionAlias}"), - Alias = ActionNew.ActionAlias, - Icon = "add" + Icon = "add", + OpensDialog = true }; //we want to go to this route: /member/member/edit/-1?create=true createMenuItem.NavigateToRoute("/member/member/edit/-1?create=true"); @@ -181,7 +180,7 @@ namespace Umbraco.Web.Trees } //add delete option for all members - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); if (Security.CurrentUser.HasAccessToSensitiveData()) { diff --git a/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs b/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs index 484ea1e2a9..9ea5908891 100644 --- a/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs @@ -33,7 +33,7 @@ namespace Umbraco.Web.Trees else { //delete member type/group - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); } return menu; diff --git a/src/Umbraco.Web/Trees/PackagesTreeController.cs b/src/Umbraco.Web/Trees/PackagesTreeController.cs index 8f62047941..8158b47985 100644 --- a/src/Umbraco.Web/Trees/PackagesTreeController.cs +++ b/src/Umbraco.Web/Trees/PackagesTreeController.cs @@ -84,12 +84,12 @@ namespace Umbraco.Web.Trees // Root actions if (id == "-1") { - menu.Items.Add(Services.TextService) + menu.Items.Add(Services.TextService, opensDialog: true) .ConvertLegacyMenuItem(null, Constants.Trees.Packages, queryStrings.GetValue("application")); } else if (id == "created") { - menu.Items.Add(Services.TextService) + menu.Items.Add(Services.TextService, opensDialog: true) .ConvertLegacyMenuItem(null, Constants.Trees.Packages, queryStrings.GetValue("application")); menu.Items.Add(new RefreshNode(Services.TextService, true)); @@ -97,7 +97,7 @@ namespace Umbraco.Web.Trees else { //it's a package node - menu.Items.Add(Services.TextService); + menu.Items.Add(Services.TextService, opensDialog: true); } return menu; diff --git a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs index ab6e9e2dd7..33ccc152c5 100644 --- a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { //Create the normal create action - var addMenuItem = menu.Items.Add(Services.TextService); + var addMenuItem = menu.Items.Add(Services.TextService, opensDialog: true); addMenuItem.LaunchDialogUrl("developer/RelationTypes/NewRelationType.aspx", "Create New RelationType"); //refresh action menu.Items.Add(new RefreshNode(Services.TextService, true)); @@ -37,7 +37,7 @@ namespace Umbraco.Web.Trees if (relationType == null) return new MenuItemCollection(); //add delete option for all macros - menu.Items.Add(Services.TextService) + menu.Items.Add(Services.TextService, opensDialog: true) //Since we haven't implemented anything for relationtypes in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(new EntitySlim diff --git a/src/Umbraco.Web/Trees/TemplatesTreeController.cs b/src/Umbraco.Web/Trees/TemplatesTreeController.cs index 3ae45a072e..2339d92d96 100644 --- a/src/Umbraco.Web/Trees/TemplatesTreeController.cs +++ b/src/Umbraco.Web/Trees/TemplatesTreeController.cs @@ -70,7 +70,7 @@ namespace Umbraco.Web.Trees var menu = new MenuItemCollection(); //Create the normal create action - var item = menu.Items.Add(Services.TextService); + var item = menu.Items.Add(Services.TextService, opensDialog: true); item.NavigateToRoute($"{queryStrings.GetValue("application")}/templates/edit/{id}?create=true"); if (id == Constants.System.Root.ToInvariantString()) @@ -89,7 +89,7 @@ namespace Umbraco.Web.Trees if (template.IsMasterTemplate == false) { //add delete option if it doesn't have children - menu.Items.Add(Services.TextService, true); + menu.Items.Add(Services.TextService, true, opensDialog: true); } //add refresh From 372f77fde5a16641960fa92b9c9637e9a53b3199 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 30 Oct 2018 00:36:11 +1100 Subject: [PATCH 09/16] reverts accidental change --- src/Umbraco.Web/Editors/ContentController.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index c1ed76dbc8..53e2593fef 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -944,13 +944,13 @@ namespace Umbraco.Web.Editors /// /// [EnsureUserPermissionForContent("id", 'U')] - public HttpResponseMessage PostPublishById(ContentPublish model) + public HttpResponseMessage PostPublishById(int id) { - var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(model.Id)); + var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(id)); if (foundContent == null) { - return HandleContentNotFound(model.Id, false); + return HandleContentNotFound(id, false); } var publishResult = Services.ContentService.SavePublishing(foundContent, Security.GetUserId().ResultOr(0)); From 15eaa33e08be55cc43e1cee59b261a7e22b05083 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 30 Oct 2018 01:15:23 +1100 Subject: [PATCH 10/16] updates migration to invariant string check --- .../Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs index accb755020..64ee2f6b88 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs @@ -65,17 +65,17 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 var requiresCacheRebuild = false; switch (dd.EditorAlias) { - case "Umbraco.DropDown": + case string ea when ea.InvariantEquals("Umbraco.DropDown"): UpdateDataType(dd, config, false); break; - case "Umbraco.DropdownlistPublishingKeys": + case string ea when ea.InvariantEquals("Umbraco.DropdownlistPublishingKeys"): UpdateDataType(dd, config, false); requiresCacheRebuild = true; break; - case "Umbraco.DropDownMultiple": + case string ea when ea.InvariantEquals("Umbraco.DropDownMultiple"): UpdateDataType(dd, config, false); break; - case "Umbraco.DropdownlistMultiplePublishKeys": + case string ea when ea.InvariantEquals("Umbraco.DropdownlistMultiplePublishKeys"): UpdateDataType(dd, config, true); requiresCacheRebuild = true; break; From 0d0d26d3e994ad42ecfd9edb77319d15adc0c2dc Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 30 Oct 2018 02:05:43 +1100 Subject: [PATCH 11/16] Fixes converting the Umbraco.DropDownMultiple to a multiple drop down, fixes boolean logic on the js single drop down --- .../Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs | 2 +- .../dropdownFlexible/dropdownFlexible.controller.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs index 64ee2f6b88..87d7a8c571 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs @@ -73,7 +73,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 requiresCacheRebuild = true; break; case string ea when ea.InvariantEquals("Umbraco.DropDownMultiple"): - UpdateDataType(dd, config, false); + UpdateDataType(dd, config, true); break; case string ea when ea.InvariantEquals("Umbraco.DropdownlistMultiplePublishKeys"): UpdateDataType(dd, config, true); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js index 23bd2c9a42..f8e02a240a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js @@ -77,7 +77,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo // if we run in single mode we'll store the value in a local variable // so we can pass an array as the model as our PropertyValueEditor expects that $scope.model.singleDropdownValue = ""; - if (Object.toBoolean($scope.model.config.multiple)) { + if (!Object.toBoolean($scope.model.config.multiple)) { $scope.model.singleDropdownValue = Array.isArray($scope.model.value) ? $scope.model.value[0] : $scope.model.value; } From f123331d421b4fed7485a3146af10139541bd58c Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 30 Oct 2018 02:11:33 +1100 Subject: [PATCH 12/16] Fixes updating the storage type --- .../Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs index 87d7a8c571..600f952d6a 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs @@ -6,6 +6,7 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Logging; +using Umbraco.Core.Models; namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 { @@ -96,6 +97,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 multiple = isMultiple, items = config.Items }; + dataType.DbType = ValueStorageType.Nvarchar.ToString(); dataType.Configuration = JsonConvert.SerializeObject(flexConfig); Database.Update(dataType); } From 386dd2281ce321666ce07a1b39069dc7227c68ab Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 30 Oct 2018 02:18:07 +1100 Subject: [PATCH 13/16] Fixes log messages --- .../Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs index 600f952d6a..e5cda85168 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs @@ -35,7 +35,9 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 } catch (Exception ex) { - Logger.Error(ex, $"Invalid drop down configuration detected: \"{dd.Configuration}\", cannot convert editor, values will be cleared"); + Logger.Error( + ex, "Invalid drop down configuration detected: \"{Configuration}\", cannot convert editor, values will be cleared", + dd.Configuration); dd.Configuration = null; Database.Update(dd); continue; @@ -132,7 +134,8 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 vals.Add(val.Value); else { - Logger.Warn($"Could not find associated data type configuration for stored Id {id}"); + Logger.Warn( + "Could not find associated data type configuration for stored Id {DataTypeId}", id); canConvert = false; } } From 881ea22efe05fb26740a5e2dc5d41a78429494ef Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 31 Oct 2018 10:24:40 +0000 Subject: [PATCH 14/16] Fix lang typo in ContentService & fix up the breaking unit test --- .../Services/Implement/ContentService.cs | 2 +- src/Umbraco.Tests/Services/ContentServiceTests.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index 3953e7a640..9bb8e6720e 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -1202,7 +1202,7 @@ namespace Umbraco.Core.Services.Implement var langs = string.Join(", ", _languageRepository.GetMany() .Where(x => culturesChanging.InvariantContains(x.IsoCode)) .Select(x => x.CultureName)); - Audit(AuditType.PublishVariant, userId, content.Id, $"Published languagues: {langs}", langs); + Audit(AuditType.PublishVariant, userId, content.Id, $"Published languages: {langs}", langs); } else Audit(AuditType.Publish, userId, content.Id); diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 5aad7c4d90..c5bbe197ef 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -1293,11 +1293,11 @@ namespace Umbraco.Tests.Services { // Arrange - var langUk = new Language("en-UK") { IsDefault = true }; + var langGB = new Language("en-GB") { IsDefault = true }; var langFr = new Language("fr-FR"); ServiceContext.LocalizationService.Save(langFr); - ServiceContext.LocalizationService.Save(langUk); + ServiceContext.LocalizationService.Save(langGB); var contentType = MockedContentTypes.CreateBasicContentType(); contentType.Variations = ContentVariation.Culture; @@ -1309,16 +1309,16 @@ namespace Umbraco.Tests.Services var published = ServiceContext.ContentService.SavePublishing(content); //audit log will only show that french was published var lastLog = ServiceContext.AuditService.GetLogs(content.Id).Last(); - Assert.AreEqual($"Published cultures: fr-fr", lastLog.Comment); + Assert.AreEqual($"Published languages: French (France)", lastLog.Comment); //re-get content = ServiceContext.ContentService.GetById(content.Id); - content.SetCultureName("content-en", langUk.IsoCode); - content.PublishCulture(langUk.IsoCode); + content.SetCultureName("content-en", langGB.IsoCode); + content.PublishCulture(langGB.IsoCode); published = ServiceContext.ContentService.SavePublishing(content); //audit log will only show that english was published lastLog = ServiceContext.AuditService.GetLogs(content.Id).Last(); - Assert.AreEqual($"Published cultures: en-uk", lastLog.Comment); + Assert.AreEqual($"Published languages: English (United Kingdom)", lastLog.Comment); } [Test] From b2c3944074294b062fc8eff33f6fa0fc7107a01e Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 31 Oct 2018 13:47:07 +0000 Subject: [PATCH 15/16] Remove a block of commented out code - that was forgotten --- src/Umbraco.Web/Trees/ContentTreeController.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index 1667299436..04c356a4fd 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -313,16 +313,6 @@ namespace Umbraco.Web.Trees menuItem.OpensDialog = opensDialog; } - ////fixme: Remove the need for converting to legacy - //private void AddActionNode(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool convert = false) - // where TItem : MenuItem, new() - // 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"); - //} - public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) { return _treeSearcher.ExamineSearch(Umbraco, query, UmbracoEntityTypes.Document, pageSize, pageIndex, out totalFound, searchFrom); From f15d30b1b491e39fb8fd61a4a4a598ef775818aa Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Sun, 28 Oct 2018 12:51:17 +0100 Subject: [PATCH 16/16] Assign the current main culture to GetChildren lookup if none is defined, as this is required for variant data --- .../src/common/resources/content.resource.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js index 64c2b127e9..2475353d94 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js @@ -23,7 +23,7 @@ * **/ -function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { +function contentResource($q, $http, $routeParams, umbDataFormatter, umbRequestHelper) { /** internal method process the saving of data and post processing the result */ function saveContentItem(content, action, files, restApiUrl, showNotifications) { @@ -607,7 +607,10 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { else if (options.orderDirection === "desc") { options.orderDirection = "Descending"; } - + if (!options.cultureName) { + // must send a culture to the content API to handle variant data correctly + options.cultureName = $routeParams.mculture; + } //converts the value to a js bool function toBool(v) { if (angular.isNumber(v)) {