From 02764e0cccbe1c6f5daa4a4c348c6448fcdb534c Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 5 Mar 2019 13:02:59 +0100 Subject: [PATCH 01/23] Implement IPublishedContent Siblings --- src/Umbraco.Web/PublishedContentExtensions.cs | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index f880076c50..dbd5008b74 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Examine; using Umbraco.Web.Composing; +using Umbraco.Web.PublishedCache; namespace Umbraco.Web { @@ -21,6 +22,7 @@ namespace Umbraco.Web // see notes in PublishedElementExtensions // private static IPublishedValueFallback PublishedValueFallback => Current.PublishedValueFallback; + private static IPublishedSnapshot PublishedSnapshot => Current.PublishedSnapshot; #region Urls @@ -235,7 +237,8 @@ namespace Umbraco.Web /// /// The content items. /// The specific culture to filter for. If null is used the current culture is used. (Default is null). - internal static IEnumerable WhereIsInvariantOrHasCulture(this IEnumerable contents, string culture = null) + internal static IEnumerable WhereIsInvariantOrHasCulture(this IEnumerable contents, string culture = null) + where T : class, IPublishedContent { if (contents == null) throw new ArgumentNullException(nameof(contents)); @@ -1117,6 +1120,52 @@ namespace Umbraco.Web #endregion + #region Axes: siblings + + /// + /// Gets the siblings of the content. + /// + /// The content. + /// The specific culture to filter for. If null is used the current culture is used. (Default is null) + /// The siblings of the content. + public static IEnumerable Siblings(this IPublishedContent content, string culture = null) + { + return content.Parent != null + ? content.Parent.Children(culture) + : PublishedSnapshot.Content.GetAtRoot().WhereIsInvariantOrHasCulture(culture); + } + + /// + /// Gets the siblings of the content, of a given content type. + /// + /// The content. + /// The specific culture to filter for. If null is used the current culture is used. (Default is null) + /// The content type alias. + /// The siblings of the content, of the given content type. + public static IEnumerable SiblingsOfType(this IPublishedContent content, string contentTypeAlias, string culture = null) + { + return content.Parent != null + ? content.Parent.ChildrenOfType(contentTypeAlias, culture) + : PublishedSnapshot.Content.GetAtRoot().OfTypes(contentTypeAlias).WhereIsInvariantOrHasCulture(culture); + } + + /// + /// Gets the siblings of the content, of a given content type. + /// + /// The content type. + /// The content. + /// The specific culture to filter for. If null is used the current culture is used. (Default is null) + /// The siblings of the content, of the given content type. + public static IEnumerable Siblings(this IPublishedContent content, string culture = null) + where T : class, IPublishedContent + { + return content.Parent != null + ? content.Parent.Children(culture) + : PublishedSnapshot.Content.GetAtRoot().OfType().WhereIsInvariantOrHasCulture(culture); + } + + #endregion + #region Axes: custom /// From 7b815cfcb3ca7e454eb066ed6661d47d1916fd98 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Tue, 5 Mar 2019 21:34:49 +0100 Subject: [PATCH 02/23] Add methods for fetching multiple members to UmbracoHelper --- src/Umbraco.Web/UmbracoHelper.cs | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index 12d4ce1d76..5d39f1c8dd 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -288,6 +288,56 @@ namespace Umbraco.Web var asInt = id.TryConvertTo(); return asInt ? MembershipHelper.GetById(asInt.Result) : MembershipHelper.GetByProviderKey(id); } + + public IEnumerable Member(IEnumerable ids) + { + return ids.Select(id => Member(id)).WhereNotNull(); + } + + public IEnumerable Member(IEnumerable ids) + { + return ids.Select(id => Member(id)).WhereNotNull(); + } + + public IEnumerable Member(IEnumerable ids) + { + return ids.Select(id => Member(id)).WhereNotNull(); + } + + public IEnumerable Member(IEnumerable ids) + { + return ids.Select(id => Member(id)).WhereNotNull(); + } + + public IEnumerable Member(IEnumerable ids) + { + return ids.Select(id => Member(id)).WhereNotNull(); + } + + public IEnumerable Member(params int[] ids) + { + return ids.Select(id => Member(id)).WhereNotNull(); + } + + public IEnumerable Member(params string[] ids) + { + return ids.Select(id => Member(id)).WhereNotNull(); + } + + public IEnumerable Member(params Guid[] ids) + { + return ids.Select(id => Member(id)).WhereNotNull(); + } + + public IEnumerable Member(params Udi[] ids) + { + return ids.Select(id => Member(id)).WhereNotNull(); + } + + public IEnumerable Member(params object[] ids) + { + return ids.Select(id => Member(id)).WhereNotNull(); + } #endregion From 36827cfa9f608659c2c7178b2d8fa8efb3437221 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Fri, 8 Mar 2019 07:31:39 +0100 Subject: [PATCH 03/23] Move some of the multiget member methods to MembershipHelper --- src/Umbraco.Web/Security/MembershipHelper.cs | 35 ++++++++++++++++++++ src/Umbraco.Web/UmbracoHelper.cs | 24 +++++++------- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index 3bb6951d9a..c2d80257e1 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -289,11 +289,46 @@ namespace Umbraco.Web.Security return MemberCache.GetByProviderKey(key); } + public virtual IEnumerable GetByProviderKey(IEnumerable keys) + { + return keys?.Select(GetByProviderKey).WhereNotNull() ?? new IPublishedContent[0]; + } + + public virtual IEnumerable GetByProviderKey(params object[] keys) + { + return keys?.Select(GetByProviderKey).WhereNotNull() ?? new IPublishedContent[0]; + } + public virtual IPublishedContent GetById(int memberId) { return MemberCache.GetById(memberId); } + public virtual IEnumerable GetById(IEnumerable memberIds) + { + return memberIds?.Select(GetById).WhereNotNull() ?? new IPublishedContent[0]; + } + + public virtual IEnumerable GetById(params int[] memberIds) + { + return memberIds?.Select(GetById).WhereNotNull() ?? new IPublishedContent[0]; + } + + public virtual IPublishedContent GetById(Guid memberId) + { + return GetByProviderKey(memberId); + } + + public virtual IEnumerable GetById(IEnumerable memberIds) + { + return GetByProviderKey(memberIds.OfType()); + } + + public virtual IEnumerable GetById(params Guid[] memberIds) + { + return GetByProviderKey(memberIds.OfType()); + } + public virtual IPublishedContent GetByUsername(string username) { return MemberCache.GetByUsername(username); diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index 5d39f1c8dd..e9fdfd73e5 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -264,7 +264,7 @@ namespace Umbraco.Web public IPublishedContent Member(Guid id) { - return MembershipHelper.GetByProviderKey(id); + return MembershipHelper.GetById(id); } public IPublishedContent Member(object id) @@ -288,55 +288,55 @@ namespace Umbraco.Web var asInt = id.TryConvertTo(); return asInt ? MembershipHelper.GetById(asInt.Result) : MembershipHelper.GetByProviderKey(id); } - + public IEnumerable Member(IEnumerable ids) { - return ids.Select(id => Member(id)).WhereNotNull(); + return MembershipHelper.GetById(ids); } public IEnumerable Member(IEnumerable ids) { - return ids.Select(id => Member(id)).WhereNotNull(); + return ids.Select(Member).WhereNotNull(); } public IEnumerable Member(IEnumerable ids) { - return ids.Select(id => Member(id)).WhereNotNull(); + return MembershipHelper.GetById(ids); } public IEnumerable Member(IEnumerable ids) { - return ids.Select(id => Member(id)).WhereNotNull(); + return ids.Select(Member).WhereNotNull(); } public IEnumerable Member(IEnumerable ids) { - return ids.Select(id => Member(id)).WhereNotNull(); + return ids.Select(Member).WhereNotNull(); } public IEnumerable Member(params int[] ids) { - return ids.Select(id => Member(id)).WhereNotNull(); + return ids.Select(Member).WhereNotNull(); } public IEnumerable Member(params string[] ids) { - return ids.Select(id => Member(id)).WhereNotNull(); + return ids.Select(Member).WhereNotNull(); } public IEnumerable Member(params Guid[] ids) { - return ids.Select(id => Member(id)).WhereNotNull(); + return MembershipHelper.GetById(ids); } public IEnumerable Member(params Udi[] ids) { - return ids.Select(id => Member(id)).WhereNotNull(); + return ids.Select(Member).WhereNotNull(); } public IEnumerable Member(params object[] ids) { - return ids.Select(id => Member(id)).WhereNotNull(); + return ids.Select(Member).WhereNotNull(); } #endregion From 1f7172e98dc4306c28dc2f2a5f4b9349d646d3ea Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Tue, 12 Mar 2019 21:54:13 +0000 Subject: [PATCH 04/23] Cleaned up class names in logviewer overview to use new logviewer classes and made a logviewer specific less stylesheet. Also left aligned the saved searches to make them look better --- src/Umbraco.Web.UI.Client/src/less/belle.less | 1 + .../src/less/components/umb-logviewer.less | 42 +++++++++++++++++++ .../src/views/logviewer/overview.html | 10 ++--- 3 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index 88988485fe..82fe416319 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -137,6 +137,7 @@ @import "components/umb-iconpicker.less"; @import "components/umb-insert-code-box.less"; @import "components/umb-packages.less"; +@import "components/umb-logviewer.less"; @import "components/umb-package-local-install.less"; @import "components/umb-panel-group.less"; @import "components/umb-lightbox.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less new file mode 100644 index 0000000000..f7aa0e4558 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less @@ -0,0 +1,42 @@ +/* PACKAGE DETAILS */ + +.umb-logviewer { + display: flex; + flex-flow: row wrap; +} + +@sidebarwidth: 350px; // Width of sidebar. Ugly hack because of old version of Less + +.umb-logviewer__main-content { + flex: 1 1 auto; + margin-right: 20px; + width: calc(~'100%' - ~'@{sidebarwidth}' - ~'20px'); // Make sure that the main content area doesn't gets affected by inline styling + min-width: 500px; + + .btn-link { + text-align: left; + } +} + +.umb-logviewer__sidebar { + flex: 0 0 @sidebarwidth; +} + +@media (max-width: 768px) { + + .umb-logviewer { + flex-direction: column; + } + + .umb-logviewer__main-content { + flex: 1 1 auto; + width: 100%; + margin-bottom: 30px; + margin-right: 0; + } + + .umb-logviewer__sidebar { + flex: 1 1 auto; + width: 100%; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html b/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html index 67d89e5ee7..a46853f97e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html +++ b/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html @@ -1,4 +1,4 @@ -
+
@@ -24,8 +24,8 @@
-
-
+
+
@@ -68,7 +68,7 @@
-
+
@@ -95,4 +95,4 @@
-
\ No newline at end of file +
From 53e6c620eb13a9ee8e862953b1108d72ddb6295c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 13 Mar 2019 14:45:30 +0100 Subject: [PATCH 05/23] fixes 4627 + makes front-end validations appear as soon as they are invalid again. --- .../directives/validation/valpropertymsg.directive.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js index 9ee83dc2ba..c027e0778e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js @@ -62,8 +62,8 @@ function valPropertyMsg(serverValidationManager) { if (!watcher) { watcher = scope.$watch("currentProperty.value", function (newValue, oldValue) { - - if (!newValue || angular.equals(newValue, oldValue)) { + + if (angular.equals(newValue, oldValue)) { return; } @@ -78,10 +78,12 @@ function valPropertyMsg(serverValidationManager) { // based on other errors. We'll also check if there's no other validation errors apart from valPropertyMsg, if valPropertyMsg // is the only one, then we'll clear. - if ((errCount === 1 && angular.isArray(formCtrl.$error.valPropertyMsg)) || (formCtrl.$invalid && angular.isArray(formCtrl.$error.valServer))) { + if (errCount === 0 || (errCount === 1 && angular.isArray(formCtrl.$error.valPropertyMsg)) || (formCtrl.$invalid && angular.isArray(formCtrl.$error.valServer))) { scope.errorMsg = ""; formCtrl.$setValidity('valPropertyMsg', true); - stopWatch(); + } else if (showValidation && scope.errorMsg === "") { + formCtrl.$setValidity('valPropertyMsg', false); + scope.errorMsg = getErrorMsg(); } }, true); } @@ -152,6 +154,7 @@ function valPropertyMsg(serverValidationManager) { showValidation = true; if (hasError && scope.errorMsg === "") { scope.errorMsg = getErrorMsg(); + startWatch(); } else if (!hasError) { scope.errorMsg = ""; From 7f334540029f76761525b494c7d2ac40c9c6b98b Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 18 Mar 2019 17:51:04 +0100 Subject: [PATCH 06/23] Better ServerMessenger configuration --- src/Umbraco.Core/CompositionExtensions.cs | 22 +++++ .../BatchedDatabaseServerMessenger.cs | 5 +- ...aseServerRegistrarAndMessengerComponent.cs | 80 ++++++++----------- 3 files changed, 59 insertions(+), 48 deletions(-) diff --git a/src/Umbraco.Core/CompositionExtensions.cs b/src/Umbraco.Core/CompositionExtensions.cs index e1c7ad4467..828a577c34 100644 --- a/src/Umbraco.Core/CompositionExtensions.cs +++ b/src/Umbraco.Core/CompositionExtensions.cs @@ -203,6 +203,28 @@ namespace Umbraco.Core composition.RegisterUnique(_ => registrar); } + /// + /// Sets the database server messenger options. + /// + /// The composition. + /// A function creating the options. + /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default. + public static void SetDatabaseServerMessengerOptions(this Composition composition, Func factory) + { + composition.RegisterUnique(factory); + } + + /// + /// Sets the database server messenger options. + /// + /// The composition. + /// Options. + /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default. + public static void SetDatabaseServerMessengerOptions(this Composition composition, DatabaseServerMessengerOptions options) + { + composition.RegisterUnique(_ => options); + } + /// /// Sets the short string helper. /// diff --git a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs index 76d7565862..818e8ecf77 100644 --- a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs @@ -27,9 +27,8 @@ namespace Umbraco.Web private readonly IUmbracoDatabaseFactory _databaseFactory; public BatchedDatabaseServerMessenger( - IRuntimeState runtime, IUmbracoDatabaseFactory databaseFactory, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, IGlobalSettings globalSettings, - bool enableDistCalls, DatabaseServerMessengerOptions options) - : base(runtime, scopeProvider, sqlContext, proflog, globalSettings, enableDistCalls, options) + IRuntimeState runtime, IUmbracoDatabaseFactory databaseFactory, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, IGlobalSettings globalSettings, DatabaseServerMessengerOptions options) + : base(runtime, scopeProvider, sqlContext, proflog, globalSettings, true, options) { _databaseFactory = databaseFactory; } diff --git a/src/Umbraco.Web/Compose/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Web/Compose/DatabaseServerRegistrarAndMessengerComponent.cs index 086aa9b197..a68e137665 100644 --- a/src/Umbraco.Web/Compose/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Web/Compose/DatabaseServerRegistrarAndMessengerComponent.cs @@ -38,54 +38,44 @@ namespace Umbraco.Web.Compose public sealed class DatabaseServerRegistrarAndMessengerComposer : ComponentComposer, ICoreComposer { + public static DatabaseServerMessengerOptions GetDefaultOptions(IFactory factory) + { + var logger = factory.GetInstance(); + var indexRebuilder = factory.GetInstance(); + + return new DatabaseServerMessengerOptions + { + //These callbacks will be executed if the server has not been synced + // (i.e. it is a new server or the lastsynced.txt file has been removed) + InitializingCallbacks = new Action[] + { + //rebuild the xml cache file if the server is not synced + () => + { + // rebuild the published snapshot caches entirely, if the server is not synced + // this is equivalent to DistributedCache RefreshAll... but local only + // (we really should have a way to reuse RefreshAll... locally) + // note: refresh all content & media caches does refresh content types too + var svc = Current.PublishedSnapshotService; + svc.Notify(new[] { new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll) }); + svc.Notify(new[] { new ContentCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out _, out _); + svc.Notify(new[] { new MediaCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out _); + }, + + //rebuild indexes if the server is not synced + // NOTE: This will rebuild ALL indexes including the members, if developers want to target specific + // indexes then they can adjust this logic themselves. + () => { ExamineComponent.RebuildIndexes(indexRebuilder, logger, false, 5000); } + } + }; + } + public override void Compose(Composition composition) { base.Compose(composition); - composition.SetServerMessenger(factory => - { - var runtime = factory.GetInstance(); - var databaseFactory = factory.GetInstance(); - var globalSettings = factory.GetInstance(); - var proflog = factory.GetInstance(); - var scopeProvider = factory.GetInstance(); - var sqlContext = factory.GetInstance(); - var logger = factory.GetInstance(); - var indexRebuilder = factory.GetInstance(); - - return new BatchedDatabaseServerMessenger( - runtime, databaseFactory, scopeProvider, sqlContext, proflog, globalSettings, - true, - //Default options for web including the required callbacks to build caches - new DatabaseServerMessengerOptions - { - //These callbacks will be executed if the server has not been synced - // (i.e. it is a new server or the lastsynced.txt file has been removed) - InitializingCallbacks = new Action[] - { - //rebuild the xml cache file if the server is not synced - () => - { - // rebuild the published snapshot caches entirely, if the server is not synced - // this is equivalent to DistributedCache RefreshAll... but local only - // (we really should have a way to reuse RefreshAll... locally) - // note: refresh all content & media caches does refresh content types too - var svc = Current.PublishedSnapshotService; - svc.Notify(new[] { new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll) }); - svc.Notify(new[] { new ContentCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out _, out _); - svc.Notify(new[] { new MediaCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out _); - }, - - //rebuild indexes if the server is not synced - // NOTE: This will rebuild ALL indexes including the members, if developers want to target specific - // indexes then they can adjust this logic themselves. - () => - { - ExamineComponent.RebuildIndexes(indexRebuilder, logger, false, 5000); - } - } - }); - }); + composition.SetDatabaseServerMessengerOptions(GetDefaultOptions); + composition.SetServerMessenger(); } } @@ -128,7 +118,7 @@ namespace Umbraco.Web.Compose } public void Initialize() - { + { //We will start the whole process when a successful request is made if (_registrar != null || _messenger != null) UmbracoModule.RouteAttempt += RegisterBackgroundTasksOnce; From e73029cf4fb486318dc0b6510cb2cc2115298137 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 19 Mar 2019 13:08:08 +0100 Subject: [PATCH 07/23] Rename siblings to ParentChildren (Because the actual returned list contains the content node self) --- src/Umbraco.Web/PublishedContentExtensions.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index dbd5008b74..8af2a933f2 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -1120,15 +1120,15 @@ namespace Umbraco.Web #endregion - #region Axes: siblings + #region Axes: Parent Children (siblings including self) /// - /// Gets the siblings of the content. + /// Gets the children of the parent of the content. /// /// The content. /// The specific culture to filter for. If null is used the current culture is used. (Default is null) - /// The siblings of the content. - public static IEnumerable Siblings(this IPublishedContent content, string culture = null) + /// The children of the parent of the content. + public static IEnumerable ParentChildren(this IPublishedContent content, string culture = null) { return content.Parent != null ? content.Parent.Children(culture) @@ -1136,13 +1136,13 @@ namespace Umbraco.Web } /// - /// Gets the siblings of the content, of a given content type. + /// Gets the children of the parent of the content, of a given content type. /// /// The content. /// The specific culture to filter for. If null is used the current culture is used. (Default is null) /// The content type alias. - /// The siblings of the content, of the given content type. - public static IEnumerable SiblingsOfType(this IPublishedContent content, string contentTypeAlias, string culture = null) + /// The children of the parent of the content, of the given content type. + public static IEnumerable ParentChildrenOfType(this IPublishedContent content, string contentTypeAlias, string culture = null) { return content.Parent != null ? content.Parent.ChildrenOfType(contentTypeAlias, culture) @@ -1150,13 +1150,13 @@ namespace Umbraco.Web } /// - /// Gets the siblings of the content, of a given content type. + /// Gets the children of the parent of the content, of a given content type. /// /// The content type. /// The content. /// The specific culture to filter for. If null is used the current culture is used. (Default is null) - /// The siblings of the content, of the given content type. - public static IEnumerable Siblings(this IPublishedContent content, string culture = null) + /// The children of the parent of the content, of the given content type. + public static IEnumerable ParentChildren(this IPublishedContent content, string culture = null) where T : class, IPublishedContent { return content.Parent != null From e4c6ef05a9e3e4d6f8b6d55026d3bd5f4654ee7a Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 19 Mar 2019 14:59:52 +0100 Subject: [PATCH 08/23] Introduced both Siblings and SiblingsAndSelf --- .../PublishedContent/PublishedContentTests.cs | 89 +++++++++++++++++++ src/Umbraco.Web/PublishedContentExtensions.cs | 65 +++++++++++--- 2 files changed, 144 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index ab576171f4..de641a99a2 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -10,6 +10,7 @@ using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Core.Composing; using Moq; +using Newtonsoft.Json; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; @@ -32,6 +33,8 @@ namespace Umbraco.Tests.PublishedContent protected override void Compose() { base.Compose(); + _publishedSnapshotAccessorMock = new Mock(); + Composition.RegisterUnique(_publishedSnapshotAccessorMock.Object); Composition.RegisterUnique(f => new PublishedModelFactory(f.GetInstance().GetTypes())); Composition.RegisterUnique(); @@ -87,6 +90,7 @@ namespace Umbraco.Tests.PublishedContent } private readonly Guid _node1173Guid = Guid.NewGuid(); + private Mock _publishedSnapshotAccessorMock; protected override string GetXmlContent(int templateId) { @@ -792,6 +796,91 @@ namespace Umbraco.Tests.PublishedContent Assert.IsTrue(customDoc3.IsDescendantOrSelf(customDoc3)); } + [Test] + public void SiblingsAndSelf() + { + // Structure: + // - Root : 1046 (no parent) + // -- Level1.1: 1173 (parent 1046) + // --- Level1.1.1: 1174 (parent 1173) + // --- Level1.1.2: 117 (parent 1173) + // --- Level1.1.3: 1177 (parent 1173) + // --- Level1.1.4: 1178 (parent 1173) + // --- Level1.1.5: 1176 (parent 1173) + // -- Level1.2: 1175 (parent 1046) + // -- Level1.3: 4444 (parent 1046) + var root = GetNode(1046); + var level1_1 = GetNode(1173); + var level1_1_1 = GetNode(1174); + var level1_1_2 = GetNode(117); + var level1_1_3 = GetNode(1177); + var level1_1_4 = GetNode(1178); + var level1_1_5 = GetNode(1176); + var level1_2 = GetNode(1175); + var level1_3 = GetNode(4444); + + _publishedSnapshotAccessorMock.Setup(x => x.PublishedSnapshot.Content.GetAtRoot()).Returns(new []{root}); + + CollectionAssertAreEqual(new []{root}, root.SiblingsAndSelf()); + + CollectionAssertAreEqual( new []{level1_1, level1_2, level1_3}, level1_1.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1, level1_2, level1_3}, level1_2.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1, level1_2, level1_3}, level1_3.SiblingsAndSelf()); + + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_1.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_2.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_3.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_4.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_5.SiblingsAndSelf()); + + } + + [Test] + public void Siblings() + { + // Structure: + // - Root : 1046 (no parent) + // -- Level1.1: 1173 (parent 1046) + // --- Level1.1.1: 1174 (parent 1173) + // --- Level1.1.2: 117 (parent 1173) + // --- Level1.1.3: 1177 (parent 1173) + // --- Level1.1.4: 1178 (parent 1173) + // --- Level1.1.5: 1176 (parent 1173) + // -- Level1.2: 1175 (parent 1046) + // -- Level1.3: 4444 (parent 1046) + var root = GetNode(1046); + var level1_1 = GetNode(1173); + var level1_1_1 = GetNode(1174); + var level1_1_2 = GetNode(117); + var level1_1_3 = GetNode(1177); + var level1_1_4 = GetNode(1178); + var level1_1_5 = GetNode(1176); + var level1_2 = GetNode(1175); + var level1_3 = GetNode(4444); + + _publishedSnapshotAccessorMock.Setup(x => x.PublishedSnapshot.Content.GetAtRoot()).Returns(new []{root}); + + CollectionAssertAreEqual(new IPublishedContent[0], root.Siblings()); + + CollectionAssertAreEqual( new []{level1_2, level1_3}, level1_1.Siblings()); + CollectionAssertAreEqual( new []{level1_1, level1_3}, level1_2.Siblings()); + CollectionAssertAreEqual( new []{level1_1, level1_2}, level1_3.Siblings()); + + CollectionAssertAreEqual( new []{ level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_1.Siblings()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_3, level1_1_4, level1_1_5}, level1_1_2.Siblings()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_4, level1_1_5}, level1_1_3.Siblings()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_5}, level1_1_4.Siblings()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4}, level1_1_5.Siblings()); + + } + + private void CollectionAssertAreEqual(IEnumerable expected, IEnumerable actual) + where T: IPublishedContent + { + var e = expected.Select(x => x.Id); + var a = actual.Select(x => x.Id); + CollectionAssert.AreEquivalent(e, a, $"\nExpected:\n{string.Join(", ", e)}\n\nActual:\n{string.Join(", ", a)}"); + } [Test] public void FragmentProperty() diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 8af2a933f2..bba58dfae5 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -1120,15 +1120,60 @@ namespace Umbraco.Web #endregion - #region Axes: Parent Children (siblings including self) + #region Axes: Siblings /// - /// Gets the children of the parent of the content. + /// Gets the siblings of the content. /// /// The content. /// The specific culture to filter for. If null is used the current culture is used. (Default is null) - /// The children of the parent of the content. - public static IEnumerable ParentChildren(this IPublishedContent content, string culture = null) + /// The siblings of the content. + /// + /// Note that in V7 this method also return the content node self. + /// + public static IEnumerable Siblings(this IPublishedContent content, string culture = null) + { + return SiblingsAndSelf(content, culture).Where(x => x.Id != content.Id); + } + + /// + /// Gets the siblings of the content, of a given content type. + /// + /// The content. + /// The specific culture to filter for. If null is used the current culture is used. (Default is null) + /// The content type alias. + /// The siblings of the content, of the given content type. + /// + /// Note that in V7 this method also return the content node self. + /// + public static IEnumerable SiblingsOfType(this IPublishedContent content, string contentTypeAlias, string culture = null) + { + return SiblingsAndSelfOfType(content, contentTypeAlias, culture).Where(x => x.Id != content.Id); + } + + /// + /// Gets the siblings of the content, of a given content type. + /// + /// The content type. + /// The content. + /// The specific culture to filter for. If null is used the current culture is used. (Default is null) + /// The siblings of the content, of the given content type. + /// + /// Note that in V7 this method also return the content node self. + /// + public static IEnumerable Siblings(this IPublishedContent content, string culture = null) + where T : class, IPublishedContent + { + return SiblingsAndSelf(content, culture).Where(x => x.Id != content.Id); + } + + /// + /// Gets the siblings of the content including the node itself to indicate the position. + /// + /// The content. + /// The specific culture to filter for. If null is used the current culture is used. (Default is null) + /// The siblings of the content including the node itself. + public static IEnumerable SiblingsAndSelf(this IPublishedContent content, string culture = null) { return content.Parent != null ? content.Parent.Children(culture) @@ -1136,13 +1181,13 @@ namespace Umbraco.Web } /// - /// Gets the children of the parent of the content, of a given content type. + /// Gets the siblings of the content including the node itself to indicate the position, of a given content type. /// /// The content. /// The specific culture to filter for. If null is used the current culture is used. (Default is null) /// The content type alias. - /// The children of the parent of the content, of the given content type. - public static IEnumerable ParentChildrenOfType(this IPublishedContent content, string contentTypeAlias, string culture = null) + /// The siblings of the content including the node itself, of the given content type. + public static IEnumerable SiblingsAndSelfOfType(this IPublishedContent content, string contentTypeAlias, string culture = null) { return content.Parent != null ? content.Parent.ChildrenOfType(contentTypeAlias, culture) @@ -1150,13 +1195,13 @@ namespace Umbraco.Web } /// - /// Gets the children of the parent of the content, of a given content type. + /// Gets the siblings of the content including the node itself to indicate the position, of a given content type. /// /// The content type. /// The content. /// The specific culture to filter for. If null is used the current culture is used. (Default is null) - /// The children of the parent of the content, of the given content type. - public static IEnumerable ParentChildren(this IPublishedContent content, string culture = null) + /// The siblings of the content including the node itself, of the given content type. + public static IEnumerable SiblingsAndSelf(this IPublishedContent content, string culture = null) where T : class, IPublishedContent { return content.Parent != null From bf3ce014cb50a62d6c964ac5cda32af68d35a668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 25 Mar 2019 10:51:06 +0100 Subject: [PATCH 09/23] changed button styles for a better low hanging-fruit solution --- .../src/views/dashboard/content/redirecturls.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/content/redirecturls.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/content/redirecturls.html index 98a8294e80..0f08897501 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/content/redirecturls.html +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/content/redirecturls.html @@ -13,7 +13,8 @@ type="button" size="s" action="vm.disableUrlTracker($event)" - label-key="redirectUrls_disableUrlTracker"> + label-key="redirectUrls_disableUrlTracker" + button-style="white"> + label-key="redirectUrls_enableUrlTracker" + button-style="success"> From e6720a175cbf9b45a09b4b059ae9a15fed1bb0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 25 Mar 2019 11:36:50 +0100 Subject: [PATCH 10/23] changed notification auto remove time to 10 seconds --- .../common/services/notifications.service.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js b/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js index 2575b05bb6..c123ac6cea 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js @@ -85,17 +85,17 @@ angular.module('umbraco.services') nArray.push(item); if(!item.sticky) { - $timeout(function() { - var found = _.find(nArray, function(i) { - return i.id === item.id; - }); - - if (found) { - var index = nArray.indexOf(found); - nArray.splice(index, 1); - } - - }, 7000); + $timeout( + function() { + var found = _.find(nArray, function(i) { + return i.id === item.id; + }); + if (found) { + var index = nArray.indexOf(found); + nArray.splice(index, 1); + } + } + , 10000); } return item; From 84e4189b45c519e703f3060c513e350c29f83ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 25 Mar 2019 11:37:05 +0100 Subject: [PATCH 11/23] added margin and round corners to notifications --- .../less/components/notifications/umb-notifications.less | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less b/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less index 9e16eca414..7f04fef9a9 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less @@ -22,7 +22,14 @@ font-size: 14px; border: none; position: relative; - margin-bottom: 0; + border-radius: 10px; + margin: 10px; + + .close { + top: 0; + right: -6px; + opacity: 0.4; + } } .umb-notifications__notification.-extra-padding { From 64bae439bf7c735410bc3c95fe45dfb5e90762e3 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Tue, 26 Mar 2019 08:44:03 +0100 Subject: [PATCH 12/23] Fix stuff from review --- src/Umbraco.Web/Security/MembershipHelper.cs | 24 ++++++++++---------- src/Umbraco.Web/UmbracoHelper.cs | 6 ++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index c2d80257e1..bbcfc0760e 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -289,14 +289,14 @@ namespace Umbraco.Web.Security return MemberCache.GetByProviderKey(key); } - public virtual IEnumerable GetByProviderKey(IEnumerable keys) + public virtual IEnumerable GetByProviderKeys(IEnumerable keys) { - return keys?.Select(GetByProviderKey).WhereNotNull() ?? new IPublishedContent[0]; + return keys?.Select(GetByProviderKey).WhereNotNull() ?? Enumerable.Empty(); } - public virtual IEnumerable GetByProviderKey(params object[] keys) + public virtual IEnumerable GetByProviderKeys(params object[] keys) { - return keys?.Select(GetByProviderKey).WhereNotNull() ?? new IPublishedContent[0]; + return keys?.Select(GetByProviderKey).WhereNotNull() ?? Enumerable.Empty(); } public virtual IPublishedContent GetById(int memberId) @@ -304,14 +304,14 @@ namespace Umbraco.Web.Security return MemberCache.GetById(memberId); } - public virtual IEnumerable GetById(IEnumerable memberIds) + public virtual IEnumerable GetByIds(IEnumerable memberIds) { - return memberIds?.Select(GetById).WhereNotNull() ?? new IPublishedContent[0]; + return memberIds?.Select(GetById).WhereNotNull() ?? Enumerable.Empty(); } - public virtual IEnumerable GetById(params int[] memberIds) + public virtual IEnumerable GetByIds(params int[] memberIds) { - return memberIds?.Select(GetById).WhereNotNull() ?? new IPublishedContent[0]; + return memberIds?.Select(GetById).WhereNotNull() ?? Enumerable.Empty(); } public virtual IPublishedContent GetById(Guid memberId) @@ -319,14 +319,14 @@ namespace Umbraco.Web.Security return GetByProviderKey(memberId); } - public virtual IEnumerable GetById(IEnumerable memberIds) + public virtual IEnumerable GetByIds(IEnumerable memberIds) { - return GetByProviderKey(memberIds.OfType()); + return GetByProviderKeys(memberIds.OfType()); } - public virtual IEnumerable GetById(params Guid[] memberIds) + public virtual IEnumerable GetByIds(params Guid[] memberIds) { - return GetByProviderKey(memberIds.OfType()); + return GetByProviderKeys(memberIds.OfType()); } public virtual IPublishedContent GetByUsername(string username) diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index e9fdfd73e5..80e3b95534 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -291,7 +291,7 @@ namespace Umbraco.Web public IEnumerable Member(IEnumerable ids) { - return MembershipHelper.GetById(ids); + return MembershipHelper.GetByIds(ids); } public IEnumerable Member(IEnumerable ids) @@ -301,7 +301,7 @@ namespace Umbraco.Web public IEnumerable Member(IEnumerable ids) { - return MembershipHelper.GetById(ids); + return MembershipHelper.GetByIds(ids); } public IEnumerable Member(IEnumerable ids) @@ -326,7 +326,7 @@ namespace Umbraco.Web public IEnumerable Member(params Guid[] ids) { - return MembershipHelper.GetById(ids); + return MembershipHelper.GetByIds(ids); } public IEnumerable Member(params Udi[] ids) From b36288b987cd37122da42f4b261b1ab5a90bcfd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 26 Mar 2019 14:11:01 +0100 Subject: [PATCH 13/23] infinity editing dim-layer for umb-modelcolumn --- src/Umbraco.Web.UI.Client/src/less/modals.less | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/modals.less b/src/Umbraco.Web.UI.Client/src/less/modals.less index 771be1bc2a..8e88774613 100644 --- a/src/Umbraco.Web.UI.Client/src/less/modals.less +++ b/src/Umbraco.Web.UI.Client/src/less/modals.less @@ -55,6 +55,16 @@ position: absolute;; } +.--notInFront .umb-modalcolumn::after { + content: ''; + position: absolute; + top: 0; + bottom: 0; + right: 0; + left: 0; + background: rgba(0,0,0,.4); +} + /* re-align loader */ .umb-modal .umb-loader-wrapper, .umb-modalcolumn .umb-loader-wrapper, .umb-dialog .umb-loader-wrapper{ position:relative; From 458e51096151a1578e02241d9949ae547ebfa7ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 26 Mar 2019 14:57:13 +0100 Subject: [PATCH 14/23] remove double ;; --- src/Umbraco.Web.UI.Client/src/less/modals.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/modals.less b/src/Umbraco.Web.UI.Client/src/less/modals.less index 771be1bc2a..f922d7d95a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/modals.less +++ b/src/Umbraco.Web.UI.Client/src/less/modals.less @@ -52,7 +52,7 @@ bottom: 0px; left: 0px; right: 0px; - position: absolute;; + position: absolute; } /* re-align loader */ From 4a14d45a64199673125e846d51f60b3e76a1216b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 26 Mar 2019 14:57:30 +0100 Subject: [PATCH 15/23] remove inline styling --- .../src/views/content/overlays/schedule.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html index 2bf290b752..42f6ae7b98 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html @@ -27,7 +27,7 @@ {{vm.variants[0].releaseDateFormatted}} - + Set date @@ -59,7 +59,7 @@ {{vm.variants[0].expireDateFormatted}} - + Set date @@ -123,7 +123,7 @@ {{variant.releaseDateFormatted}} - + Set date @@ -149,7 +149,7 @@ {{variant.expireDateFormatted}} - + Set date From d6be02aaecd83823c8b0578a6314a807a86859af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 26 Mar 2019 14:57:45 +0100 Subject: [PATCH 16/23] style set date input --- .../src/less/properties.less | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/properties.less b/src/Umbraco.Web.UI.Client/src/less/properties.less index 916f1b5a3a..d3e69a2d79 100644 --- a/src/Umbraco.Web.UI.Client/src/less/properties.less +++ b/src/Umbraco.Web.UI.Client/src/less/properties.less @@ -16,6 +16,31 @@ border-left: 1px solid @gray-10; } +.date-wrapper__date .flatpickr-input > a { + + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + padding: 5px 15px; + box-sizing: border-box; + min-width: 200px; + + color: @ui-action-discreet-type; + border: 1px dashed @ui-action-discreet-border; + border-radius: 3px; + + &:hover { + text-decoration: none; + color: @ui-action-discreet-type-hover; + border-color: @ui-action-discreet-border-hover; + + localize { + text-decoration: none; + } + } +} + //------------------- HISTORY ------------------ .history { From 4d0d17eb1b856d5c8390bee5541ed6e87f04c4be Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Tue, 26 Mar 2019 15:11:05 +0100 Subject: [PATCH 17/23] Remove params overloads on MembershipHelper --- src/Umbraco.Web/Security/MembershipHelper.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index bbcfc0760e..cdf696c520 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -294,11 +294,6 @@ namespace Umbraco.Web.Security return keys?.Select(GetByProviderKey).WhereNotNull() ?? Enumerable.Empty(); } - public virtual IEnumerable GetByProviderKeys(params object[] keys) - { - return keys?.Select(GetByProviderKey).WhereNotNull() ?? Enumerable.Empty(); - } - public virtual IPublishedContent GetById(int memberId) { return MemberCache.GetById(memberId); @@ -309,11 +304,6 @@ namespace Umbraco.Web.Security return memberIds?.Select(GetById).WhereNotNull() ?? Enumerable.Empty(); } - public virtual IEnumerable GetByIds(params int[] memberIds) - { - return memberIds?.Select(GetById).WhereNotNull() ?? Enumerable.Empty(); - } - public virtual IPublishedContent GetById(Guid memberId) { return GetByProviderKey(memberId); @@ -324,11 +314,6 @@ namespace Umbraco.Web.Security return GetByProviderKeys(memberIds.OfType()); } - public virtual IEnumerable GetByIds(params Guid[] memberIds) - { - return GetByProviderKeys(memberIds.OfType()); - } - public virtual IPublishedContent GetByUsername(string username) { return MemberCache.GetByUsername(username); From 719a4a8b6a50b829e7b8ce1166a5afaafdde436b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 27 Mar 2019 08:29:04 +0100 Subject: [PATCH 18/23] adjusted size --- src/Umbraco.Web.UI.Client/src/less/properties.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/properties.less b/src/Umbraco.Web.UI.Client/src/less/properties.less index d3e69a2d79..d206b2a413 100644 --- a/src/Umbraco.Web.UI.Client/src/less/properties.less +++ b/src/Umbraco.Web.UI.Client/src/less/properties.less @@ -22,7 +22,7 @@ align-items: center; justify-content: center; font-weight: 700; - padding: 5px 15px; + padding: 4px 15px; box-sizing: border-box; min-width: 200px; From 9b13d8f5d77e978d869086c3bebab6d04bed2644 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 27 Mar 2019 10:28:49 +0100 Subject: [PATCH 19/23] Stop logging useless errors in UriExtensions --- src/Umbraco.Core/UriExtensions.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Core/UriExtensions.cs b/src/Umbraco.Core/UriExtensions.cs index 083ca90cc4..1198b26e0f 100644 --- a/src/Umbraco.Core/UriExtensions.cs +++ b/src/Umbraco.Core/UriExtensions.cs @@ -23,21 +23,21 @@ namespace Umbraco.Core /// /// /// There are some special routes we need to check to properly determine this: - /// + /// /// If any route has an extension in the path like .aspx = back office - /// + /// /// These are def back office: /// /Umbraco/BackOffice = back office /// /Umbraco/Preview = back office /// If it's not any of the above, and there's no extension then we cannot determine if it's back office or front-end /// so we can only assume that it is not back office. This will occur if people use an UmbracoApiController for the backoffice /// but do not inherit from UmbracoAuthorizedApiController and do not use [IsBackOffice] attribute. - /// + /// /// These are def front-end: /// /Umbraco/Surface = front-end /// /Umbraco/Api = front-end /// But if we've got this far we'll just have to assume it's front-end anyways. - /// + /// /// internal static bool IsBackOfficeRequest(this Uri url, string applicationPath, IGlobalSettings globalSettings) { @@ -152,9 +152,9 @@ namespace Umbraco.Core var toInclude = new[] {".aspx", ".ashx", ".asmx", ".axd", ".svc"}; return toInclude.Any(ext.InvariantEquals) == false; } - catch (ArgumentException ex) + catch (ArgumentException) { - Current.Logger.Error(typeof(UriExtensions), ex, "Failed to determine if request was client side"); + Current.Logger.Debug(typeof(UriExtensions), "Failed to determine if request was client side (invalid chars in path \"{Path}\"?)", url.LocalPath); return false; } } From 8da9ecc9e4d0f967d9aea54674801b53ed13f85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 27 Mar 2019 12:49:03 +0100 Subject: [PATCH 20/23] date-wrapper styles for variants schedule publishing --- .../src/less/properties.less | 48 ++++++++++++++++++- .../src/views/content/overlays/schedule.html | 28 ++--------- 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/properties.less b/src/Umbraco.Web.UI.Client/src/less/properties.less index d206b2a413..e14bb5c0d6 100644 --- a/src/Umbraco.Web.UI.Client/src/less/properties.less +++ b/src/Umbraco.Web.UI.Client/src/less/properties.less @@ -30,7 +30,51 @@ border: 1px dashed @ui-action-discreet-border; border-radius: 3px; - &:hover { + &:hover, &:focus { + text-decoration: none; + color: @ui-action-discreet-type-hover; + border-color: @ui-action-discreet-border-hover; + + localize { + text-decoration: none; + } + } +} + +//----- VARIANTS SCHEDULED PUBLISH ------ + +.date-wrapper-mini { + display: flex; + flex-direction: row; +} + +.date-wrapper-mini__date { + display: flex; + + margin-left: 5px; + margin-top: 5px; + margin-bottom: 10px; + + &:first-of-type { + margin-left: 0; + } +} + +.date-wrapper-mini__date .flatpickr-input > a { + + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + padding: 1px 15px; + box-sizing: border-box; + min-width: 180px; + + color: @ui-action-discreet-type; + border: 1px dashed @ui-action-discreet-border; + border-radius: 3px; + + &:hover, &:focus { text-decoration: none; color: @ui-action-discreet-type-hover; border-color: @ui-action-discreet-border-hover; @@ -96,4 +140,4 @@ .history-line { display: none; } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html index 42f6ae7b98..8cdc4a0abc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html @@ -84,8 +84,8 @@
-
- +
+
-
+
+
-
Publish:  {{variant.releaseDateFormatted}}
@@ -134,7 +134,7 @@
-
+
Unpublish:  {{variant.expireDateFormatted}}
@@ -182,24 +182,6 @@
-
-
-

-
- -
-
-
- {{ variant.language.name }} -
-
- - - -
-
-
-
-
From 6d9ed6c59bb6cb55d97d25c03195ff23054de391 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 28 Mar 2019 12:46:54 +0100 Subject: [PATCH 21/23] Change Member to Members (plural) for methods returning multiple members --- src/Umbraco.Web/UmbracoHelper.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index 80e3b95534..1c6eb28b92 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -289,52 +289,52 @@ namespace Umbraco.Web return asInt ? MembershipHelper.GetById(asInt.Result) : MembershipHelper.GetByProviderKey(id); } - public IEnumerable Member(IEnumerable ids) + public IEnumerable Members(IEnumerable ids) { return MembershipHelper.GetByIds(ids); } - public IEnumerable Member(IEnumerable ids) + public IEnumerable Members(IEnumerable ids) { return ids.Select(Member).WhereNotNull(); } - public IEnumerable Member(IEnumerable ids) + public IEnumerable Members(IEnumerable ids) { return MembershipHelper.GetByIds(ids); } - public IEnumerable Member(IEnumerable ids) + public IEnumerable Members(IEnumerable ids) { return ids.Select(Member).WhereNotNull(); } - public IEnumerable Member(IEnumerable ids) + public IEnumerable Members(IEnumerable ids) { return ids.Select(Member).WhereNotNull(); } - public IEnumerable Member(params int[] ids) + public IEnumerable Members(params int[] ids) { return ids.Select(Member).WhereNotNull(); } - public IEnumerable Member(params string[] ids) + public IEnumerable Members(params string[] ids) { return ids.Select(Member).WhereNotNull(); } - public IEnumerable Member(params Guid[] ids) + public IEnumerable Members(params Guid[] ids) { return MembershipHelper.GetByIds(ids); } - public IEnumerable Member(params Udi[] ids) + public IEnumerable Members(params Udi[] ids) { return ids.Select(Member).WhereNotNull(); } - public IEnumerable Member(params object[] ids) + public IEnumerable Members(params object[] ids) { return ids.Select(Member).WhereNotNull(); } From 07bb7ac0f7c9bebf57b0ba31d650d76ee896b217 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 29 Mar 2019 08:26:36 +0100 Subject: [PATCH 22/23] Add content.SetValue overload for posted files --- src/Umbraco.Core/ContentExtensions.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/ContentExtensions.cs b/src/Umbraco.Core/ContentExtensions.cs index f802c2d0d9..a7d40b0b7d 100644 --- a/src/Umbraco.Core/ContentExtensions.cs +++ b/src/Umbraco.Core/ContentExtensions.cs @@ -7,6 +7,7 @@ using System.Web; using System.Xml.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using NPoco.Expressions; using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -52,8 +53,8 @@ namespace Umbraco.Core return ContentStatus.Unpublished; } - - + + #endregion /// @@ -134,9 +135,14 @@ namespace Umbraco.Core /// /// Sets the posted file value of a property. /// - /// This really is for FileUpload fields only, and should be obsoleted. For anything else, - /// you need to store the file by yourself using Store and then figure out - /// how to deal with auto-fill properties (if any) and thumbnails (if any) by yourself. + public static void SetValue(this IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias, string filename, HttpPostedFileBase postedFile, string culture = null, string segment = null) + { + content.SetValue(contentTypeBaseServiceProvider, propertyTypeAlias, postedFile.FileName, postedFile.InputStream, culture, segment); + } + + /// + /// Sets the posted file value of a property. + /// public static void SetValue(this IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null) { if (filename == null || filestream == null) return; From cea8753ff28a3b6c695ffd10e183c9f4e6fb5e45 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 28 Mar 2019 12:10:59 +0100 Subject: [PATCH 23/23] Replace dynamic ViewBag with ViewData --- .../Umbraco/Install/Views/Index.cshtml | 6 +- .../Umbraco/Views/AuthorizeUpgrade.cshtml | 4 +- .../Umbraco/Views/Default.cshtml | 4 +- .../Editors/BackOfficeController.cs | 37 ++++------ .../Install/Controllers/InstallController.cs | 4 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 + src/Umbraco.Web/ViewDataExtensions.cs | 71 +++++++++++++++++++ 7 files changed, 95 insertions(+), 32 deletions(-) create mode 100644 src/Umbraco.Web/ViewDataExtensions.cs diff --git a/src/Umbraco.Web.UI/Umbraco/Install/Views/Index.cshtml b/src/Umbraco.Web.UI/Umbraco/Install/Views/Index.cshtml index 1d397bfd01..e74dbea217 100644 --- a/src/Umbraco.Web.UI/Umbraco/Install/Views/Index.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Install/Views/Index.cshtml @@ -7,7 +7,7 @@ - + @@ -66,8 +66,8 @@ var Umbraco = {}; Umbraco.Sys = {}; Umbraco.Sys.ServerVariables = { - "installApiBaseUrl": "@ViewBag.InstallApiBaseUrl", - "umbracoBaseUrl": "@ViewBag.UmbracoBaseFolder" + "installApiBaseUrl": "@ViewData.GetInstallApiBaseUrl()", + "umbracoBaseUrl": "@ViewData.GetUmbracoBaseFolder()" }; diff --git a/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml index fba9a83789..b7c1e6540c 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml @@ -51,7 +51,7 @@ @{ var externalLoginUrl = Url.Action("ExternalLogin", "BackOffice", new { - area = ViewBag.UmbracoPath, + area = ViewData.GetUmbracoPath(), //Custom redirect URL since we don't want to just redirect to the back office since this is for authing upgrades redirectUrl = Url.Action("AuthorizeUpgrade", "BackOffice") }); @@ -61,7 +61,7 @@