From 643b79c145ad6b6c48a416c57f2736faf4b4a79e Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 14 Sep 2023 13:17:35 +0200
Subject: [PATCH 1/4] V12: Property editors should only contain layout when in
preview mode (#14796)
* Revert "Make sure the property editor layout is contained within its container (prevent Z-index bleed-through) (#13583)"
This reverts commit 8463d906a747868ddbda3b1c01465f6cee1a589a.
* remove seemingly unused attribute readonly
* contain everything with contain:layout
this is set if the property editor is in preview mode to make sure all overlays work
* Revert "remove seemingly unused attribute readonly"
This reverts commit 7a2743e8f664e707e8df5022fe754dfd77c508ea.
---
.../src/less/components/umb-property-editor.less | 6 +++++-
.../src/views/components/property/umb-property-editor.html | 4 ++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less
index d2d6a970b9..c34ada479e 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less
@@ -1,6 +1,10 @@
.umb-property-editor {
position: relative;
- contain: layout;
+ contain: style;
+
+ &.is-preview {
+ contain: layout;
+ }
}
.umb-property-editor--preview {
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html
index 8667fb84c2..b2387e230a 100644
--- a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html
+++ b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html
@@ -1,4 +1,4 @@
-
+
-
+
From 173d8dcf47fcd18584b80190db14144a363cbdd5 Mon Sep 17 00:00:00 2001
From: Zeegaan
Date: Wed, 20 Sep 2023 10:29:50 +0200
Subject: [PATCH 2/4] Bump version
---
version.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/version.json b/version.json
index 4b04b0255b..de4e207d31 100644
--- a/version.json
+++ b/version.json
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
- "version": "12.2.0-rc",
+ "version": "12.2.0",
"assemblyVersion": {
"precision": "build"
},
From 2335924b5714ad9b1138222bbd81bc344c439d13 Mon Sep 17 00:00:00 2001
From: Kenn Jacobsen
Date: Thu, 21 Sep 2023 09:25:29 +0200
Subject: [PATCH 3/4] Ensure that value type JSON is translated correctly for
Delivery API output (#14839)
---
.../ValueConverters/JsonValueConverter.cs | 15 ++++++++--
.../DeliveryApi/JsonValueConverterTests.cs | 30 +++++++++++++++++++
.../PropertyEditorValueConverterTests.cs | 17 +++++++++++
3 files changed, 60 insertions(+), 2 deletions(-)
create mode 100644 tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/JsonValueConverterTests.cs
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/JsonValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/JsonValueConverter.cs
index 4eaa24ecf9..e6345ab61d 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/JsonValueConverter.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/JsonValueConverter.cs
@@ -1,10 +1,12 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
+using System.Text.Json.Nodes;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.PropertyEditors.DeliveryApi;
using Umbraco.Extensions;
namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
@@ -16,7 +18,7 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
/// Since this is a default (umbraco) converter it will be ignored if another converter found conflicts with this one.
///
[DefaultPropertyValueConverter]
-public class JsonValueConverter : PropertyValueConverterBase
+public class JsonValueConverter : PropertyValueConverterBase, IDeliveryApiPropertyValueConverter
{
private readonly ILogger _logger;
private readonly PropertyEditorCollection _propertyEditors;
@@ -76,5 +78,14 @@ public class JsonValueConverter : PropertyValueConverterBase
return sourceString;
}
- // TODO: Now to convert that to XPath!
+ public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType)
+ => GetPropertyCacheLevel(propertyType);
+
+ public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType)
+ => typeof(JsonNode);
+
+ public object? ConvertIntermediateToDeliveryApiObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview, bool expanding)
+ => inter is JObject jObject
+ ? JsonNode.Parse(jObject.ToString())
+ : null;
}
diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/JsonValueConverterTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/JsonValueConverterTests.cs
new file mode 100644
index 0000000000..ac22f3985f
--- /dev/null
+++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/JsonValueConverterTests.cs
@@ -0,0 +1,30 @@
+using System.Text.Json.Nodes;
+using Microsoft.Extensions.Logging;
+using Moq;
+using NUnit.Framework;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.PropertyEditors;
+using Umbraco.Cms.Core.PropertyEditors.ValueConverters;
+
+namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi;
+
+[TestFixture]
+public class JsonValueConverterTests : PropertyValueConverterTests
+{
+ [Test]
+ public void JsonValueConverterTests_ConvertsCustomPropertyWithValueTypeJson()
+ {
+ var valueEditor = Mock.Of(x => x.ValueType == ValueTypes.Json);
+ var dataEditor = Mock.Of(x => x.GetValueEditor() == valueEditor);
+ var propertyEditors = new PropertyEditorCollection(new DataEditorCollection(() => new[] { dataEditor }));
+ var propertyType = Mock.Of(x => x.EditorAlias == "My.Custom.Json");
+
+ var valueConverter = new JsonValueConverter(propertyEditors, Mock.Of>());
+ var inter = valueConverter.ConvertSourceToIntermediate(Mock.Of(), propertyType, "{\"message\": \"Hello, JSON\"}", false);
+ var result = valueConverter.ConvertIntermediateToDeliveryApiObject(Mock.Of(), propertyType, PropertyCacheLevel.Element, inter, false, false);
+ Assert.IsTrue(result is JsonNode);
+ JsonNode jsonNode = (JsonNode)result;
+ Assert.AreEqual("Hello, JSON", jsonNode["message"]!.GetValue());
+ }
+}
diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/PropertyEditorValueConverterTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/PropertyEditorValueConverterTests.cs
index b3537c4659..d046064af2 100644
--- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/PropertyEditorValueConverterTests.cs
+++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/PropertyEditorValueConverterTests.cs
@@ -3,7 +3,9 @@
using System.Collections.Generic;
using System.Linq;
+using Microsoft.Extensions.Logging;
using Moq;
+using Newtonsoft.Json.Linq;
using NUnit.Framework;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
@@ -133,4 +135,19 @@ public class PropertyEditorValueConverterTests
Assert.AreEqual(expected, result);
}
+
+ [Test]
+ public void CanConvertManifestBasedPropertyWithValueTypeJson()
+ {
+ var valueEditor = Mock.Of(x => x.ValueType == ValueTypes.Json);
+ var dataEditor = Mock.Of(x => x.GetValueEditor() == valueEditor);
+ var propertyEditors = new PropertyEditorCollection(new DataEditorCollection(() => new[] { dataEditor }));
+ var propertyType = Mock.Of(x => x.EditorAlias == "My.Custom.Json");
+
+ var valueConverter = new JsonValueConverter(propertyEditors, Mock.Of>());
+ var inter = valueConverter.ConvertSourceToIntermediate(Mock.Of(), propertyType, "{\"message\": \"Hello, JSON\"}", false);
+ var result = valueConverter.ConvertIntermediateToObject(Mock.Of(), propertyType, PropertyCacheLevel.Element, inter, false) as JObject;
+ Assert.IsNotNull(result);
+ Assert.AreEqual("Hello, JSON", result["message"]!.Value());
+ }
}
From d39502674e95d3a0474517c491b3ebc269bc4e72 Mon Sep 17 00:00:00 2001
From: Bjarke Berg
Date: Fri, 22 Sep 2023 10:38:55 +0200
Subject: [PATCH 4/4] Added our own db context pool, that basically bypass the
bool until umbraco is in Run mode (#14852)
---
...mbracoEFCoreServiceCollectionExtensions.cs | 18 ++++++-
.../UmbracoPooledDbContextFactory.cs | 47 +++++++++++++++++++
2 files changed, 64 insertions(+), 1 deletion(-)
create mode 100644 src/Umbraco.Cms.Persistence.EFCore/Factories/UmbracoPooledDbContextFactory.cs
diff --git a/src/Umbraco.Cms.Persistence.EFCore/Extensions/UmbracoEFCoreServiceCollectionExtensions.cs b/src/Umbraco.Cms.Persistence.EFCore/Extensions/UmbracoEFCoreServiceCollectionExtensions.cs
index da9c2e59ef..ded5be40fd 100644
--- a/src/Umbraco.Cms.Persistence.EFCore/Extensions/UmbracoEFCoreServiceCollectionExtensions.cs
+++ b/src/Umbraco.Cms.Persistence.EFCore/Extensions/UmbracoEFCoreServiceCollectionExtensions.cs
@@ -1,11 +1,13 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DistributedLocking;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Persistence.EFCore.Factories;
using Umbraco.Cms.Persistence.EFCore.Locking;
-using Umbraco.Cms.Persistence.EFCore.Migrations;
using Umbraco.Cms.Persistence.EFCore.Scoping;
namespace Umbraco.Extensions;
@@ -17,6 +19,13 @@ public static class UmbracoEFCoreServiceCollectionExtensions
public static IServiceCollection AddUmbracoEFCoreContext(this IServiceCollection services, DefaultEFCoreOptionsAction? defaultEFCoreOptionsAction = null)
where T : DbContext
{
+ var optionsBuilder = new DbContextOptionsBuilder();
+ services.TryAddSingleton>(
+ sp =>
+ {
+ SetupDbContext(defaultEFCoreOptionsAction, sp, optionsBuilder);
+ return new UmbracoPooledDbContextFactory(sp.GetRequiredService(),optionsBuilder.Options);
+ });
services.AddPooledDbContextFactory((provider, builder) => SetupDbContext(defaultEFCoreOptionsAction, provider, builder));
services.AddTransient(services => services.GetRequiredService>().CreateDbContext());
@@ -39,6 +48,13 @@ public static class UmbracoEFCoreServiceCollectionExtensions
connectionString = connectionString.Replace(Constants.System.DataDirectoryPlaceholder, dataDirectory);
}
+ var optionsBuilder = new DbContextOptionsBuilder();
+ services.TryAddSingleton>(
+ sp =>
+ {
+ SetupDbContext(defaultEFCoreOptionsAction, sp, optionsBuilder);
+ return new UmbracoPooledDbContextFactory(sp.GetRequiredService(),optionsBuilder.Options);
+ });
services.AddPooledDbContextFactory(options => defaultEFCoreOptionsAction?.Invoke(options, providerName, connectionString));
services.AddTransient(services => services.GetRequiredService>().CreateDbContext());
diff --git a/src/Umbraco.Cms.Persistence.EFCore/Factories/UmbracoPooledDbContextFactory.cs b/src/Umbraco.Cms.Persistence.EFCore/Factories/UmbracoPooledDbContextFactory.cs
new file mode 100644
index 0000000000..de0f7db200
--- /dev/null
+++ b/src/Umbraco.Cms.Persistence.EFCore/Factories/UmbracoPooledDbContextFactory.cs
@@ -0,0 +1,47 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Umbraco.Cms.Core;
+using Umbraco.Cms.Core.Services;
+
+namespace Umbraco.Cms.Persistence.EFCore.Factories;
+
+///
+internal class UmbracoPooledDbContextFactory : PooledDbContextFactory
+ where TContext : DbContext
+{
+ private readonly IRuntimeState _runtimeState;
+ private readonly DbContextOptions _options;
+
+ ///
+ public UmbracoPooledDbContextFactory(IRuntimeState runtimeState, DbContextOptions options, int poolSize = 1024 /*DbContextPool.DefaultPoolSize*/) : base(options, poolSize)
+ {
+ _runtimeState = runtimeState;
+ _options = options;
+ }
+
+ ///
+ public override TContext CreateDbContext()
+ {
+ if (_runtimeState.Level == RuntimeLevel.Run)
+ {
+ return base.CreateDbContext();
+ }
+ else
+ {
+ return (TContext?)Activator.CreateInstance(typeof(TContext), _options) ?? throw new InvalidOperationException("Unable to create DbContext");
+ }
+ }
+
+ ///
+ public override async Task CreateDbContextAsync(CancellationToken cancellationToken = default)
+ {
+ if (_runtimeState.Level == RuntimeLevel.Run)
+ {
+ return await base.CreateDbContextAsync(cancellationToken);
+ }
+ else
+ {
+ return (TContext?)Activator.CreateInstance(typeof(TContext), _options) ?? throw new InvalidOperationException("Unable to create DbContext");
+ }
+ }
+}