From 6b19ab3b468c295132f6e428e832fe8bdbf6a5dc Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Sat, 27 Oct 2018 22:04:47 +0100 Subject: [PATCH 01/27] Prototyped edit view --- .../src/views/relationtypes/edit.html | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html new file mode 100644 index 0000000000..55c5ec2d88 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html @@ -0,0 +1,104 @@ +
+ + +
+ + + + + + + + + +
1234
+ 0123-4567-8910-abcd +
+ + + +
    +
  • + +
  • +
  • + +
  • +
+
+ + + +
Document
+
+ + + +
Document
+
+ + + +
12
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ParentChildCreatedComment
SomethingSomething else2018-10-27 18:58A comment here
SomethingSomething else2018-10-27 18:58A comment here
SomethingSomething else2018-10-27 18:58A comment here
+
+
+
+
+
+ + + + + + + +
+
+
From 083de953113482ace9f9c8d9b386b593ba71f120 Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Sat, 27 Oct 2018 23:37:08 +0100 Subject: [PATCH 02/27] Stubbed out relation type controller and resource --- .../common/resources/relationtype.resource.js | 40 ++++++++++++++ .../Editors/RelationTypeController.cs | 52 +++++++++++++++++++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + 3 files changed, 93 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js create mode 100644 src/Umbraco.Web/Editors/RelationTypeController.cs diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js new file mode 100644 index 0000000000..46df8e2608 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js @@ -0,0 +1,40 @@ +/** + * @ngdoc service + * @name umbraco.resources.relationTypeResource + * @description Loads in data for relation types. + */ +function relationTypeResource($q, $http, umbRequestHelper) { + return { + + /** + * @ngdoc method + * @name umbraco.resources.relationTypeResource#getById + * @methodOf umbraco.resources.relationTypeResource + * @param {Int} id of the dictionary item to get. + * @returns {Promise} resourcePromise containing relation type data. + */ + getById: function (id) { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "relationTypeBaseUrl", + "GetById", + [{ id: id }] + ) + ), + "Failed to get item " + id + ); + }, + + save: function () { + + }, + + deleteById: function (id) { + + } + + }; +} + +angular.module("umbraco.resources").factory("relationTypeResource", relationTypeResource); diff --git a/src/Umbraco.Web/Editors/RelationTypeController.cs b/src/Umbraco.Web/Editors/RelationTypeController.cs new file mode 100644 index 0000000000..cfd6c2e56f --- /dev/null +++ b/src/Umbraco.Web/Editors/RelationTypeController.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using System.Web.Http; +using AutoMapper; +using Umbraco.Core.Models; +using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi.Filters; +using Constants = Umbraco.Core.Constants; +using RelationType = Umbraco.Web.Models.ContentEditing.RelationType; + +namespace Umbraco.Web.Editors +{ + /// + /// The API controller for editing relation types. + /// + [PluginController("UmbracoApi")] + [UmbracoTreeAuthorize(Constants.Trees.RelationTypes)] + [EnableOverrideAuthorization] + public class RelationTypeController : BackOfficeNotificationsController + { + /// + /// Gets a relation type by ID. + /// + /// The relation type ID. + /// Returns the . + public RelationType GetById(int id) + { + var relationType = Services.RelationService.GetRelationTypeById(id); + + if (relationType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return Mapper.Map(relationType); + } + + public void PostSave() + { + throw new NotImplementedException(); + } + + public void DeleteById() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 656bbd29c5..e3bdd95eb4 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -111,6 +111,7 @@ + From 06d19f2735a455bdb8fbe2dedccc81f03792feb8 Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Sun, 28 Oct 2018 19:04:00 +0000 Subject: [PATCH 03/27] Load relation type edit view --- .../common/resources/relationtype.resource.js | 2 +- .../views/relationtypes/edit.controller.js | 30 +++++++++++++ .../src/views/relationtypes/edit.html | 28 ++++++------ .../Editors/BackOfficeServerVariables.cs | 4 ++ .../Editors/RelationTypeController.cs | 8 ++-- .../Models/ContentEditing/RelationType.cs | 1 + .../ContentEditing/RelationTypeDisplay.cs | 44 +++++++++++++++++++ .../Models/Mapping/RelationMapperProfile.cs | 25 +++++++++++ .../Trees/RelationTypeTreeController.cs | 5 +-- src/Umbraco.Web/Umbraco.Web.csproj | 1 + 10 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js create mode 100644 src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js index 46df8e2608..81fdbdb838 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js @@ -17,7 +17,7 @@ function relationTypeResource($q, $http, umbRequestHelper) { return umbRequestHelper.resourcePromise( $http.get( umbRequestHelper.getApiUrl( - "relationTypeBaseUrl", + "relationTypeApiBaseUrl", "GetById", [{ id: id }] ) diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js new file mode 100644 index 0000000000..37eb1ea6d9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js @@ -0,0 +1,30 @@ +function RelationTypeEditController($scope, $routeParams, relationTypeResource, editorState, navigationService) { + + var vm = this; + + vm.page = {}; + vm.page.loading = false; + vm.page.saveButtonState = "init"; + vm.page.menu = {} + + if($routeParams.create) { + alert("create"); + } else { + vm.page.loading = true; + + relationTypeResource.getById($routeParams.id) + .then(function(data) { + vm.relation = data; + + editorState.set(vm.relation); + + navigationService.syncTree({ tree: "relationTypes", path: data.path, forceReload: true }).then(function (syncArgs) { + vm.page.menu.currentNode = syncArgs.node; + }); + + vm.page.loading = false; + }); + } +} + +angular.module("umbraco").controller("Umbraco.Editors.RelationTypes.EditController", RelationTypeEditController); diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html index 55c5ec2d88..3f88c914f4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html @@ -1,15 +1,13 @@ -
- +
+
- + + name="vm.relation.name" + alias="vm.relation.alias" + hide-description="true" + hide-icon="true"> @@ -17,8 +15,8 @@ -
1234
- 0123-4567-8910-abcd +
{{vm.relation.id}}
+ {{vm.relation.key}}
@@ -26,12 +24,12 @@
@@ -39,12 +37,12 @@ -
Document
+
{{vm.relation.parentObjectTypeName}}
-
Document
+
{{vm.relation.childObjectTypeName}}
diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index 98114f0664..a05ac5338e 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -299,6 +299,10 @@ namespace Umbraco.Web.Editors { "languageApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.GetAllLanguages()) + }, + { + "relationTypeApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( + controller => controller.GetById(1)) } } }, diff --git a/src/Umbraco.Web/Editors/RelationTypeController.cs b/src/Umbraco.Web/Editors/RelationTypeController.cs index cfd6c2e56f..2b9242ef31 100644 --- a/src/Umbraco.Web/Editors/RelationTypeController.cs +++ b/src/Umbraco.Web/Editors/RelationTypeController.cs @@ -7,10 +7,10 @@ using System.Threading.Tasks; using System.Web.Http; using AutoMapper; using Umbraco.Core.Models; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; -using RelationType = Umbraco.Web.Models.ContentEditing.RelationType; namespace Umbraco.Web.Editors { @@ -26,8 +26,8 @@ namespace Umbraco.Web.Editors /// Gets a relation type by ID. /// /// The relation type ID. - /// Returns the . - public RelationType GetById(int id) + /// Returns the . + public RelationTypeDisplay GetById(int id) { var relationType = Services.RelationService.GetRelationTypeById(id); @@ -36,7 +36,7 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.NotFound); } - return Mapper.Map(relationType); + return Mapper.Map(relationType); } public void PostSave() diff --git a/src/Umbraco.Web/Models/ContentEditing/RelationType.cs b/src/Umbraco.Web/Models/ContentEditing/RelationType.cs index 129376da5c..f52ac507ac 100644 --- a/src/Umbraco.Web/Models/ContentEditing/RelationType.cs +++ b/src/Umbraco.Web/Models/ContentEditing/RelationType.cs @@ -3,6 +3,7 @@ using System.Runtime.Serialization; namespace Umbraco.Web.Models.ContentEditing { + [Obsolete("Use Umbraco.Web.Models.ContentEditing.RelationTypeDisplay instead")] [DataContract(Name = "relationType", Namespace = "")] public class RelationType { diff --git a/src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs new file mode 100644 index 0000000000..3861e0938d --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs @@ -0,0 +1,44 @@ +using System; +using System.ComponentModel; +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models.ContentEditing +{ + [DataContract(Name = "relationType", Namespace = "")] + public class RelationTypeDisplay : EntityBasic + { + /// + /// Gets or sets a boolean indicating whether the RelationType is Bidirectional (true) or Parent to Child (false) + /// + [DataMember(Name = "isBidirectional", IsRequired = true)] + public bool IsBidirectional { get; set; } + + /// + /// Gets or sets the Parents object type id + /// + /// Corresponds to the NodeObjectType in the umbracoNode table + [DataMember(Name = "parentObjectType", IsRequired = true)] + public Guid ParentObjectType { get; set; } + + /// + /// Gets or sets the Parent's object type name. + /// + [DataMember(Name = "parentObjectTypeName")] + [ReadOnly(true)] + public string ParentObjectTypeName { get; set; } + + /// + /// Gets or sets the Childs object type id + /// + /// Corresponds to the NodeObjectType in the umbracoNode table + [DataMember(Name = "childObjectType", IsRequired = true)] + public Guid ChildObjectType { get; set; } + + /// + /// Gets or sets the Child's object type name. + /// + [DataMember(Name = "childObjectTypeName")] + [ReadOnly(true)] + public string ChildObjectTypeName { get; set; } + } +} diff --git a/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs index 31acf4e5e1..95f4fab054 100644 --- a/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs @@ -1,5 +1,7 @@ using AutoMapper; +using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Web.Models.ContentEditing; using Relation = Umbraco.Web.Models.ContentEditing.Relation; using RelationType = Umbraco.Web.Models.ContentEditing.RelationType; @@ -9,6 +11,29 @@ namespace Umbraco.Web.Models.Mapping { public RelationMapperProfile() { + // FROM IRelationType to RelationTypeDisplay + CreateMap() + .ForMember(x => x.Icon, expression => expression.Ignore()) + .ForMember(x => x.Trashed, expression => expression.Ignore()) + .ForMember(x => x.Alias, expression => expression.Ignore()) + .ForMember(x => x.Path, expression => expression.Ignore()) + .ForMember(x => x.AdditionalData, expression => expression.Ignore()) + .ForMember(x => x.ChildObjectTypeName, expression => expression.Ignore()) + .ForMember(x => x.ParentObjectTypeName, expression => expression.Ignore()) + .ForMember( + x => x.Udi, + expression => expression.MapFrom( + content => Udi.Create(Constants.UdiEntityType.RelationType, content.Key))) + .AfterMap((src, dest) => + { + // Build up the path + dest.Path = "-1," + src.Id; + + // Set the "friendly" names for the parent and child object types + dest.ParentObjectTypeName = ObjectTypes.GetUmbracoObjectType(src.ParentObjectType).GetFriendlyName(); + dest.ChildObjectTypeName = ObjectTypes.GetUmbracoObjectType(src.ChildObjectType).GetFriendlyName(); + }); + //FROM IRelationType TO RelationType CreateMap(); diff --git a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs index 4930b4dc5e..884b6c5f54 100644 --- a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs @@ -65,10 +65,7 @@ namespace Umbraco.Web.Trees queryStrings, rt.Name, "icon-trafic", - false, - //TODO: Rebuild the macro editor in angular, then we dont need to have this at all (which is just a path to the legacy editor) - "/" + queryStrings.GetValue("application") + "/framed/" + - Uri.EscapeDataString("/umbraco/developer/RelationTypes/EditRelationType.aspx?id=" + rt.Id) + false ))); } return nodes; diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index e3bdd95eb4..7e51974bc9 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -148,6 +148,7 @@ + From 78b7bb6a2299244b410b9036d79125366c5b9651 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 8 Nov 2018 15:33:14 +0000 Subject: [PATCH 04/27] Recreate benchmark project and update deps Fix #3561 --- .../Config/QuickRunConfigAttribute.cs | 13 +- .../CtorInvokeBenchmarks.cs | 2 +- src/Umbraco.Tests.Benchmarks/Program.cs | 7 +- .../Properties/AssemblyInfo.cs | 4 +- .../TryConvertToBenchmarks.cs | 8 +- .../Umbraco.Tests.Benchmarks.csproj | 110 ++----- src/Umbraco.Tests.Benchmarks/app.config | 300 +----------------- src/umbraco.sln | 14 +- 8 files changed, 52 insertions(+), 406 deletions(-) diff --git a/src/Umbraco.Tests.Benchmarks/Config/QuickRunConfigAttribute.cs b/src/Umbraco.Tests.Benchmarks/Config/QuickRunConfigAttribute.cs index f7d6b6bb72..52d670de3c 100644 --- a/src/Umbraco.Tests.Benchmarks/Config/QuickRunConfigAttribute.cs +++ b/src/Umbraco.Tests.Benchmarks/Config/QuickRunConfigAttribute.cs @@ -1,13 +1,14 @@ -using BenchmarkDotNet.Configs; +using System; +using BenchmarkDotNet.Configs; using BenchmarkDotNet.Horology; using BenchmarkDotNet.Jobs; -using System; namespace Umbraco.Tests.Benchmarks.Config { /// /// Configures the benchmark to run with less warmup and a shorter iteration time than the standard benchmark. /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class QuickRunConfigAttribute : Attribute, IConfigSource { /// @@ -15,11 +16,11 @@ namespace Umbraco.Tests.Benchmarks.Config /// public QuickRunConfigAttribute() { - Config = (ManualConfig) ManualConfig.CreateEmpty() + this.Config = (ManualConfig)ManualConfig.CreateEmpty() .With(Job.Default.WithLaunchCount(1) // benchmark process will be launched only once .WithIterationTime(new TimeInterval(100, TimeUnit.Millisecond)) // 100ms per iteration .WithWarmupCount(3) // 3 warmup iteration - .WithTargetCount(3)); // 3 target iteration + .WithIterationCount(3)); // 3 target iteration } /// @@ -28,6 +29,6 @@ namespace Umbraco.Tests.Benchmarks.Config protected ManualConfig Config { get; } /// - IConfig IConfigSource.Config => Config; + IConfig IConfigSource.Config => this.Config; } -} \ No newline at end of file +} diff --git a/src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs index 1d5876187b..5588e13d12 100644 --- a/src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs +++ b/src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.Benchmarks .WithLaunchCount(1) // benchmark process will be launched only once .WithIterationTime(TimeInterval.FromMilliseconds(400)) .WithWarmupCount(3) - .WithTargetCount(6)); + .WithIterationCount(6)); } } diff --git a/src/Umbraco.Tests.Benchmarks/Program.cs b/src/Umbraco.Tests.Benchmarks/Program.cs index c9332e7fa3..62137bd85d 100644 --- a/src/Umbraco.Tests.Benchmarks/Program.cs +++ b/src/Umbraco.Tests.Benchmarks/Program.cs @@ -2,11 +2,8 @@ namespace Umbraco.Tests.Benchmarks { - internal class Program + internal static class Program { - public static void Main(string[] args) - { - new BenchmarkSwitcher(typeof(Program).Assembly).Run(args); - } + private static void Main(string[] args) => new BenchmarkSwitcher(typeof(Program).Assembly).Run(args); } } diff --git a/src/Umbraco.Tests.Benchmarks/Properties/AssemblyInfo.cs b/src/Umbraco.Tests.Benchmarks/Properties/AssemblyInfo.cs index 2ab0051c26..9f5a3c7453 100644 --- a/src/Umbraco.Tests.Benchmarks/Properties/AssemblyInfo.cs +++ b/src/Umbraco.Tests.Benchmarks/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Umbraco.Tests.Benchmarks")] -[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyCopyright("Copyright © 2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -20,7 +20,7 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("86deb346-089f-4106-89c8-d852b9cf2a33")] +[assembly: Guid("3a33adc9-c6c0-4db1-a613-a9af0210df3d")] // Version information for an assembly consists of the following four values: // diff --git a/src/Umbraco.Tests.Benchmarks/TryConvertToBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/TryConvertToBenchmarks.cs index 57b47dc1d0..7e73c5e438 100644 --- a/src/Umbraco.Tests.Benchmarks/TryConvertToBenchmarks.cs +++ b/src/Umbraco.Tests.Benchmarks/TryConvertToBenchmarks.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Linq; using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Engines; using Umbraco.Core; namespace Umbraco.Tests.Benchmarks @@ -12,9 +14,9 @@ namespace Umbraco.Tests.Benchmarks private static readonly string Date = "Saturday 10, November 2012"; [Benchmark(Description = "List to IEnumerable")] - public IEnumerable TryConvertToEnumerable() + public IList TryConvertToEnumerable() { - return List.TryConvertTo>().Result; + return List.TryConvertTo>().Result.ToList(); } [Benchmark(Description = "Int to Double")] @@ -41,4 +43,4 @@ namespace Umbraco.Tests.Benchmarks return Date.TryConvertTo().Result; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj index 9755e4f9db..99bb768842 100644 --- a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj +++ b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj @@ -1,20 +1,17 @@  - + Debug AnyCPU - {86DEB346-089F-4106-89C8-D852B9CF2A33} + {3A33ADC9-C6C0-4DB1-A613-A9AF0210DF3D} Exe - Properties Umbraco.Tests.Benchmarks Umbraco.Tests.Benchmarks v4.7.2 512 - - - - false + true + true AnyCPU @@ -25,7 +22,6 @@ DEBUG;TRACE prompt 4 - latest AnyCPU @@ -35,92 +31,27 @@ TRACE prompt 4 - latest - - - Always + false + 7.3 - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - @@ -130,27 +61,34 @@ - + {31785bc3-256c-4613-b2f5-a1b0bdded8c1} Umbraco.Core + + {07fbc26b-2927-4a22-8d96-d644c667fecc} + Umbraco.Examine + {5d3b8245-ada6-453f-a008-50ed04bfe770} Umbraco.Tests + + {4c4c194c-b5e4-4991-8f87-4373e24cc19f} + Umbraco.Web.UI + {651e1350-91b6-44b7-bd60-7207006d7003} Umbraco.Web - - - $(NuGetPackageFolders.Split(';')[0]) - + + + 0.11.2 + + - - - \ No newline at end of file + diff --git a/src/Umbraco.Tests.Benchmarks/app.config b/src/Umbraco.Tests.Benchmarks/app.config index b5e577b22c..56efbc7b5f 100644 --- a/src/Umbraco.Tests.Benchmarks/app.config +++ b/src/Umbraco.Tests.Benchmarks/app.config @@ -1,298 +1,6 @@ - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/umbraco.sln b/src/umbraco.sln index ceb687b876..41bd8359c3 100644 --- a/src/umbraco.sln +++ b/src/umbraco.sln @@ -82,8 +82,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{5B03EF4E ..\build\NuSpecs\build\UmbracoCms.targets = ..\build\NuSpecs\build\UmbracoCms.targets EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Tests.Benchmarks", "Umbraco.Tests.Benchmarks\Umbraco.Tests.Benchmarks.csproj", "{86DEB346-089F-4106-89C8-D852B9CF2A33}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DocTools", "DocTools", "{53594E5B-64A2-4545-8367-E3627D266AE8}" ProjectSection(SolutionItems) = preProject ApiDocs\docfx.filter.yml = ApiDocs\docfx.filter.yml @@ -92,6 +90,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DocTools", "DocTools", "{53 ApiDocs\toc.yml = ApiDocs\toc.yml EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Tests.Benchmarks", "Umbraco.Tests.Benchmarks\Umbraco.Tests.Benchmarks.csproj", "{3A33ADC9-C6C0-4DB1-A613-A9AF0210DF3D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -120,10 +120,10 @@ Global {07FBC26B-2927-4A22-8D96-D644C667FECC}.Debug|Any CPU.Build.0 = Debug|Any CPU {07FBC26B-2927-4A22-8D96-D644C667FECC}.Release|Any CPU.ActiveCfg = Release|Any CPU {07FBC26B-2927-4A22-8D96-D644C667FECC}.Release|Any CPU.Build.0 = Release|Any CPU - {86DEB346-089F-4106-89C8-D852B9CF2A33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {86DEB346-089F-4106-89C8-D852B9CF2A33}.Debug|Any CPU.Build.0 = Debug|Any CPU - {86DEB346-089F-4106-89C8-D852B9CF2A33}.Release|Any CPU.ActiveCfg = Release|Any CPU - {86DEB346-089F-4106-89C8-D852B9CF2A33}.Release|Any CPU.Build.0 = Release|Any CPU + {3A33ADC9-C6C0-4DB1-A613-A9AF0210DF3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A33ADC9-C6C0-4DB1-A613-A9AF0210DF3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A33ADC9-C6C0-4DB1-A613-A9AF0210DF3D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A33ADC9-C6C0-4DB1-A613-A9AF0210DF3D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -133,8 +133,8 @@ Global {5D3B8245-ADA6-453F-A008-50ED04BFE770} = {B5BD12C1-A454-435E-8A46-FF4A364C0382} {E3F9F378-AFE1-40A5-90BD-82833375DBFE} = {227C3B55-80E5-4E7E-A802-BE16C5128B9D} {5B03EF4E-E0AC-4905-861B-8C3EC1A0D458} = {227C3B55-80E5-4E7E-A802-BE16C5128B9D} - {86DEB346-089F-4106-89C8-D852B9CF2A33} = {B5BD12C1-A454-435E-8A46-FF4A364C0382} {53594E5B-64A2-4545-8367-E3627D266AE8} = {FD962632-184C-4005-A5F3-E705D92FC645} + {3A33ADC9-C6C0-4DB1-A613-A9AF0210DF3D} = {B5BD12C1-A454-435E-8A46-FF4A364C0382} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7A0F2E34-D2AF-4DAB-86A0-7D7764B3D0EC} From a8fc62cf4242a7bc4f6ae4d7cf2768a6aec30ed2 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 12 Nov 2018 16:22:33 +0000 Subject: [PATCH 05/27] Optimize Guid.Combine and HexString generation. --- src/Umbraco.Core/ByteArrayExtensions.cs | 39 --------- src/Umbraco.Core/GuidUtils.cs | 44 ++++++++++ src/Umbraco.Core/HexEncoder.cs | 84 +++++++++++++++++++ .../CombinedGuidsMediaPathScheme.cs | 17 +--- src/Umbraco.Core/Umbraco.Core.csproj | 3 +- .../CombineGuidBenchmarks.cs | 48 +++++++++++ .../HexStringBenchmarks.cs | 69 +++++++++++++++ .../Umbraco.Tests.Benchmarks.csproj | 4 +- .../CoreThings/GuidUtilsTests.cs | 32 +++++++ .../CoreThings/HexEncoderTests.cs | 71 ++++++++++++++++ src/Umbraco.Tests/Umbraco.Tests.csproj | 2 + 11 files changed, 357 insertions(+), 56 deletions(-) delete mode 100644 src/Umbraco.Core/ByteArrayExtensions.cs create mode 100644 src/Umbraco.Core/GuidUtils.cs create mode 100644 src/Umbraco.Core/HexEncoder.cs create mode 100644 src/Umbraco.Tests.Benchmarks/CombineGuidBenchmarks.cs create mode 100644 src/Umbraco.Tests.Benchmarks/HexStringBenchmarks.cs create mode 100644 src/Umbraco.Tests/CoreThings/GuidUtilsTests.cs create mode 100644 src/Umbraco.Tests/CoreThings/HexEncoderTests.cs diff --git a/src/Umbraco.Core/ByteArrayExtensions.cs b/src/Umbraco.Core/ByteArrayExtensions.cs deleted file mode 100644 index dacdd509ca..0000000000 --- a/src/Umbraco.Core/ByteArrayExtensions.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace Umbraco.Core -{ - public static class ByteArrayExtensions - { - private static readonly char[] BytesToHexStringLookup = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - - public static string ToHexString(this byte[] bytes) - { - int i = 0, p = 0, bytesLength = bytes.Length; - var chars = new char[bytesLength * 2]; - while (i < bytesLength) - { - var b = bytes[i++]; - chars[p++] = BytesToHexStringLookup[b / 0x10]; - chars[p++] = BytesToHexStringLookup[b % 0x10]; - } - return new string(chars, 0, chars.Length); - } - - public static string ToHexString(this byte[] bytes, char separator, int blockSize, int blockCount) - { - int p = 0, bytesLength = bytes.Length, count = 0, size = 0; - var chars = new char[bytesLength * 2 + blockCount]; - for (var i = 0; i < bytesLength; i++) - { - var b = bytes[i++]; - chars[p++] = BytesToHexStringLookup[b / 0x10]; - chars[p++] = BytesToHexStringLookup[b % 0x10]; - if (count == blockCount) continue; - if (++size < blockSize) continue; - - chars[p++] = '/'; - size = 0; - count++; - } - return new string(chars, 0, chars.Length); - } - } -} diff --git a/src/Umbraco.Core/GuidUtils.cs b/src/Umbraco.Core/GuidUtils.cs new file mode 100644 index 0000000000..3768e1385d --- /dev/null +++ b/src/Umbraco.Core/GuidUtils.cs @@ -0,0 +1,44 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Umbraco.Core +{ + /// + /// Utility methods for the struct. + /// + internal static class GuidUtils + { + /// + /// Combines two guid instances utilizing an exclusive disjunction. + /// The resultant guid is not guaranteed to be unique since the number of unique bits is halved. + /// + /// The first guid. + /// The seconds guid. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Guid Combine(Guid a, Guid b) + { + var ad = new DecomposedGuid(a); + var bd = new DecomposedGuid(b); + + ad.Hi ^= bd.Hi; + ad.Lo ^= bd.Lo; + + return ad.Value; + } + + /// + /// A decomposed guid. Allows access to the high and low bits without unsafe code. + /// + [StructLayout(LayoutKind.Explicit)] + private struct DecomposedGuid + { + [FieldOffset(00)] public Guid Value; + [FieldOffset(00)] public long Hi; + [FieldOffset(08)] public long Lo; + + public DecomposedGuid(Guid value) : this() => this.Value = value; + } + } +} diff --git a/src/Umbraco.Core/HexEncoder.cs b/src/Umbraco.Core/HexEncoder.cs new file mode 100644 index 0000000000..073dc8b543 --- /dev/null +++ b/src/Umbraco.Core/HexEncoder.cs @@ -0,0 +1,84 @@ +using System.Linq; +using System.Runtime.CompilerServices; + +namespace Umbraco.Core +{ + /// + /// Provides methods for encoding byte arrays into hexidecimal strings. + /// + internal static class HexEncoder + { + // LUT's that provide the hexidecimal representation of each possible byte value. + private static readonly char[] HexLutBase = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + // The base LUT arranged in 16x each item order. 0 * 16, 1 * 16, .... F * 16 + private static readonly char[] HexLutHi = Enumerable.Range(0, 256).Select(x => HexLutBase[x / 0x10]).ToArray(); + + // The base LUT repeated 16x. + private static readonly char[] HexLutLo = Enumerable.Range(0, 256).Select(x => HexLutBase[x % 0x10]).ToArray(); + + /// + /// Converts a to a hexidecimal formatted padded to 2 digits. + /// + /// The bytes. + /// The . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string Encode(byte[] bytes) + { + var length = bytes.Length; + var chars = new char[length * 2]; + + var index = 0; + for (var i = 0; i < length; i++) + { + var byteIndex = bytes[i]; + chars[index++] = HexLutHi[byteIndex]; + chars[index++] = HexLutLo[byteIndex]; + } + + return new string(chars, 0, chars.Length); + } + + /// + /// Converts a to a hexidecimal formatted padded to 2 digits + /// and split into blocks with the given char separator. + /// + /// The bytes. + /// The separator. + /// The block size. + /// The block count. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string Encode(byte[] bytes, char separator, int blockSize, int blockCount) + { + var length = bytes.Length; + var chars = new char[(length * 2) + blockCount]; + var count = 0; + var size = 0; + var index = 0; + + for (var i = 0; i < length; i++) + { + var byteIndex = bytes[i]; + chars[index++] = HexLutHi[byteIndex]; + chars[index++] = HexLutLo[byteIndex]; + + if (count == blockCount) + { + continue; + } + + if (++size < blockSize) + { + continue; + } + + chars[index++] = separator; + size = 0; + count++; + } + + return new string(chars, 0, chars.Length); + } + } +} diff --git a/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs b/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs index ef71aff3bc..37c6a7b209 100644 --- a/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs +++ b/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs @@ -20,24 +20,11 @@ namespace Umbraco.Core.IO.MediaPathSchemes { // assumes that cuid and puid keys can be trusted - and that a single property type // for a single content cannot store two different files with the same name - var directory = Combine(itemGuid, propertyGuid).ToHexString(/*'/', 2, 4*/); // could use ext to fragment path eg 12/e4/f2/... + var directory = HexEncoder.Encode(GuidUtils.Combine(itemGuid, propertyGuid).ToByteArray()/*'/', 2, 4*/); // could use ext to fragment path eg 12/e4/f2/... return Path.Combine(directory, filename).Replace('\\', '/'); } /// - public string GetDeleteDirectory(string filepath) - { - return Path.GetDirectoryName(filepath); - } - - private static byte[] Combine(Guid guid1, Guid guid2) - { - var bytes1 = guid1.ToByteArray(); - var bytes2 = guid2.ToByteArray(); - var bytes = new byte[bytes1.Length]; - for (var i = 0; i < bytes1.Length; i++) - bytes[i] = (byte) (bytes1[i] ^ bytes2[i]); - return bytes; - } + public string GetDeleteDirectory(string filepath) => Path.GetDirectoryName(filepath); } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index ac115e843b..49fa197850 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -111,7 +111,6 @@ - @@ -320,6 +319,8 @@ + + diff --git a/src/Umbraco.Tests.Benchmarks/CombineGuidBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/CombineGuidBenchmarks.cs new file mode 100644 index 0000000000..ce55f6890d --- /dev/null +++ b/src/Umbraco.Tests.Benchmarks/CombineGuidBenchmarks.cs @@ -0,0 +1,48 @@ +using System; +using BenchmarkDotNet.Attributes; +using Umbraco.Core; +using Umbraco.Tests.Benchmarks.Config; + +namespace Umbraco.Tests.Benchmarks +{ + [QuickRunWithMemoryDiagnoserConfig] + public class CombineGuidBenchmarks + { + private static readonly Guid _a = Guid.NewGuid(); + private static readonly Guid _b = Guid.NewGuid(); + + [Benchmark] + public byte[] CombineUtils() => GuidUtils.Combine(_a, _b).ToByteArray(); + + [Benchmark] + public byte[] CombineLoop() => Combine(_a, _b); + + private static byte[] Combine(Guid guid1, Guid guid2) + { + var bytes1 = guid1.ToByteArray(); + var bytes2 = guid2.ToByteArray(); + var bytes = new byte[bytes1.Length]; + for (var i = 0; i < bytes1.Length; i++) + { + bytes[i] = (byte)(bytes1[i] ^ bytes2[i]); + } + + return bytes; + } + } + + // Nov 8 2018 + //BenchmarkDotNet=v0.11.2, OS=Windows 10.0.17763.55 (1809/October2018Update/Redstone5) + //Intel Core i7-6600U CPU 2.60GHz(Skylake), 1 CPU, 4 logical and 2 physical cores + // [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.3190.0 + // Job-JIATTD : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.3190.0 + + //IterationCount=3 IterationTime=100.0000 ms LaunchCount = 1 + //WarmupCount=3 + + // Method | Mean | Error | StdDev | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | + //------------- |---------:|----------:|----------:|------------:|------------:|------------:|--------------------:| + // CombineUtils | 33.34 ns | 8.086 ns | 0.4432 ns | 0.0133 | - | - | 28 B | + // CombineLoop | 55.03 ns | 11.311 ns | 0.6200 ns | 0.0395 | - | - | 84 B | +} + diff --git a/src/Umbraco.Tests.Benchmarks/HexStringBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/HexStringBenchmarks.cs new file mode 100644 index 0000000000..e29a5a24f3 --- /dev/null +++ b/src/Umbraco.Tests.Benchmarks/HexStringBenchmarks.cs @@ -0,0 +1,69 @@ +using System; +using System.Text; +using BenchmarkDotNet.Attributes; +using Umbraco.Core; +using Umbraco.Tests.Benchmarks.Config; + +namespace Umbraco.Tests.Benchmarks +{ + [QuickRunConfig] + public class HexStringBenchmarks + { + private byte[] _buffer; + + [Params(8, 16, 32, 64, 128, 256)] + public int Count { get; set; } + + [GlobalSetup] + public void Setup() + { + this._buffer = new byte[this.Count]; + var random = new Random(); + random.NextBytes(this._buffer); + } + + [Benchmark(Baseline = true)] + public string ToHexStringBuilder() + { + var sb = new StringBuilder(this._buffer.Length * 2); + for (var i = 0; i < this._buffer.Length; i++) + { + sb.Append(this._buffer[i].ToString("X2")); + } + + return sb.ToString(); + } + + [Benchmark] + public string ToHexStringEncoder() => HexEncoder.Encode(this._buffer); + } + + // Nov 8 2018 + //BenchmarkDotNet=v0.11.2, OS=Windows 10.0.17763.55 (1809/October2018Update/Redstone5) + //Intel Core i7-6600U CPU 2.60GHz(Skylake), 1 CPU, 4 logical and 2 physical cores + // [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.3190.0 + // Job-JIATTD : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.3190.0 + + //IterationCount=3 IterationTime=100.0000 ms LaunchCount = 1 + //WarmupCount=3 + + // Method | Count | Mean | Error | StdDev | Ratio | + //------------------- |------ |-------------:|-------------:|-----------:|------:| + // ToHexStringBuilder | 8 | 786.49 ns | 319.92 ns | 17.536 ns | 1.00 | + // ToHexStringEncoder | 8 | 64.19 ns | 30.21 ns | 1.656 ns | 0.08 | + // | | | | | | + // ToHexStringBuilder | 16 | 1,442.43 ns | 503.00 ns | 27.571 ns | 1.00 | + // ToHexStringEncoder | 16 | 133.46 ns | 177.55 ns | 9.732 ns | 0.09 | + // | | | | | | + // ToHexStringBuilder | 32 | 2,869.23 ns | 924.35 ns | 50.667 ns | 1.00 | + // ToHexStringEncoder | 32 | 181.03 ns | 96.64 ns | 5.297 ns | 0.06 | + // | | | | | | + // ToHexStringBuilder | 64 | 5,775.33 ns | 2,825.42 ns | 154.871 ns | 1.00 | + // ToHexStringEncoder | 64 | 331.16 ns | 125.63 ns | 6.886 ns | 0.06 | + // | | | | | | + // ToHexStringBuilder | 128 | 11,662.35 ns | 4,908.03 ns | 269.026 ns | 1.00 | + // ToHexStringEncoder | 128 | 633.78 ns | 57.56 ns | 3.155 ns | 0.05 | + // | | | | | | + // ToHexStringBuilder | 256 | 22,960.11 ns | 14,111.47 ns | 773.497 ns | 1.00 | + // ToHexStringEncoder | 256 | 1,224.76 ns | 547.27 ns | 29.998 ns | 0.05 | +} diff --git a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj index 99bb768842..e5bc3e88b0 100644 --- a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj +++ b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj @@ -46,10 +46,12 @@ + + @@ -91,4 +93,4 @@ - + \ No newline at end of file diff --git a/src/Umbraco.Tests/CoreThings/GuidUtilsTests.cs b/src/Umbraco.Tests/CoreThings/GuidUtilsTests.cs new file mode 100644 index 0000000000..5ef8cba356 --- /dev/null +++ b/src/Umbraco.Tests/CoreThings/GuidUtilsTests.cs @@ -0,0 +1,32 @@ +using System; +using NUnit.Framework; +using Umbraco.Core; + +namespace Umbraco.Tests.CoreThings +{ + public class GuidUtilsTests + { + [Test] + public void GuidCombineMethodsAreEqual() + { + var a = Guid.NewGuid(); + var b = Guid.NewGuid(); + + Assert.AreEqual(GuidUtils.Combine(a, b).ToByteArray(), Combine(a, b)); + } + + // Reference implementation taken from original code. + private static byte[] Combine(Guid guid1, Guid guid2) + { + var bytes1 = guid1.ToByteArray(); + var bytes2 = guid2.ToByteArray(); + var bytes = new byte[bytes1.Length]; + for (var i = 0; i < bytes1.Length; i++) + { + bytes[i] = (byte)(bytes1[i] ^ bytes2[i]); + } + + return bytes; + } + } +} diff --git a/src/Umbraco.Tests/CoreThings/HexEncoderTests.cs b/src/Umbraco.Tests/CoreThings/HexEncoderTests.cs new file mode 100644 index 0000000000..588fff83e8 --- /dev/null +++ b/src/Umbraco.Tests/CoreThings/HexEncoderTests.cs @@ -0,0 +1,71 @@ +using System; +using System.Text; +using NUnit.Framework; +using Umbraco.Core; + +namespace Umbraco.Tests.CoreThings +{ + public class HexEncoderTests + { + [Test] + public void ToHexStringCreatesCorrectValue() + { + var buffer = new byte[255]; + var random = new Random(); + random.NextBytes(buffer); + + var sb = new StringBuilder(buffer.Length * 2); + for (var i = 0; i < buffer.Length; i++) + { + sb.Append(buffer[i].ToString("X2")); + } + + var expected = sb.ToString(); + + var actual = HexEncoder.Encode(buffer); + Assert.AreEqual(expected, actual); + } + + [Test] + public void ToHexStringWithSeparatorCreatesCorrectValue() + { + var buffer = new byte[255]; + var random = new Random(); + random.NextBytes(buffer); + + var expected = ToHexString(buffer, '/', 2, 4); + var actual = HexEncoder.Encode(buffer, '/', 2, 4); + + Assert.AreEqual(expected, actual); + } + + private static readonly char[] _bytesToHexStringLookup = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + // Reference implementation taken from original extension method. + private static string ToHexString(byte[] bytes, char separator, int blockSize, int blockCount) + { + int p = 0, bytesLength = bytes.Length, count = 0, size = 0; + var chars = new char[(bytesLength * 2) + blockCount]; + for (var i = 0; i < bytesLength; i++) + { + var b = bytes[i]; + chars[p++] = _bytesToHexStringLookup[b / 0x10]; + chars[p++] = _bytesToHexStringLookup[b % 0x10]; + if (count == blockCount) + { + continue; + } + + if (++size < blockSize) + { + continue; + } + + chars[p++] = separator; + size = 0; + count++; + } + return new string(chars, 0, chars.Length); + } + } +} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 156bc06a14..8d3da825f5 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -118,6 +118,8 @@ + + From 10f6f8df909810a42bcec3bb7b207f3a9867f95b Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Thu, 15 Nov 2018 22:22:15 +0000 Subject: [PATCH 06/27] Show relations in edit view --- .../views/relationtypes/edit.controller.js | 18 +++++-- .../src/views/relationtypes/edit.html | 45 ++++++---------- .../Editors/RelationTypeController.cs | 7 ++- .../Models/ContentEditing/Relation.cs | 4 +- .../Models/ContentEditing/RelationDisplay.cs | 52 +++++++++++++++++++ .../ContentEditing/RelationTypeDisplay.cs | 9 ++++ .../Models/Mapping/RelationMapperProfile.cs | 4 ++ .../Trees/RelationTypeTreeController.cs | 6 +-- src/Umbraco.Web/Umbraco.Web.csproj | 1 + 9 files changed, 108 insertions(+), 38 deletions(-) create mode 100644 src/Umbraco.Web/Models/ContentEditing/RelationDisplay.cs diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js index 37eb1ea6d9..290117850c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js @@ -1,4 +1,4 @@ -function RelationTypeEditController($scope, $routeParams, relationTypeResource, editorState, navigationService) { +function RelationTypeEditController($scope, $routeParams, relationTypeResource, editorState, navigationService, dateHelper, userService) { var vm = this; @@ -14,17 +14,29 @@ function RelationTypeEditController($scope, $routeParams, relationTypeResource, relationTypeResource.getById($routeParams.id) .then(function(data) { - vm.relation = data; + vm.relationType = data; - editorState.set(vm.relation); + editorState.set(vm.relationType); navigationService.syncTree({ tree: "relationTypes", path: data.path, forceReload: true }).then(function (syncArgs) { vm.page.menu.currentNode = syncArgs.node; }); + formatDates(vm.relationType.relations); + vm.page.loading = false; }); } + + function formatDates(relations) { + if(relations) { + userService.getCurrentUser().then(function (currentUser) { + angular.forEach(relations, function (relation) { + relation.timestampFormatted = dateHelper.getLocalDate(relation.createDate, currentUser.locale, 'LLL'); + }); + }); + } + } } angular.module("umbraco").controller("Umbraco.Editors.RelationTypes.EditController", RelationTypeEditController); diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html index 3f88c914f4..c822c90a15 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html @@ -4,8 +4,8 @@ @@ -15,8 +15,8 @@ -
{{vm.relation.id}}
- {{vm.relation.key}} +
{{vm.relationType.id}}
+ {{vm.relationType.key}}
@@ -24,12 +24,12 @@
@@ -37,23 +37,22 @@ -
{{vm.relation.parentObjectTypeName}}
+
{{vm.relationType.parentObjectTypeName}}
-
{{vm.relation.childObjectTypeName}}
+
{{vm.relationType.childObjectTypeName}}
- -
12
+ +
{{vm.relationType.relations.length}}
- +
- @@ -61,23 +60,11 @@ - - - - - - - - - - - - - - - - - + + + + +
ParentCreated Comment
SomethingSomething else2018-10-27 18:58A comment here
SomethingSomething else2018-10-27 18:58A comment here
SomethingSomething else2018-10-27 18:58A comment here
{{relation.parentId}}{{relation.childId}}{{relation.timestampFormatted}}{{relation.comment}}
diff --git a/src/Umbraco.Web/Editors/RelationTypeController.cs b/src/Umbraco.Web/Editors/RelationTypeController.cs index 2b9242ef31..552f3601e9 100644 --- a/src/Umbraco.Web/Editors/RelationTypeController.cs +++ b/src/Umbraco.Web/Editors/RelationTypeController.cs @@ -35,8 +35,13 @@ namespace Umbraco.Web.Editors { throw new HttpResponseException(HttpStatusCode.NotFound); } + + var relations = Services.RelationService.GetByRelationTypeId(relationType.Id); - return Mapper.Map(relationType); + var display = Mapper.Map(relationType); + display.Relations = Mapper.Map, IEnumerable>(relations); + + return display; } public void PostSave() diff --git a/src/Umbraco.Web/Models/ContentEditing/Relation.cs b/src/Umbraco.Web/Models/ContentEditing/Relation.cs index b166c67f55..2b012dc750 100644 --- a/src/Umbraco.Web/Models/ContentEditing/Relation.cs +++ b/src/Umbraco.Web/Models/ContentEditing/Relation.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.Text; @@ -6,6 +7,7 @@ using System.Threading.Tasks; namespace Umbraco.Web.Models.ContentEditing { + [Obsolete("Use Umbraco.Web.Models.ContentEditing.RelationDisplay instead")] [DataContract(Name = "relation", Namespace = "")] public class Relation { diff --git a/src/Umbraco.Web/Models/ContentEditing/RelationDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/RelationDisplay.cs new file mode 100644 index 0000000000..24ebabc615 --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/RelationDisplay.cs @@ -0,0 +1,52 @@ +using System; +using System.ComponentModel; +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models.ContentEditing +{ + [DataContract(Name = "relation", Namespace = "")] + public class RelationDisplay + { + /// + /// Gets or sets the Parent Id of the Relation (Source). + /// + [DataMember(Name = "parentId")] + [ReadOnly(true)] + public int ParentId { get; set; } + + /// + /// Gets or sets the Parent Name of the relation (Source). + /// + [DataMember(Name = "parentName")] + [ReadOnly(true)] + public string ParentName { get; set; } + + /// + /// Gets or sets the Child Id of the Relation (Destination). + /// + [DataMember(Name = "childId")] + [ReadOnly(true)] + public int ChildId { get; set; } + + /// + /// Gets or sets the Child Name of the relation (Destination). + /// + [DataMember(Name = "childName")] + [ReadOnly(true)] + public string ChildName { get; set; } + + /// + /// Gets or sets the date when the Relation was created. + /// + [DataMember(Name = "createDate")] + [ReadOnly(true)] + public DateTime CreateDate { get; set; } + + /// + /// Gets or sets a comment for the Relation. + /// + [DataMember(Name = "comment")] + [ReadOnly(true)] + public string Comment { get; set; } + } +} diff --git a/src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs index 3861e0938d..4873d2288d 100644 --- a/src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs @@ -1,4 +1,6 @@ using System; +using System.Collections; +using System.Collections.Generic; using System.ComponentModel; using System.Runtime.Serialization; @@ -40,5 +42,12 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "childObjectTypeName")] [ReadOnly(true)] public string ChildObjectTypeName { get; set; } + + /// + /// Gets or sets the relations associated with this relation type. + /// + [DataMember(Name = "relations")] + [ReadOnly(true)] + public IEnumerable Relations { get; set; } } } diff --git a/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs index 95f4fab054..e56fd2ad3b 100644 --- a/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs @@ -20,6 +20,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(x => x.AdditionalData, expression => expression.Ignore()) .ForMember(x => x.ChildObjectTypeName, expression => expression.Ignore()) .ForMember(x => x.ParentObjectTypeName, expression => expression.Ignore()) + .ForMember(x => x.Relations, expression => expression.Ignore()) .ForMember( x => x.Udi, expression => expression.MapFrom( @@ -34,6 +35,9 @@ namespace Umbraco.Web.Models.Mapping dest.ChildObjectTypeName = ObjectTypes.GetUmbracoObjectType(src.ChildObjectType).GetFriendlyName(); }); + // FROM IRelation to RelationDisplay + CreateMap(); + //FROM IRelationType TO RelationType CreateMap(); diff --git a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs index 884b6c5f54..5dbe18a690 100644 --- a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs @@ -24,10 +24,8 @@ 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")); + menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)); + //refresh action menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 7e51974bc9..76ea0d92cf 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -148,6 +148,7 @@ + From d019ba81f3ba8aae56e9350c4059159db1d0cdc6 Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Thu, 15 Nov 2018 22:34:43 +0000 Subject: [PATCH 07/27] Get relation names --- .../src/views/relationtypes/edit.controller.js | 16 +++++++++++++++- .../src/views/relationtypes/edit.html | 4 ++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js index 290117850c..11e8321350 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js @@ -1,4 +1,4 @@ -function RelationTypeEditController($scope, $routeParams, relationTypeResource, editorState, navigationService, dateHelper, userService) { +function RelationTypeEditController($scope, $routeParams, relationTypeResource, editorState, navigationService, dateHelper, userService, entityResource) { var vm = this; @@ -23,6 +23,7 @@ function RelationTypeEditController($scope, $routeParams, relationTypeResource, }); formatDates(vm.relationType.relations); + getRelationNames(vm.relationType); vm.page.loading = false; }); @@ -37,6 +38,19 @@ function RelationTypeEditController($scope, $routeParams, relationTypeResource, }); } } + + function getRelationNames(relationType) { + if(relationType.relations) { + angular.forEach(relationType.relations, function(relation){ + entityResource.getById(relation.parentId, relationType.parentObjectTypeName).then(function(entity) { + relation.parentName = entity.name; + }); + entityResource.getById(relation.childId, relationType.childObjectTypeName).then(function(entity) { + relation.childName = entity.name; + }); + }); + } + } } angular.module("umbraco").controller("Umbraco.Editors.RelationTypes.EditController", RelationTypeEditController); diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html index c822c90a15..1a1bcfe6c9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html @@ -61,8 +61,8 @@ Comment - {{relation.parentId}} - {{relation.childId}} + {{relation.parentName}} + {{relation.childName}} {{relation.timestampFormatted}} {{relation.comment}} From 738b42964d7b204872433e981a307d1e7241e705 Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Tue, 20 Nov 2018 23:15:16 +0000 Subject: [PATCH 08/27] Added save action --- .../common/resources/relationtype.resource.js | 34 +++++++++++-- .../services/umbdataformatter.service.js | 16 ++++++ .../views/relationtypes/edit.controller.js | 49 ++++++++++++++----- .../src/views/relationtypes/edit.html | 3 +- .../Editors/RelationTypeController.cs | 27 +++++++++- .../ContentEditing/RelationTypeDisplay.cs | 14 +++++- .../Models/ContentEditing/RelationTypeSave.cs | 14 ++++++ .../Models/Mapping/RelationMapperProfile.cs | 3 ++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + 9 files changed, 141 insertions(+), 20 deletions(-) create mode 100644 src/Umbraco.Web/Models/ContentEditing/RelationTypeSave.cs diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js index 81fdbdb838..e4a59d01d5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js @@ -3,14 +3,26 @@ * @name umbraco.resources.relationTypeResource * @description Loads in data for relation types. */ -function relationTypeResource($q, $http, umbRequestHelper) { +function relationTypeResource($q, $http, umbRequestHelper, umbDataFormatter) { return { /** * @ngdoc method * @name umbraco.resources.relationTypeResource#getById * @methodOf umbraco.resources.relationTypeResource - * @param {Int} id of the dictionary item to get. + * + * @description + * Gets a relation type with a given ID. + * + * ##usage + *
+         * relationTypeResource.getById(1234)
+         *    .then(function() {
+         *        alert('Found it!');
+         *    });
+         * 
+ * + * @param {Int} id of the relation type to get. * @returns {Promise} resourcePromise containing relation type data. */ getById: function (id) { @@ -26,8 +38,24 @@ function relationTypeResource($q, $http, umbRequestHelper) { ); }, - save: function () { + /** + * @ngdoc method + * @name umbraco.resources.relationTypeResource#save + * @methodof umbraco.resources.relationTypeResource + * + * @description + * Updates a relation type. + * + * @param {Object} relationType The relation type object to update. + * @returns {Promise} A resourcePromise object. + */ + save: function (relationType) { + var saveModel = umbDataFormatter.formatRelationTypePostData(relationType); + return umbRequestHelper.resourcePromise( + $http.post(umbRequestHelper.getApiUrl("relationTypeApiBaseUrl", "PostSave"), saveModel), + "Failed to save data for relation type ID" + relationType.id + ); }, deleteById: function (id) { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js index b18cb73eae..d7c071f039 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js @@ -429,6 +429,22 @@ } return displayModel; + }, + + /** + * Formats the display model used to display the relation type to a model used to save the relation type. + * @param {Object} relationType + */ + formatRelationTypePostData : function(relationType) { + var saveModel = { + id: relationType.id, + name: relationType.name, + alias: relationType.alias, + key : relationType.key, + isBidirectional: relationType.isBidirectional + }; + + return saveModel; } }; } diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js index 11e8321350..0ec6e18214 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js @@ -1,4 +1,4 @@ -function RelationTypeEditController($scope, $routeParams, relationTypeResource, editorState, navigationService, dateHelper, userService, entityResource) { +function RelationTypeEditController($scope, $routeParams, relationTypeResource, editorState, navigationService, dateHelper, userService, entityResource, formHelper, contentEditingHelper) { var vm = this; @@ -7,6 +7,8 @@ function RelationTypeEditController($scope, $routeParams, relationTypeResource, vm.page.saveButtonState = "init"; vm.page.menu = {} + vm.save = saveRelationType; + if($routeParams.create) { alert("create"); } else { @@ -14,21 +16,24 @@ function RelationTypeEditController($scope, $routeParams, relationTypeResource, relationTypeResource.getById($routeParams.id) .then(function(data) { - vm.relationType = data; - - editorState.set(vm.relationType); - - navigationService.syncTree({ tree: "relationTypes", path: data.path, forceReload: true }).then(function (syncArgs) { - vm.page.menu.currentNode = syncArgs.node; - }); - - formatDates(vm.relationType.relations); - getRelationNames(vm.relationType); - + bindRelationType(data); vm.page.loading = false; }); } + function bindRelationType(relationType) { + formatDates(relationType.relations); + getRelationNames(relationType); + + vm.relationType = relationType; + + editorState.set(vm.relationType); + + navigationService.syncTree({ tree: "relationTypes", path: relationType.path, forceReload: true }).then(function (syncArgs) { + vm.page.menu.currentNode = syncArgs.node; + }); + } + function formatDates(relations) { if(relations) { userService.getCurrentUser().then(function (currentUser) { @@ -51,6 +56,26 @@ function RelationTypeEditController($scope, $routeParams, relationTypeResource, }); } } + + function saveRelationType() { + vm.page.saveButtonState = "busy"; + + if (formHelper.submitForm({ scope: $scope, statusMessage: "Saving..." })) { + relationTypeResource.save(vm.relationType).then(function (data) { + formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + bindRelationType(data); + vm.page.saveButtonState = "success"; + }, function (error) { + contentEditingHelper.handleSaveError({ + redirectOnFailure: false, + err: error + }); + + notificationsService.error(error.data.message); + vm.page.saveButtonState = "error"; + }); + } + } } angular.module("umbraco").controller("Umbraco.Editors.RelationTypes.EditController", RelationTypeEditController); diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html index 1a1bcfe6c9..bd7b073957 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html @@ -1,7 +1,7 @@
- + diff --git a/src/Umbraco.Web/Editors/RelationTypeController.cs b/src/Umbraco.Web/Editors/RelationTypeController.cs index 552f3601e9..e2466fef9c 100644 --- a/src/Umbraco.Web/Editors/RelationTypeController.cs +++ b/src/Umbraco.Web/Editors/RelationTypeController.cs @@ -9,6 +9,7 @@ using AutoMapper; using Umbraco.Core.Models; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; @@ -44,9 +45,31 @@ namespace Umbraco.Web.Editors return display; } - public void PostSave() + public RelationTypeDisplay PostSave(RelationTypeSave relationType) { - throw new NotImplementedException(); + var relationTypePersisted = Services.RelationService.GetRelationTypeById(relationType.Key); + + if (relationTypePersisted == null) + { + // TODO: Translate message + throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("Relation type does not exist")); + } + + Mapper.Map(relationType, relationTypePersisted); + + try + { + Services.RelationService.Save(relationTypePersisted); + var display = Mapper.Map(relationTypePersisted); + display.AddSuccessNotification("Relation type saved", ""); + + return display; + } + catch (Exception ex) + { + Logger.Error(GetType(), ex, "Error saving relation type with {Id}", relationType.Id); + throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("Something went wrong when saving the relation type")); + } } public void DeleteById() diff --git a/src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs index 4873d2288d..c443175260 100644 --- a/src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.Serialization; @@ -7,8 +6,13 @@ using System.Runtime.Serialization; namespace Umbraco.Web.Models.ContentEditing { [DataContract(Name = "relationType", Namespace = "")] - public class RelationTypeDisplay : EntityBasic + public class RelationTypeDisplay : EntityBasic, INotificationModel { + public RelationTypeDisplay() + { + Notifications = new List(); + } + /// /// Gets or sets a boolean indicating whether the RelationType is Bidirectional (true) or Parent to Child (false) /// @@ -49,5 +53,11 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "relations")] [ReadOnly(true)] public IEnumerable Relations { get; set; } + + /// + /// This is used to add custom localized messages/strings to the response for the app to use for localized UI purposes. + /// + [DataMember(Name = "notifications")] + public List Notifications { get; private set; } } } diff --git a/src/Umbraco.Web/Models/ContentEditing/RelationTypeSave.cs b/src/Umbraco.Web/Models/ContentEditing/RelationTypeSave.cs new file mode 100644 index 0000000000..df118f37ee --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/RelationTypeSave.cs @@ -0,0 +1,14 @@ +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models.ContentEditing +{ + [DataContract(Name = "relationType", Namespace = "")] + public class RelationTypeSave : EntityBasic + { + /// + /// Gets or sets a boolean indicating whether the RelationType is Bidirectional (true) or Parent to Child (false) + /// + [DataMember(Name = "isBidirectional", IsRequired = true)] + public bool IsBidirectional { get; set; } + } +} diff --git a/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs index e56fd2ad3b..5a4f9cd9a3 100644 --- a/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs @@ -38,6 +38,9 @@ namespace Umbraco.Web.Models.Mapping // FROM IRelation to RelationDisplay CreateMap(); + // FROM RelationTypeSave to IRelationType + CreateMap(); + //FROM IRelationType TO RelationType CreateMap(); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 76ea0d92cf..04d0765598 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -150,6 +150,7 @@ + From 5872b6de22ca63a0ae15e41ad21160a086008ee5 Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Thu, 22 Nov 2018 14:19:40 +0000 Subject: [PATCH 09/27] Prototyped create view --- .../views/relationtypes/create.controller.js | 5 ++ .../src/views/relationtypes/create.html | 62 +++++++++++++++++++ .../Trees/RelationTypeTreeController.cs | 2 +- 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js new file mode 100644 index 0000000000..b59cd4aa71 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js @@ -0,0 +1,5 @@ +function RelationTypeCreateController($scope) { + var vm = this; +} + +angular.module("umbraco").controller("Umbraco.Editors.RelationTypes.CreateController", RelationTypeCreateController); diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html new file mode 100644 index 0000000000..43988f4ad9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html @@ -0,0 +1,62 @@ + + + diff --git a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs index 5dbe18a690..096c7a6870 100644 --- a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs @@ -24,7 +24,7 @@ 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.Localize("actions", ActionNew.Instance.Alias)); //refresh action menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); From 12d11b7c88f879b268de65a39611b66b497903ae Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Thu, 29 Nov 2018 22:07:17 +0000 Subject: [PATCH 10/27] Render create view Load object types from API --- .../common/resources/relationtype.resource.js | 19 +++++++++ .../views/relationtypes/create.controller.js | 40 ++++++++++++++++++- .../src/views/relationtypes/create.html | 32 +++++++-------- .../Editors/RelationTypeController.cs | 24 +++++++++++ .../Models/ContentEditing/ObjectType.cs | 15 +++++++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + 6 files changed, 112 insertions(+), 19 deletions(-) create mode 100644 src/Umbraco.Web/Models/ContentEditing/ObjectType.cs diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js index e4a59d01d5..3112d7378b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js @@ -38,6 +38,25 @@ function relationTypeResource($q, $http, umbRequestHelper, umbDataFormatter) { ); }, + /** + * @ngdoc method + * @name umbraco.resources.relationTypeResource#getRelationObjectTypes + * @methodof umbraco.resources.relationTypeResource + * + * @description + * Gets a list of Umbraco object types which can be associated with a relation. + * + * @returns {Object} A collection of Umbraco object types. + */ + getRelationObjectTypes: function() { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl("relationTypeApiBaseUrl", "GetRelationObjectTypes") + ), + "Failed to get object types" + ); + }, + /** * @ngdoc method * @name umbraco.resources.relationTypeResource#save diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js index b59cd4aa71..b7389c0e56 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js @@ -1,5 +1,43 @@ -function RelationTypeCreateController($scope) { +function RelationTypeCreateController($scope, relationTypeResource, navigationService, formHelper, appState) { var vm = this; + vm.relationType = {}; + vm.objectTypes = {}; + + vm.createRelationType = createRelationType; + + init(); + + function init() { + relationTypeResource.getRelationObjectTypes().then(function (data) { + vm.objectTypes = data; + }, function (err) { + alert("oh no"); + }) + } + + function createRelationType() { + if (formHelper.submitForm({ scope: $scope, formCtrl: this.createRelationTypeForm, statusMessage: "Creating relation type..." })) { + var node = $scope.dialogOptions.currentNode; + + relationTypeResource.create(vm.relationType).then(function (data) { + navigationService.hideMenu(); + + // Set the new item as active in the tree + var currentPath = node.path ? node.path : "-1"; + navigationService.syncTree({ tree: "relationType", path: currentPath + "," + data, forceReload: true, activate: true }); + + formHelper.resetForm({ scope: $scope }); + + var currentSection = appState.getSectionState("currentSection"); + $location.path("/" + currentSection + "/relationTypes/edit/" + data); + }, function (err) { + if (err.data && err.data.message) { + notificationsService.error(err.data.message); + navigationService.hideMenu(); + } + }); + } + } } angular.module("umbraco").controller("Umbraco.Editors.RelationTypes.CreateController", RelationTypeCreateController); diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html index 43988f4ad9..1d07c8e1b4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html @@ -1,9 +1,9 @@
[DataMember(Name = "isBidirectional", IsRequired = true)] public bool IsBidirectional { get; set; } + + /// + /// Gets or sets the parent object type ID. + /// + [DataMember(Name = "parentObjectType", IsRequired = false)] + public Guid ParentObjectType { get; set; } + + /// + /// Gets or sets the child object type ID. + /// + [DataMember(Name = "childObjectType", IsRequired = false)] + public Guid ChildObjectType { get; set; } } } From a6ab47150520b8d2a09374a6cf46af29bb7bc116 Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Fri, 30 Nov 2018 14:09:48 +0000 Subject: [PATCH 12/27] Added delete endpoint. Updated tree controller to use Angular delete view --- .../src/views/relationtypes/delete.html | 0 .../Editors/RelationTypeController.cs | 18 ++++++++++++++++-- .../Trees/RelationTypeTreeController.cs | 19 +++++++------------ 3 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.html diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Umbraco.Web/Editors/RelationTypeController.cs b/src/Umbraco.Web/Editors/RelationTypeController.cs index 3751dd5bcf..05de96699d 100644 --- a/src/Umbraco.Web/Editors/RelationTypeController.cs +++ b/src/Umbraco.Web/Editors/RelationTypeController.cs @@ -126,9 +126,23 @@ namespace Umbraco.Web.Editors } } - public void DeleteById() + /// + /// Deletes a relation type with a given ID. + /// + /// The ID of the relation type to delete. + /// A . + [HttpPost] + [HttpDelete] + public HttpResponseMessage DeleteById(int id) { - throw new NotImplementedException(); + var relationType = Services.RelationService.GetRelationTypeById(id); + + if(relationType == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + Services.RelationService.Delete(relationType); + + return Request.CreateResponse(HttpStatusCode.OK); } } } diff --git a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs index 096c7a6870..6131ca8646 100644 --- a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs @@ -34,9 +34,10 @@ namespace Umbraco.Web.Trees var relationType = Services.RelationService.GetRelationTypeById(int.Parse(id)); if (relationType == null) return new MenuItemCollection(); + + menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)); - //add delete option for all macros - menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)) + /*menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)) //Since we haven't implemented anything for relationtypes in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(new EntitySlim @@ -45,7 +46,7 @@ namespace Umbraco.Web.Trees Level = 1, ParentId = -1, Name = relationType.Name - }, "relationTypes", queryStrings.GetValue("application")); + }, "relationTypes", queryStrings.GetValue("application"));*/ return menu; } @@ -56,15 +57,9 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { - nodes.AddRange(Services.RelationService - .GetAllRelationTypes().Select(rt => CreateTreeNode( - rt.Id.ToString(), - id, - queryStrings, - rt.Name, - "icon-trafic", - false - ))); + nodes.AddRange(Services.RelationService.GetAllRelationTypes() + .Select(rt => CreateTreeNode(rt.Id.ToString(), id, queryStrings, rt.Name, + "icon-trafic", false))); } return nodes; } From 2dfcb8ed4e48e62585bb79de36095ff5f695d12e Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Sun, 2 Dec 2018 18:10:03 +0000 Subject: [PATCH 13/27] Completed delete action --- .../common/resources/relationtype.resource.js | 31 ++++++++++++----- .../views/relationtypes/delete.controller.js | 33 +++++++++++++++++++ .../src/views/relationtypes/delete.html | 12 +++++++ 3 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.controller.js diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js index 4035ce0994..f17aae0a6b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/relationtype.resource.js @@ -27,13 +27,7 @@ function relationTypeResource($q, $http, umbRequestHelper, umbDataFormatter) { */ getById: function (id) { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "relationTypeApiBaseUrl", - "GetById", - [{ id: id }] - ) - ), + $http.get(umbRequestHelper.getApiUrl("relationTypeApiBaseUrl", "GetById", [{ id: id }])), "Failed to get item " + id ); }, @@ -97,8 +91,29 @@ function relationTypeResource($q, $http, umbRequestHelper, umbDataFormatter) { ); }, + /** + * @ngdoc method + * @name umbraco.resources.relationTypeResource#deleteById + * @methodof umbraco.resources.relationTypeResource + * + * @description + * Deletes a relation type with a given ID. + * + * * ## Usage + *
+         * relationTypeResource.deleteById(1234).then(function() {
+         *    alert('Deleted it!');
+         * });
+         * 
+ * + * @param {Int} id The ID of the relation type to delete. + * @returns {Promose} resourcePromise object. + */ deleteById: function (id) { - + return umbRequestHelper.resourcePromise( + $http.post(umbRequestHelper.getApiUrl("relationTypeApiBaseUrl", "DeleteById", [{ id: id }])), + "Failed to delete item " + id + ); } }; diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.controller.js new file mode 100644 index 0000000000..ead951ae3a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.controller.js @@ -0,0 +1,33 @@ +function RelationTypeDeleteController($scope, $location, relationTypeResource, treeService, navigationService, appState) { + + var vm = this; + + vm.cancel = cancel; + vm.performDelete = performDelete; + + function cancel() { + navigationService.hideDialog(); + } + + function performDelete() { + // stop from firing again on double-click + if ($scope.busy) { return false; } + + //mark it for deletion (used in the UI) + $scope.currentNode.loading = true; + $scope.busy = true; + + relationTypeResource.deleteById($scope.currentNode.id).then(function () { + $scope.currentNode.loading = false; + + treeService.removeNode($scope.currentNode); + + navigationService.hideMenu(); + + var currentSection = appState.getSectionState("currentSection"); + $location.path("/" + currentSection + "/"); + }); + } +} + +angular.module("umbraco").controller("Umbraco.Editors.RelationTypes.DeleteController", RelationTypeDeleteController); diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.html index e69de29bb2..e0fdbc6751 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.html +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.html @@ -0,0 +1,12 @@ +
+
+ +

+ Are you sure you want to delete {{currentNode.name}}? +

+ + + + +
+
From 4617c0c24fac1967fdd445e1ce3f6e29e707505e Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Sun, 2 Dec 2018 18:17:20 +0000 Subject: [PATCH 14/27] Tidy up - remove obsoleted classes --- .../views/relationtypes/create.controller.js | 8 ++++ .../views/relationtypes/delete.controller.js | 8 ++++ .../views/relationtypes/edit.controller.js | 8 ++++ src/Umbraco.Web/Editors/RelationController.cs | 16 +++---- .../Models/ContentEditing/Relation.cs | 45 ------------------- .../Models/ContentEditing/RelationType.cs | 43 ------------------ .../Models/Mapping/RelationMapperProfile.cs | 8 ---- .../Trees/RelationTypeTreeController.cs | 18 +------- src/Umbraco.Web/Umbraco.Web.csproj | 2 - 9 files changed, 34 insertions(+), 122 deletions(-) delete mode 100644 src/Umbraco.Web/Models/ContentEditing/Relation.cs delete mode 100644 src/Umbraco.Web/Models/ContentEditing/RelationType.cs diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js index 073099994b..7ac95dc4d9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js @@ -1,3 +1,11 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.RelationTypes.CreateController + * @function + * + * @description + * The controller for creating relation types. + */ function RelationTypeCreateController($scope, $location, relationTypeResource, navigationService, formHelper, appState, notificationsService) { var vm = this; vm.relationType = {}; diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.controller.js index ead951ae3a..1a32f17a46 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/delete.controller.js @@ -1,3 +1,11 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.RelationTypes.DeleteController + * @function + * + * @description + * The controller for deleting relation types. + */ function RelationTypeDeleteController($scope, $location, relationTypeResource, treeService, navigationService, appState) { var vm = this; diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js index 0ec6e18214..da32804f6d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js @@ -1,3 +1,11 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.RelationTypes.EditController + * @function + * + * @description + * The controller for editing relation types. + */ function RelationTypeEditController($scope, $routeParams, relationTypeResource, editorState, navigationService, dateHelper, userService, entityResource, formHelper, contentEditingHelper) { var vm = this; diff --git a/src/Umbraco.Web/Editors/RelationController.cs b/src/Umbraco.Web/Editors/RelationController.cs index c287e8a429..430f1af690 100644 --- a/src/Umbraco.Web/Editors/RelationController.cs +++ b/src/Umbraco.Web/Editors/RelationController.cs @@ -6,40 +6,40 @@ using System.Web.Http; using AutoMapper; using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; -using Relation = Umbraco.Web.Models.ContentEditing.Relation; namespace Umbraco.Web.Editors { [PluginController("UmbracoApi")] - [UmbracoApplicationAuthorizeAttribute(Constants.Applications.Content)] + [UmbracoApplicationAuthorize(Constants.Applications.Content)] public class RelationController : UmbracoAuthorizedJsonController { - public Relation GetById(int id) + public RelationDisplay GetById(int id) { - return Mapper.Map(Services.RelationService.GetById(id)); + return Mapper.Map(Services.RelationService.GetById(id)); } //[EnsureUserPermissionForContent("childId")] - public IEnumerable GetByChildId(int childId, string relationTypeAlias = "") + public IEnumerable GetByChildId(int childId, string relationTypeAlias = "") { var relations = Services.RelationService.GetByChildId(childId).ToArray(); if (relations.Any() == false) { - return Enumerable.Empty(); + return Enumerable.Empty(); } if (string.IsNullOrWhiteSpace(relationTypeAlias) == false) { return - Mapper.Map, IEnumerable>( + Mapper.Map, IEnumerable>( relations.Where(x => x.RelationType.Alias.InvariantEquals(relationTypeAlias))); } - return Mapper.Map, IEnumerable>(relations); + return Mapper.Map, IEnumerable>(relations); } [HttpDelete] diff --git a/src/Umbraco.Web/Models/ContentEditing/Relation.cs b/src/Umbraco.Web/Models/ContentEditing/Relation.cs deleted file mode 100644 index 2b012dc750..0000000000 --- a/src/Umbraco.Web/Models/ContentEditing/Relation.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using System.Text; -using System.Threading.Tasks; - -namespace Umbraco.Web.Models.ContentEditing -{ - [Obsolete("Use Umbraco.Web.Models.ContentEditing.RelationDisplay instead")] - [DataContract(Name = "relation", Namespace = "")] - public class Relation - { - - public Relation() - { - RelationType = new RelationType(); - } - - /// - /// Gets or sets the Parent Id of the Relation (Source) - /// - [DataMember(Name = "parentId")] - public int ParentId { get; set; } - - /// - /// Gets or sets the Child Id of the Relation (Destination) - /// - [DataMember(Name = "childId")] - public int ChildId { get; set; } - - /// - /// Gets or sets the for the Relation - /// - [DataMember(Name = "relationType", IsRequired = true)] - public RelationType RelationType { get; set; } - - /// - /// Gets or sets a comment for the Relation - /// - [DataMember(Name = "comment")] - public string Comment { get; set; } - - } -} diff --git a/src/Umbraco.Web/Models/ContentEditing/RelationType.cs b/src/Umbraco.Web/Models/ContentEditing/RelationType.cs deleted file mode 100644 index f52ac507ac..0000000000 --- a/src/Umbraco.Web/Models/ContentEditing/RelationType.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace Umbraco.Web.Models.ContentEditing -{ - [Obsolete("Use Umbraco.Web.Models.ContentEditing.RelationTypeDisplay instead")] - [DataContract(Name = "relationType", Namespace = "")] - public class RelationType - { - - /// - /// Gets or sets the Name of the RelationType - /// - [DataMember(Name = "name", IsRequired = true)] - public string Name { get; set; } - - /// - /// Gets or sets the Alias of the RelationType - /// - [DataMember(Name = "alias", IsRequired = true)] - public string Alias { get; set; } - - /// - /// Gets or sets a boolean indicating whether the RelationType is Bidirectional (true) or Parent to Child (false) - /// - [DataMember(Name = "isBidirectional", IsRequired = true)] - public bool IsBidirectional { get; set; } - - /// - /// Gets or sets the Parents object type id - /// - /// Corresponds to the NodeObjectType in the umbracoNode table - [DataMember(Name = "parentObjectType", IsRequired = true)] - public Guid ParentObjectType { get; set; } - - /// - /// Gets or sets the Childs object type id - /// - /// Corresponds to the NodeObjectType in the umbracoNode table - [DataMember(Name = "childObjectType", IsRequired = true)] - public Guid ChildObjectType { get; set; } - } -} diff --git a/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs index 5a4f9cd9a3..1622fb907e 100644 --- a/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs @@ -2,8 +2,6 @@ using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Web.Models.ContentEditing; -using Relation = Umbraco.Web.Models.ContentEditing.Relation; -using RelationType = Umbraco.Web.Models.ContentEditing.RelationType; namespace Umbraco.Web.Models.Mapping { @@ -40,12 +38,6 @@ namespace Umbraco.Web.Models.Mapping // FROM RelationTypeSave to IRelationType CreateMap(); - - //FROM IRelationType TO RelationType - CreateMap(); - - //FROM IRelation TO Relation - CreateMap(); } } } diff --git a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs index 6131ca8646..59e43225de 100644 --- a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs @@ -1,13 +1,10 @@ -using System; -using System.Linq; +using System.Linq; 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; namespace Umbraco.Web.Trees { @@ -36,18 +33,7 @@ namespace Umbraco.Web.Trees if (relationType == null) return new MenuItemCollection(); menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)); - - /*menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)) - //Since we haven't implemented anything for relationtypes in angular, this needs to be converted to - //use the legacy format - .ConvertLegacyMenuItem(new EntitySlim - { - Id = relationType.Id, - Level = 1, - ParentId = -1, - Name = relationType.Name - }, "relationTypes", queryStrings.GetValue("application"));*/ - + return menu; } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 35a3bfd752..f9e1eda168 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -640,9 +640,7 @@ - - From f87dac9972e541ac9f16e6d2f1dfb499c49ff1bb Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Sun, 2 Dec 2018 21:56:03 +0000 Subject: [PATCH 15/27] Remove redundant webforms views --- .../Editors/RelationTypeController.cs | 5 +- src/Umbraco.Web/Umbraco.Web.csproj | 26 -- .../RelationTypes/EditRelationType.aspx | 146 --------- .../RelationTypes/EditRelationType.aspx.cs | 284 ------------------ .../EditRelationType.aspx.designer.cs | 249 --------------- .../RelationTypes/NewRelationType.aspx | 54 ---- .../RelationTypes/NewRelationType.aspx.cs | 89 ------ .../NewRelationType.aspx.designer.cs | 168 ----------- .../RelationTypesWebService.asmx | 1 - .../RelationTypesWebService.asmx.cs | 35 --- .../TreeMenu/ActionDeleteRelationType.cs | 83 ----- .../TreeMenu/ActionNewRelationType.cs | 83 ----- 12 files changed, 2 insertions(+), 1221 deletions(-) delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx.designer.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.designer.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.Web/Editors/RelationTypeController.cs b/src/Umbraco.Web/Editors/RelationTypeController.cs index 05de96699d..ef3def1889 100644 --- a/src/Umbraco.Web/Editors/RelationTypeController.cs +++ b/src/Umbraco.Web/Editors/RelationTypeController.cs @@ -75,7 +75,7 @@ namespace Umbraco.Web.Editors /// A containing the persisted relation type's ID. public HttpResponseMessage PostCreate(RelationTypeSave relationType) { - var relationTypePersisted = new Core.Models.RelationType(relationType.ChildObjectType, relationType.ParentObjectType, relationType.Name.ToSafeAlias(true)) + var relationTypePersisted = new RelationType(relationType.ChildObjectType, relationType.ParentObjectType, relationType.Name.ToSafeAlias(true)) { Name = relationType.Name, IsBidirectional = relationType.IsBidirectional @@ -90,7 +90,7 @@ namespace Umbraco.Web.Editors catch (Exception ex) { Logger.Error(GetType(), ex, "Error creating relation type with {Name}", relationType.Name); - return Request.CreateNotificationValidationErrorResponse("Error creating dictionary item"); + return Request.CreateNotificationValidationErrorResponse("Error creating relation type."); } } @@ -105,7 +105,6 @@ namespace Umbraco.Web.Editors if (relationTypePersisted == null) { - // TODO: Translate message throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("Relation type does not exist")); } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index f9e1eda168..09b3e67cb0 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1259,25 +1259,6 @@ FeedProxy.aspx - - EditRelationType.aspx - - - EditRelationType.aspx - - - NewRelationType.aspx - ASPXCodeBehind - - - NewRelationType.aspx - - - RelationTypesWebService.asmx - Component - - - insertMasterpageContent.aspx ASPXCodeBehind @@ -1375,13 +1356,6 @@ - - ASPXCodeBehind - - - ASPXCodeBehind - - ASPXCodeBehind diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx deleted file mode 100644 index b81a8c4e5f..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx +++ /dev/null @@ -1,146 +0,0 @@ -<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="EditRelationType.aspx.cs" Inherits="umbraco.cms.presentation.developer.RelationTypes.EditRelationType" MasterPageFile="../../masterpages/umbracoPage.Master" %> -<%@ Register TagPrefix="umb" Namespace="Umbraco.Web._Legacy.Controls" %> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Parent  ChildCreatedComment
 <%# DataBinder.Eval(Container.DataItem, "ParentText") %>  <%# DataBinder.Eval(Container.DataItem, "ChildText") %><%# DataBinder.Eval(Container.DataItem, "DateTime") %><%# DataBinder.Eval(Container.DataItem, "Comment") %>
- -
- - -
- -
- - -
\ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx.cs deleted file mode 100644 index 3b1217d808..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx.cs +++ /dev/null @@ -1,284 +0,0 @@ -//TODO: Rebuild with new tree format and apis and then remove - -//using System; -//using System.Collections.Generic; -//using System.Web.UI; -//using System.Web.UI.WebControls; -// -//using umbraco.BusinessLogic; -//using Umbraco.Core; -//using Umbraco.Core.Models; -//using RelationType = umbraco.cms.businesslogic.relation.RelationType; - -//namespace umbraco.cms.presentation.developer.RelationTypes -//{ -// /// -// /// Edit an existing RelationType -// /// -// [WebformsPageTreeAuthorize(Constants.Trees.RelationTypes)] -// public partial class EditRelationType : UmbracoEnsuredPage -// { - -// /// -// /// Class scope reference to the current RelationType being edited -// /// -// private IRelationType _relationType; - -// /// -// /// Class scope reference to the relations associated with the current RelationType -// /// -// private List _relations; - -// /// -// /// Umbraco ObjectType used to represent all parent items in this relation type -// /// -// /// -// private UmbracoObjectTypes _parentObjectType; - -// /// -// /// Umbraco ObjectType used to represent all child items in this relation type -// /// -// private UmbracoObjectTypes _childObjectType; - -// /// -// /// Gets the name of the parent object type for all relations in this relation type -// /// -// protected string ParentObjectType -// { -// get -// { -// return this._parentObjectType.GetName(); //UmbracoHelper.GetName(this.parentObjectType); -// } -// } - -// /// -// /// Gets the name of the child object type for all relations in this relation type -// /// -// protected string ChildObjectType -// { -// get -// { -// return this._childObjectType.GetName(); //UmbracoHelper.GetName(this.childObjectType); -// } -// } - -// /// -// /// Gets a string representing the current relation type direction -// /// -// protected string RelationTypeDirection -// { -// get -// { -// return this._relationType.IsBidirectional ? "bidirectional" : "parentToChild"; -// } -// } - -// /// -// /// Gets the Relations for this RelationType, via lazy load -// /// -// private List Relations -// { -// get -// { -// if (this._relations == null) -// { -// this._relations = new List(); - -// using (var reader = uQuery.SqlHelper.ExecuteReader(@" -// SELECT A.id, -// A.parentId, -// B.[text] AS parentText, -// A.childId, -// C.[text] AS childText, -// A.relType, -// A.[datetime], -// A.comment -// FROM umbracoRelation A -// LEFT OUTER JOIN umbracoNode B ON A.parentId = B.id -// LEFT OUTER JOIN umbracoNode C ON A.childId = C.id -// WHERE A.relType = " + this._relationType.Id.ToString())) -// { -// while (reader.Read()) -// { -// var readOnlyRelation = new ReadOnlyRelation(); - -// readOnlyRelation.Id = reader.GetInt("id"); -// readOnlyRelation.ParentId = reader.GetInt("parentId"); -// readOnlyRelation.ParentText = reader.GetString("parentText"); -// readOnlyRelation.ChildId = reader.GetInt("childId"); -// readOnlyRelation.ChildText = reader.GetString("childText"); -// readOnlyRelation.RelType = reader.GetInt("relType"); -// readOnlyRelation.DateTime = reader.GetDateTime("datetime"); -// readOnlyRelation.Comment = reader.GetString("comment"); - -// this._relations.Add(readOnlyRelation); -// } -// } -// } - -// return this._relations; -// } -// } - -// /// -// /// On Load event -// /// -// /// this aspx page -// /// EventArgs (expect empty) -// protected void Page_Load(object sender, EventArgs e) -// { -// int id; -// if (int.TryParse(Request.QueryString["id"], out id)) -// { -// var relationService = Services.RelationService; - -// this._relationType = relationService.GetRelationTypeById(id); -// if (this._relationType != null) -// { -// this._parentObjectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(this._relationType.ParentObjectType); -// this._childObjectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(this._relationType.ChildObjectType); - -// // ----------- - -// if (!this.IsPostBack) -// { -// this.EnsureChildControls(); - -// this.idLiteral.Text = this._relationType.Id.ToString(); -// this.nameTextBox.Text = this._relationType.Name; -// this.aliasTextBox.Text = this._relationType.Alias; - -// if (this._relationType.IsBidirectional) -// { -// this.dualRadioButtonList.Items.FindByValue("1").Selected = true; -// } -// else -// { -// this.dualRadioButtonList.Items.FindByValue("0").Selected = true; -// } - -// this.parentLiteral.Text = this._parentObjectType.GetFriendlyName(); -// // UmbracoHelper.GetFriendlyName(this.parentObjectType); -// this.childLiteral.Text = this._childObjectType.GetFriendlyName(); -// // UmbracoHelper.GetFriendlyName(this.childObjectType); - -// this.relationsCountLiteral.Text = this.Relations.Count.ToString(); - -// this.relationsRepeater.DataSource = this.Relations; -// this.relationsRepeater.DataBind(); -// } -// } -// else -// { -// throw new Exception("Unable to get RelationType where ID = " + id); -// } -// } -// else -// { -// throw new Exception("Invalid RelationType ID"); -// } -// } - -// /// -// /// Creates the child controls used in this page -// /// -// protected override void CreateChildControls() -// { -// base.CreateChildControls(); - -// var relationTypeTabPage = this.tabControl.NewTabPage("Relation Type"); -// relationTypeTabPage.Controls.Add(this.idPane); -// relationTypeTabPage.Controls.Add(this.nameAliasPane); -// relationTypeTabPage.Controls.Add(this.directionPane); -// relationTypeTabPage.Controls.Add(this.objectTypePane); - -// var saveMenuImageButton = tabControl.Menu.NewButton(); -// saveMenuImageButton.ToolTip = "save relation type"; -// saveMenuImageButton.Click +=saveMenuImageButton_Click; -// saveMenuImageButton.CausesValidation = true; -// saveMenuImageButton.Text = Services.TextService.Localize("save"); -// saveMenuImageButton.ValidationGroup = "RelationType"; - -// var relationsTabPage = this.tabControl.NewTabPage("Relations"); -// relationsTabPage.Controls.Add(this.relationsCountPane); -// relationsTabPage.Controls.Add(this.relationsPane); - -// /* -// var refreshMenuImageButton = relationsTabPage.Menu.NewImageButton(); -// refreshMenuImageButton.AlternateText = "refresh relations"; -// refreshMenuImageButton.Click += this.RefreshMenuImageButton_Click; -// refreshMenuImageButton.ImageUrl = "/umbraco/developer/RelationTypes/Images/Refresh.gif"; -// refreshMenuImageButton.CausesValidation = false;*/ -// } - -// /// -// /// check that alias hasn't been changed to clash with another (except itself) -// /// -// /// the aliasCustomValidator control -// /// to set validation respose -// protected void AliasCustomValidator_ServerValidate(object source, ServerValidateEventArgs args) -// { -// args.IsValid = (RelationType.GetByAlias(this.aliasTextBox.Text.Trim()) == null) || -// (this.aliasTextBox.Text.Trim() == this._relationType.Alias); -// } - -// /// -// /// Reload the relations, in case they have changed -// /// -// /// expects refreshMenuImageButton -// /// expects ImageClickEventArgs -// private void RefreshMenuImageButton_Click(object sender, ImageClickEventArgs e) -// { -// } - -// /// -// /// Save button in Umbraco menu -// /// -// /// expects saveMenuImageButton object -// /// expects ImageClickEventArgs -// void saveMenuImageButton_Click(object sender, EventArgs e) -// { -// if (this.Page.IsValid) -// { -// var nameChanged = this._relationType.Name != this.nameTextBox.Text.Trim(); -// var aliasChanged = this._relationType.Alias != this.aliasTextBox.Text.Trim(); -// var directionChanged = this._relationType.IsBidirectional != (this.dualRadioButtonList.SelectedValue == "1"); - -// if (nameChanged || aliasChanged || directionChanged) -// { -// string bubbleBody = string.Empty; - -// if (nameChanged) -// { -// bubbleBody += "Name, "; - -// this._relationType.Name = this.nameTextBox.Text.Trim(); - -// // Refresh tree, as the name as changed -// ClientTools.SyncTree(this._relationType.Id.ToString(), true); -// } - -// if (directionChanged) -// { -// bubbleBody += "Direction, "; -// this._relationType.IsBidirectional = this.dualRadioButtonList.SelectedValue == "1"; -// } - -// if (aliasChanged) -// { -// bubbleBody += "Alias, "; -// this._relationType.Alias = this.aliasTextBox.Text.Trim(); -// } - -// bubbleBody = bubbleBody.Remove(bubbleBody.LastIndexOf(','), 1); -// bubbleBody = bubbleBody + "Changed"; - -// var relationService = Services.RelationService; -// relationService.Save(this._relationType); - -// ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Save, "Relation Type Updated", bubbleBody); -// } -// } -// } -// } -//} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx.designer.cs deleted file mode 100644 index 7e8475fdfb..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/EditRelationType.aspx.designer.cs +++ /dev/null @@ -1,249 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.cms.presentation.developer.RelationTypes { - - - public partial class EditRelationType { - - /// - /// tabControl control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.TabView tabControl; - - /// - /// idPane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane idPane; - - /// - /// idPropertyPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel idPropertyPanel; - - /// - /// idLiteral control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal idLiteral; - - /// - /// nameAliasPane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane nameAliasPane; - - /// - /// nameProperyPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel nameProperyPanel; - - /// - /// nameTextBox control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox nameTextBox; - - /// - /// nameRequiredFieldValidator control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator nameRequiredFieldValidator; - - /// - /// aliasPropertyPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel aliasPropertyPanel; - - /// - /// aliasTextBox control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox aliasTextBox; - - /// - /// aliasRequiredFieldValidator control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator aliasRequiredFieldValidator; - - /// - /// aliasCustomValidator control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CustomValidator aliasCustomValidator; - - /// - /// directionPane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane directionPane; - - /// - /// dualPropertyPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel dualPropertyPanel; - - /// - /// dualRadioButtonList control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RadioButtonList dualRadioButtonList; - - /// - /// objectTypePane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane objectTypePane; - - /// - /// parentPropertyPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel parentPropertyPanel; - - /// - /// parentLiteral control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal parentLiteral; - - /// - /// childPropertyPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel childPropertyPanel; - - /// - /// childLiteral control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal childLiteral; - - /// - /// relationsCountPane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane relationsCountPane; - - /// - /// relationsCountPropertyPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel relationsCountPropertyPanel; - - /// - /// relationsCountLiteral control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal relationsCountLiteral; - - /// - /// relationsPane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane relationsPane; - - /// - /// relationsPropertyPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel relationsPropertyPanel; - - /// - /// relationsRepeater control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Repeater relationsRepeater; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx deleted file mode 100644 index 5939549fa4..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx +++ /dev/null @@ -1,54 +0,0 @@ -<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="NewRelationType.aspx.cs" Inherits="umbraco.cms.presentation.developer.RelationTypes.NewRelationType" MasterPageFile="../../masterpages/umbracoPage.Master"%> -<%@ Register TagPrefix="umb" Namespace="Umbraco.Web._Legacy.Controls" %> - - - - - - - - - - - - - - - - - - - - - - - - - - - - <% ///* */ %> - - - - - - - - - - - - - - - -
- - or - Cancel -
- - -
- diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.cs deleted file mode 100644 index cffe2157e3..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.Web.UI.WebControls; -using Umbraco.Core; -using Umbraco.Web.UI.Pages; -using Umbraco.Core.Models; - -namespace umbraco.cms.presentation.developer.RelationTypes -{ - /// - /// Add a new Relation Type - /// - [WebformsPageTreeAuthorize(Constants.Trees.RelationTypes)] - public partial class NewRelationType : UmbracoEnsuredPage - { - /// - /// On Load event - /// - /// this aspx page - /// EventArgs (expect empty) - protected void Page_Load(object sender, EventArgs e) - { - if (!this.Page.IsPostBack) - { - this.Form.DefaultFocus = this.descriptionTextBox.ClientID; - } - - this.AppendUmbracoObjectTypes(this.parentDropDownList); - this.AppendUmbracoObjectTypes(this.childDropDownList); - } - - /// - /// Server side validation to ensure there are no existing relationshipTypes with the alias of - /// the relation type being added - /// - /// the aliasCustomValidator control - /// to set validation respose - protected void AliasCustomValidator_ServerValidate(object source, ServerValidateEventArgs args) - { - var relationService = Services.RelationService; - args.IsValid = relationService.GetRelationTypeByAlias(this.aliasTextBox.Text.Trim()) == null; - } - - /// - /// Add a new relation type into the database, and redirects to it's editing page. - /// - /// expects the addButton control - /// expects EventArgs for addButton - protected void AddButton_Click(object sender, EventArgs e) - { - if (Page.IsValid) - { - var newRelationTypeAlias = this.aliasTextBox.Text.Trim(); - - var relationService = Services.RelationService; - var relationType = new RelationType(new Guid(this.childDropDownList.SelectedValue), - new Guid(this.parentDropDownList.SelectedValue), newRelationTypeAlias, this.descriptionTextBox.Text) - { - IsBidirectional = this.dualRadioButtonList.SelectedValue == "1" - }; - - relationService.Save(relationType); - - var newRelationTypeId = relationService.GetRelationTypeByAlias(newRelationTypeAlias).Id; - - ClientTools.ChangeContentFrameUrl("developer/RelationTypes/EditRelationType.aspx?id=" + newRelationTypeId).CloseModalWindow().ChildNodeCreated(); - } - } - - /// - /// Adds the Umbraco Object types to a drop down list - /// - /// control for which to add the Umbraco object types - private void AppendUmbracoObjectTypes(ListControl dropDownList) - { - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.Document.GetFriendlyName(), Constants.ObjectTypes.Strings.Document)); - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.Media.GetFriendlyName(), Constants.ObjectTypes.Strings.Media)); - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.Member.GetFriendlyName(), Constants.ObjectTypes.Strings.Member)); - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.MediaType.GetFriendlyName(), Constants.ObjectTypes.Strings.MediaType)); - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.DocumentType.GetFriendlyName(), Constants.ObjectTypes.Strings.DocumentType)); - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.MemberType.GetFriendlyName(), Constants.ObjectTypes.Strings.MemberType)); - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.DataType.GetFriendlyName(), Constants.ObjectTypes.Strings.DataType)); - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.MemberGroup.GetFriendlyName(), Constants.ObjectTypes.Strings.MemberGroup)); - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.Stylesheet.GetFriendlyName(), Constants.ObjectTypes.Strings.Stylesheet)); - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.Template.GetFriendlyName(), Constants.ObjectTypes.Strings.Template)); - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.ROOT.GetFriendlyName(), Constants.ObjectTypes.Strings.SystemRoot)); - dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.RecycleBin.GetFriendlyName(), Constants.ObjectTypes.Strings.ContentRecycleBin)); - } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.designer.cs deleted file mode 100644 index 5f463c7ad8..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.designer.cs +++ /dev/null @@ -1,168 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.cms.presentation.developer.RelationTypes { - - - public partial class NewRelationType { - - /// - /// nameAliasPane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane nameAliasPane; - - /// - /// nameProperyPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel nameProperyPanel; - - /// - /// descriptionTextBox control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox descriptionTextBox; - - /// - /// descriptionRequiredFieldValidator control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator descriptionRequiredFieldValidator; - - /// - /// aliasPropertyPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel aliasPropertyPanel; - - /// - /// aliasTextBox control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox aliasTextBox; - - /// - /// aliasRequiredFieldValidator control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator aliasRequiredFieldValidator; - - /// - /// aliasCustomValidator control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CustomValidator aliasCustomValidator; - - /// - /// directionPane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane directionPane; - - /// - /// PropertyPanel1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel PropertyPanel1; - - /// - /// dualRadioButtonList control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RadioButtonList dualRadioButtonList; - - /// - /// objectTypePane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.Pane objectTypePane; - - /// - /// PropertyPanel2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel PropertyPanel2; - - /// - /// parentDropDownList control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.DropDownList parentDropDownList; - - /// - /// PropertyPanel3 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Umbraco.Web._Legacy.Controls.PropertyPanel PropertyPanel3; - - /// - /// childDropDownList control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.DropDownList childDropDownList; - - /// - /// addButton control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button addButton; - } -} 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 - } -} From a4f270bd0267cf5fe4dd8237fe127150ffdb27e0 Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Sun, 2 Dec 2018 22:33:15 +0000 Subject: [PATCH 16/27] Added localisation --- .../src/views/relationtypes/create.html | 12 +++++----- .../src/views/relationtypes/edit.html | 22 +++++++++---------- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 12 ++++++++++ .../Umbraco/config/lang/en_us.xml | 12 ++++++++++ 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html index 1af1497953..e5f66c9fe0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html @@ -2,30 +2,30 @@
- + - +
- + - +
- +
{{vm.relationType.parentObjectTypeName}}
- +
{{vm.relationType.childObjectTypeName}}
- +
{{vm.relationType.relations.length}}
- +
- - - - + + + + diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index e852be1a4e..fa799b7370 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1946,4 +1946,16 @@ To manage your website, simply open the Umbraco back office and start adding con There is no 'restore' relation found for this node. Use the Move menu item to move it manually.The item you want to restore it under ('%0%') is in the recycle bin. Use the Move menu item to move the item manually. + + Direction + Parent to child + Bidirectional + Parent + Child + Count + Relations + Created + Comment + Name + diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 54d86eee5c..543f7b6f41 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1987,4 +1987,16 @@ To manage your website, simply open the Umbraco back office and start adding con Select your notifications forNotification settings saved for + + Direction + Parent to child + Bidirectional + Parent + Child + Count + Relations + Created + Comment + Name + From c6d09cbcff291f8bd0c3c00f85192b61e0abeff3 Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Sun, 2 Dec 2018 22:53:30 +0000 Subject: [PATCH 17/27] Split relation type and associated relations into tabbed view --- .../views/relationtypes/create.controller.js | 2 +- .../views/relationtypes/edit.controller.js | 26 ++++++-- .../src/views/relationtypes/edit.html | 65 ++----------------- .../relationtypes/views/relationType.html | 40 ++++++++++++ .../views/relationtypes/views/relations.html | 23 +++++++ src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 2 + .../Umbraco/config/lang/en_us.xml | 2 + 7 files changed, 94 insertions(+), 66 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relationType.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relations.html diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js index 7ac95dc4d9..8b1d82cf8f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js @@ -19,7 +19,7 @@ function RelationTypeCreateController($scope, $location, relationTypeResource, n relationTypeResource.getRelationObjectTypes().then(function (data) { vm.objectTypes = data; }, function (err) { - alert("oh no"); + notificationsService.error("Could not load form.") }) } diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js index da32804f6d..ed0845a773 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js @@ -6,7 +6,7 @@ * @description * The controller for editing relation types. */ -function RelationTypeEditController($scope, $routeParams, relationTypeResource, editorState, navigationService, dateHelper, userService, entityResource, formHelper, contentEditingHelper) { +function RelationTypeEditController($scope, $routeParams, relationTypeResource, editorState, navigationService, dateHelper, userService, entityResource, formHelper, contentEditingHelper, localizationService) { var vm = this; @@ -17,11 +17,29 @@ function RelationTypeEditController($scope, $routeParams, relationTypeResource, vm.save = saveRelationType; - if($routeParams.create) { - alert("create"); - } else { + init(); + + function init() { vm.page.loading = true; + localizationService.localizeMany(["relationType_tabRelationType", "relationType_tabRelations"]).then(function (data) { + vm.page.navigation = [ + { + "name": data[0], + "alias": "relationType", + "icon": "icon-info", + "view": "views/relationTypes/views/relationType.html", + "active": true + }, + { + "name": data[1], + "alias": "relations", + "icon": "icon-trafic", + "view": "views/relationTypes/views/relations.html" + } + ]; + }); + relationTypeResource.getById($routeParams.id) .then(function(data) { bindRelationType(data); diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html index 2862e89a60..2c86161bda 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html @@ -7,70 +7,13 @@ name="vm.relationType.name" alias="vm.relationType.alias" hide-description="true" - hide-icon="true"> + hide-icon="true" + navigation="vm.page.navigation"> - - - - -
{{vm.relationType.id}}
- {{vm.relationType.key}} -
- - - -
    -
  • - -
  • -
  • - -
  • -
-
- - - -
{{vm.relationType.parentObjectTypeName}}
-
- - - -
{{vm.relationType.childObjectTypeName}}
-
- - - -
{{vm.relationType.relations.length}}
-
- - - -
-
ParentChildCreatedCommentParentChildCreatedComment
{{relation.parentName}}
- - - - - - - - - - - - -
ParentChildCreatedComment
{{relation.parentName}}{{relation.childName}}{{relation.timestampFormatted}}{{relation.comment}}
-
-
- - + + diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relationType.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relationType.html new file mode 100644 index 0000000000..7f31461e69 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relationType.html @@ -0,0 +1,40 @@ + + + + +
{{model.relationType.id}}
+ {{model.relationType.key}} +
+ + + +
    +
  • + +
  • +
  • + +
  • +
+
+ + + +
{{model.relationType.parentObjectTypeName}}
+
+ + + +
{{model.relationType.childObjectTypeName}}
+
+ + + +
{{model.relationType.relations.length}}
+
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relations.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relations.html new file mode 100644 index 0000000000..ba8d9c00da --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relations.html @@ -0,0 +1,23 @@ + + + + +
+ + + + + + + + + + + + + +
ParentChildCreatedComment
{{relation.parentName}}{{relation.childName}}{{relation.timestampFormatted}}{{relation.comment}}
+
+
+
+
diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index fa799b7370..af419ac8ab 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1957,5 +1957,7 @@ To manage your website, simply open the Umbraco back office and start adding con Created Comment Name + Relation Type + Relations diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 543f7b6f41..f61e5bc3b1 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1998,5 +1998,7 @@ To manage your website, simply open the Umbraco back office and start adding con Created Comment Name + Relation Type + Relations From a11b442cfdc3aa942d5bbd5fe9e7eddd324fda6b Mon Sep 17 00:00:00 2001 From: Jack Lawry Date: Thu, 6 Dec 2018 16:32:19 +0000 Subject: [PATCH 18/27] Update text --- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 4 ++-- src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index b2e02b1f9c..39f266a3bd 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1474,8 +1474,8 @@ To manage your website, simply open the Umbraco back office and start adding con Inherit tabs and properties from an existing document type. New tabs will be added to the current document type or merged if a tab with an identical name exists. This content type is used in a composition, and therefore cannot be composed itself. There are no content types available to use as a composition. - Available editors - Reuse + Create new + Use existing Editor settings Configuration Yes, delete diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index e4050d3a7b..1856f0f3f2 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1510,8 +1510,8 @@ To manage your website, simply open the Umbraco back office and start adding con Inherit tabs and properties from an existing document type. New tabs will be added to the current document type or merged if a tab with an identical name exists. This content type is used in a composition, and therefore cannot be composed itself. There are no content types available to use as a composition. - Available editors - Reuse + Create new + Use existing Editor settings Configuration Yes, delete From 98cc48c0d36c23429805630cc2502f49e5f8ec0e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 10 Dec 2018 11:38:43 +0100 Subject: [PATCH 19/27] remove infinite editing backdrop when discarding changes --- .../components/editor/umbeditors.directive.js | 13 ++++++++----- .../src/common/services/editor.service.js | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js index c852228205..ac9b20fd66 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js @@ -203,11 +203,14 @@ })); evts.push(eventsService.on("appState.editors.close", function (name, args) { - removeEditor(args.editor); - })); - - evts.push(eventsService.on("appState.editors.closeAll", function (name, args) { - scope.editors = []; + // remove the closed editor + if(args && args.editor) { + removeEditor(args.editor); + } + // close all editors + if(args && args.editors.length === 0) { + scope.editors = []; + } })); //ensure to unregister from all events! diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js index 449470f54c..650a210784 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js @@ -98,7 +98,7 @@ editor: null }; - eventsService.emit("appState.editors.closeAll", args); + eventsService.emit("appState.editors.close", args); } /** From ca0cd8711e85759527116bde3717042081a0fb0c Mon Sep 17 00:00:00 2001 From: Claus Date: Mon, 10 Dec 2018 14:11:02 +0100 Subject: [PATCH 20/27] minor fixes. --- .../src/views/relationtypes/create.controller.js | 4 ++-- src/Umbraco.Web/Trees/RelationTypeTreeController.cs | 6 +++--- src/Umbraco.Web/Umbraco.Web.csproj | 10 ---------- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js index 8b1d82cf8f..2cef0bc5a4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js @@ -25,14 +25,14 @@ function RelationTypeCreateController($scope, $location, relationTypeResource, n function createRelationType() { if (formHelper.submitForm({ scope: $scope, formCtrl: this.createRelationTypeForm, statusMessage: "Creating relation type..." })) { - var node = $scope.dialogOptions.currentNode; + var node = $scope.currentNode; relationTypeResource.create(vm.relationType).then(function (data) { navigationService.hideMenu(); // Set the new item as active in the tree var currentPath = node.path ? node.path : "-1"; - navigationService.syncTree({ tree: "relationType", path: currentPath + "," + data, forceReload: true, activate: true }); + navigationService.syncTree({ tree: "relationTypes", path: currentPath + "," + data, forceReload: true, activate: true }); formHelper.resetForm({ scope: $scope }); diff --git a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs index 47a8d82808..1ce319b6ac 100644 --- a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs @@ -3,8 +3,8 @@ using System.Net.Http.Formatting; using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi.Filters; using Umbraco.Core; - using Umbraco.Core.Services; +using Umbraco.Web.Actions; namespace Umbraco.Web.Trees { @@ -21,7 +21,7 @@ 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.Localize("actions", ActionNew.ActionAlias)); //refresh action menu.Items.Add(new RefreshNode(Services.TextService, true)); @@ -32,7 +32,7 @@ namespace Umbraco.Web.Trees var relationType = Services.RelationService.GetRelationTypeById(int.Parse(id)); if (relationType == null) return new MenuItemCollection(); - menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)); + menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.ActionAlias)); return menu; } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index a58871a774..4034dd2be6 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1242,13 +1242,6 @@ FeedProxy.aspx - - NewRelationType.aspx - ASPXCodeBehind - - - NewRelationType.aspx - insertMasterpageContent.aspx ASPXCodeBehind @@ -1320,9 +1313,6 @@ - - ASPXCodeBehind - ASPXCodeBehind From c61ac406bb6da0a8ad4e9899c65c956a0b09edbe Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 10 Dec 2018 14:20:57 +0100 Subject: [PATCH 21/27] fix fade animation when closing the last infinite editor --- .../common/directives/components/editor/umbeditors.directive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js index ac9b20fd66..e68c2bbc9a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js @@ -208,7 +208,7 @@ removeEditor(args.editor); } // close all editors - if(args && args.editors.length === 0) { + if(args && !args.editor && args.editors.length === 0) { scope.editors = []; } })); From e173ea6dac38ff905a068ccc49c23173157e1cb1 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 10 Dec 2018 15:30:56 +0100 Subject: [PATCH 22/27] Cleanup --- .../Implement/ContentTypeRepositoryBase.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index 6be07a4c3d..9b62dbd6e3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -190,8 +190,8 @@ AND umbracoNode.nodeObjectType = @objectType", SortOrder = allowedContentType.SortOrder }); } - - + + //Insert Tabs foreach (var propertyGroup in entity.PropertyGroups) { @@ -331,11 +331,11 @@ AND umbracoNode.id <> @id", if (entity.IsPropertyDirty("PropertyTypes") || entity.PropertyTypes.Any(pt => pt.IsDirty())) { var dbPropertyTypes = Database.Fetch("WHERE contentTypeId = @Id", new { entity.Id }); - var dbPropertyTypeAlias = dbPropertyTypes.Select(x => x.Id); + var dbPropertyTypeIds = dbPropertyTypes.Select(x => x.Id); var entityPropertyTypes = entity.PropertyTypes.Where(x => x.HasIdentity).Select(x => x.Id); - var items = dbPropertyTypeAlias.Except(entityPropertyTypes); - foreach (var item in items) - DeletePropertyType(entity.Id, item); + var propertyTypeToDeleteIds = dbPropertyTypeIds.Except(entityPropertyTypes); + foreach (var propertyTypeId in propertyTypeToDeleteIds) + DeletePropertyType(entity.Id, propertyTypeId); } // Delete tabs ... by excepting entries from db with entries from collections. @@ -620,7 +620,7 @@ AND umbracoNode.id <> @id", var sqlDelete = Sql() .Delete() .WhereIn((System.Linq.Expressions.Expression>)(x => x.ContentKey), sqlSelect); - + Database.Execute(sqlDelete); } @@ -690,7 +690,7 @@ AND umbracoNode.id <> @id", //first clear out any existing names that might already exists under the default lang //there's 2x tables to update - //clear out the versionCultureVariation table + //clear out the versionCultureVariation table var sqlSelect = Sql().Select(x => x.Id) .From() .InnerJoin().On(x => x.Id, x => x.VersionId) From c4cf843b82e549a9808abbbd5613ff970667a7fb Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 10 Dec 2018 14:59:17 +0000 Subject: [PATCH 23/27] Adds in the Umbraco Forms Promo dashboard in via package.manifest so that Forms install can override when installed --- .../App_Plugins/UmbracoForms/package.manifest | 10 ++++++++++ src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 9 +++++---- src/Umbraco.Web.UI/config/Dashboard.config | 11 ----------- 3 files changed, 15 insertions(+), 15 deletions(-) create mode 100644 src/Umbraco.Web.UI/App_Plugins/UmbracoForms/package.manifest diff --git a/src/Umbraco.Web.UI/App_Plugins/UmbracoForms/package.manifest b/src/Umbraco.Web.UI/App_Plugins/UmbracoForms/package.manifest new file mode 100644 index 0000000000..c7ed4a957a --- /dev/null +++ b/src/Umbraco.Web.UI/App_Plugins/UmbracoForms/package.manifest @@ -0,0 +1,10 @@ +{ + "dashboards": [ + { + "name": "Install Umbraco Forms", + "alias": "installUmbracoForms", + "view": "views/dashboard/forms/formsdashboardintro.html", + "sections": [ "forms" ] + } + ] +} diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 2823908a92..130015ad53 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -231,6 +231,7 @@ + 404handlers.config @@ -452,10 +453,10 @@ $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.Tasks.dll $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.Tasks.dll $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.Tasks.dll - $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll - $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll - - $(ProgramFiles32)\Microsoft Visual Studio\2019\Preview\MSBuild\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll + + $(ProgramFiles32)\Microsoft Visual Studio\2019\Preview\MSBuild\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll diff --git a/src/Umbraco.Web.UI/config/Dashboard.config b/src/Umbraco.Web.UI/config/Dashboard.config index fec6ab34ae..785fb61681 100644 --- a/src/Umbraco.Web.UI/config/Dashboard.config +++ b/src/Umbraco.Web.UI/config/Dashboard.config @@ -22,17 +22,6 @@ -
- - forms - - - - views/dashboard/forms/formsdashboardintro.html - - -
-
media From f10b86c9ec58018681d4df4e4a7a023da7c58dca Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 10 Dec 2018 17:07:45 +0100 Subject: [PATCH 24/27] Fix RelationMapperProfiler --- .../Models/Mapping/RelationMapperProfile.cs | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs index 1622fb907e..e31b1877d3 100644 --- a/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/RelationMapperProfile.cs @@ -11,18 +11,17 @@ namespace Umbraco.Web.Models.Mapping { // FROM IRelationType to RelationTypeDisplay CreateMap() - .ForMember(x => x.Icon, expression => expression.Ignore()) - .ForMember(x => x.Trashed, expression => expression.Ignore()) - .ForMember(x => x.Alias, expression => expression.Ignore()) - .ForMember(x => x.Path, expression => expression.Ignore()) - .ForMember(x => x.AdditionalData, expression => expression.Ignore()) - .ForMember(x => x.ChildObjectTypeName, expression => expression.Ignore()) - .ForMember(x => x.ParentObjectTypeName, expression => expression.Ignore()) - .ForMember(x => x.Relations, expression => expression.Ignore()) - .ForMember( - x => x.Udi, - expression => expression.MapFrom( - content => Udi.Create(Constants.UdiEntityType.RelationType, content.Key))) + .ForMember(dest => dest.Icon, opt => opt.Ignore()) + .ForMember(dest => dest.Trashed, opt => opt.Ignore()) + .ForMember(dest => dest.Alias, opt => opt.Ignore()) + .ForMember(dest => dest.Path, opt => opt.Ignore()) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()) + .ForMember(dest => dest.ChildObjectTypeName, opt => opt.Ignore()) + .ForMember(dest => dest.ParentObjectTypeName, opt => opt.Ignore()) + .ForMember(dest => dest.Relations, opt => opt.Ignore()) + .ForMember(dest => dest.ParentId, opt => opt.Ignore()) + .ForMember(dest => dest.Notifications, opt => opt.Ignore()) + .ForMember(dest => dest.Udi, opt => opt.MapFrom(content => Udi.Create(Constants.UdiEntityType.RelationType, content.Key))) .AfterMap((src, dest) => { // Build up the path @@ -34,10 +33,15 @@ namespace Umbraco.Web.Models.Mapping }); // FROM IRelation to RelationDisplay - CreateMap(); + CreateMap() + .ForMember(dest => dest.ParentName, opt => opt.Ignore()) + .ForMember(dest => dest.ChildName, opt => opt.Ignore()); // FROM RelationTypeSave to IRelationType - CreateMap(); + CreateMap() + .ForMember(dest => dest.CreateDate, opt => opt.Ignore()) + .ForMember(dest => dest.UpdateDate, opt => opt.Ignore()) + .ForMember(dest => dest.DeleteDate, opt => opt.Ignore()); } } } From f9967e2d7d90733374746f8d0496d01d9034649b Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 10 Dec 2018 17:48:24 +0100 Subject: [PATCH 25/27] Fix e25e509d84 breaking tests, fix original issue --- src/Umbraco.Core/Models/ContentTypeBase.cs | 16 +++++++++------- src/Umbraco.Core/Models/PropertyGroup.cs | 7 +++++-- .../Implement/ContentTypeRepositoryBase.cs | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index caa63d7526..88b1179f6d 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -92,8 +92,8 @@ namespace Umbraco.Core.Models public readonly PropertyInfo AllowedAsRootSelector = ExpressionHelper.GetPropertyInfo(x => x.AllowedAsRoot); public readonly PropertyInfo IsContainerSelector = ExpressionHelper.GetPropertyInfo(x => x.IsContainer); public readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedContentTypes); - public readonly PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.PropertyGroups); - public readonly PropertyInfo PropertyTypeCollectionSelector = ExpressionHelper.GetPropertyInfo>(x => x.PropertyTypes); + public readonly PropertyInfo PropertyGroupsSelector = ExpressionHelper.GetPropertyInfo(x => x.PropertyGroups); + public readonly PropertyInfo PropertyTypesSelector = ExpressionHelper.GetPropertyInfo>(x => x.PropertyTypes); public readonly PropertyInfo HasPropertyTypeBeenRemovedSelector = ExpressionHelper.GetPropertyInfo(x => x.HasPropertyTypeBeenRemoved); public readonly PropertyInfo VaryBy = ExpressionHelper.GetPropertyInfo(x => x.Variations); @@ -106,12 +106,12 @@ namespace Umbraco.Core.Models protected void PropertyGroupsChanged(object sender, NotifyCollectionChangedEventArgs e) { - OnPropertyChanged(Ps.Value.PropertyGroupCollectionSelector); + OnPropertyChanged(Ps.Value.PropertyGroupsSelector); } protected void PropertyTypesChanged(object sender, NotifyCollectionChangedEventArgs e) { - OnPropertyChanged(Ps.Value.PropertyTypeCollectionSelector); + OnPropertyChanged(Ps.Value.PropertyTypesSelector); } /// @@ -263,6 +263,8 @@ namespace Umbraco.Core.Models get => _noGroupPropertyTypes; set { + if (_noGroupPropertyTypes != null) + _noGroupPropertyTypes.CollectionChanged -= PropertyTypesChanged; _noGroupPropertyTypes = new PropertyTypeCollection(IsPublishing, value); _noGroupPropertyTypes.CollectionChanged += PropertyTypesChanged; PropertyTypesChanged(_noGroupPropertyTypes, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); @@ -376,7 +378,7 @@ namespace Umbraco.Core.Models if (!HasPropertyTypeBeenRemoved) { HasPropertyTypeBeenRemoved = true; - OnPropertyChanged(Ps.Value.PropertyTypeCollectionSelector); + OnPropertyChanged(Ps.Value.PropertyTypesSelector); } break; } @@ -388,7 +390,7 @@ namespace Umbraco.Core.Models if (!HasPropertyTypeBeenRemoved) { HasPropertyTypeBeenRemoved = true; - OnPropertyChanged(Ps.Value.PropertyTypeCollectionSelector); + OnPropertyChanged(Ps.Value.PropertyTypesSelector); } } } @@ -412,7 +414,7 @@ namespace Umbraco.Core.Models // actually remove the group PropertyGroups.RemoveItem(propertyGroupName); - OnPropertyChanged(Ps.Value.PropertyGroupCollectionSelector); + OnPropertyChanged(Ps.Value.PropertyGroupsSelector); } /// diff --git a/src/Umbraco.Core/Models/PropertyGroup.cs b/src/Umbraco.Core/Models/PropertyGroup.cs index 1d0b949932..595e8d1d6a 100644 --- a/src/Umbraco.Core/Models/PropertyGroup.cs +++ b/src/Umbraco.Core/Models/PropertyGroup.cs @@ -35,12 +35,12 @@ namespace Umbraco.Core.Models { public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); - public readonly PropertyInfo PropertyTypeCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.PropertyTypes); + public readonly PropertyInfo PropertyTypes = ExpressionHelper.GetPropertyInfo(x => x.PropertyTypes); } private void PropertyTypesChanged(object sender, NotifyCollectionChangedEventArgs e) { - OnPropertyChanged(Ps.Value.PropertyTypeCollectionSelector); + OnPropertyChanged(Ps.Value.PropertyTypes); } /// @@ -76,6 +76,8 @@ namespace Umbraco.Core.Models get => _propertyTypes; set { + if (_propertyTypes != null) + _propertyTypes.CollectionChanged -= PropertyTypesChanged; _propertyTypes = value; // since we're adding this collection to this group, @@ -83,6 +85,7 @@ namespace Umbraco.Core.Models foreach (var propertyType in _propertyTypes) propertyType.PropertyGroupId = new Lazy(() => Id); + OnPropertyChanged(Ps.Value.PropertyTypes); _propertyTypes.CollectionChanged += PropertyTypesChanged; } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index 9b62dbd6e3..44215b7f7e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -328,7 +328,7 @@ AND umbracoNode.id <> @id", // We check if the entity's own PropertyTypes has been modified and then also check // any of the property groups PropertyTypes has been modified. // This specifically tells us if any property type collections have changed. - if (entity.IsPropertyDirty("PropertyTypes") || entity.PropertyTypes.Any(pt => pt.IsDirty())) + if (entity.IsPropertyDirty("NoGroupPropertyTypes") || entity.PropertyGroups.Any(x => x.IsPropertyDirty("PropertyTypes"))) { var dbPropertyTypes = Database.Fetch("WHERE contentTypeId = @Id", new { entity.Id }); var dbPropertyTypeIds = dbPropertyTypes.Select(x => x.Id); From e91cf0039b9250645de6d9e7ca795df0bf56ae76 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 11 Dec 2018 12:32:51 +1100 Subject: [PATCH 26/27] Adds ability to filter the outgoing dashboard model --- src/Umbraco.Web/Editors/DashboardController.cs | 1 + src/Umbraco.Web/Editors/EditorModelEventManager.cs | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index 72b7acc9e7..d8cbc34938 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -118,6 +118,7 @@ namespace Umbraco.Web.Editors } [ValidateAngularAntiForgeryToken] + [OutgoingEditorModelEvent] public IEnumerable> GetDashboard(string section) { return _dashboards.GetDashboards(section, Security.CurrentUser); diff --git a/src/Umbraco.Web/Editors/EditorModelEventManager.cs b/src/Umbraco.Web/Editors/EditorModelEventManager.cs index e2a248cb88..2225f5c577 100644 --- a/src/Umbraco.Web/Editors/EditorModelEventManager.cs +++ b/src/Umbraco.Web/Editors/EditorModelEventManager.cs @@ -1,4 +1,5 @@ -using System.Web.Http.Filters; +using System.Collections.Generic; +using System.Web.Http.Filters; using Umbraco.Core.Events; using Umbraco.Web.Models.ContentEditing; @@ -13,6 +14,13 @@ namespace Umbraco.Web.Editors public static event TypedEventHandler> SendingMediaModel; public static event TypedEventHandler> SendingMemberModel; public static event TypedEventHandler> SendingUserModel; + public static event TypedEventHandler>>> SendingDashboardModel; + + private static void OnSendingDashboardModel(HttpActionExecutedContext sender, EditorModelEventArgs>> e) + { + var handler = SendingDashboardModel; + handler?.Invoke(sender, e); + } private static void OnSendingUserModel(HttpActionExecutedContext sender, EditorModelEventArgs e) { @@ -56,6 +64,9 @@ namespace Umbraco.Web.Editors if (e.Model is UserDisplay) OnSendingUserModel(sender, new EditorModelEventArgs(e)); + + if (e.Model is IEnumerable>) + OnSendingDashboardModel(sender, new EditorModelEventArgs>>(e)); } } } From 9b52fa215f0eb11f7daa96dbb21e47b8d1b15942 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 11 Dec 2018 12:53:15 +1100 Subject: [PATCH 27/27] Allows replacing the model with the outgoing event args --- .../Editors/EditorModelEventArgs.cs | 21 +++++++++++++++---- .../OutgoingEditorModelEventAttribute.cs | 11 +++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web/Editors/EditorModelEventArgs.cs b/src/Umbraco.Web/Editors/EditorModelEventArgs.cs index 153a2d8786..daf262fce5 100644 --- a/src/Umbraco.Web/Editors/EditorModelEventArgs.cs +++ b/src/Umbraco.Web/Editors/EditorModelEventArgs.cs @@ -4,9 +4,13 @@ namespace Umbraco.Web.Editors { public sealed class EditorModelEventArgs : EditorModelEventArgs { + private readonly EditorModelEventArgs _baseArgs; + private T _model; + public EditorModelEventArgs(EditorModelEventArgs baseArgs) : base(baseArgs.Model, baseArgs.UmbracoContext) { + _baseArgs = baseArgs; Model = (T)baseArgs.Model; } @@ -16,7 +20,16 @@ namespace Umbraco.Web.Editors Model = model; } - public new T Model { get; private set; } + public new T Model + { + get => _model; + set + { + _model = value; + if (_baseArgs != null) + _baseArgs.Model = _model; + } + } } public class EditorModelEventArgs : EventArgs @@ -27,7 +40,7 @@ namespace Umbraco.Web.Editors UmbracoContext = umbracoContext; } - public object Model { get; private set; } - public UmbracoContext UmbracoContext { get; private set; } + public object Model { get; set; } + public UmbracoContext UmbracoContext { get; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/WebApi/Filters/OutgoingEditorModelEventAttribute.cs b/src/Umbraco.Web/WebApi/Filters/OutgoingEditorModelEventAttribute.cs index ec32b61bca..8410891a5d 100644 --- a/src/Umbraco.Web/WebApi/Filters/OutgoingEditorModelEventAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/OutgoingEditorModelEventAttribute.cs @@ -19,16 +19,17 @@ namespace Umbraco.Web.WebApi.Filters var user = UmbracoContext.Current.Security.CurrentUser; if (user == null) return; - var objectContent = actionExecutedContext.Response.Content as ObjectContent; - if (objectContent != null) + if (actionExecutedContext.Response.Content is ObjectContent objectContent) { var model = objectContent.Value; if (model != null) { - EditorModelEventManager.EmitEvent(actionExecutedContext, new EditorModelEventArgs( - (dynamic)model, - UmbracoContext.Current)); + var args = new EditorModelEventArgs( + model, + UmbracoContext.Current); + EditorModelEventManager.EmitEvent(actionExecutedContext, args); + objectContent.Value = args.Model; } }