From d0cc33b41cf45a3c81ab2eaf2636c63db02b8d9f Mon Sep 17 00:00:00 2001 From: Jason Prothero Date: Wed, 3 Apr 2024 13:17:26 -0700 Subject: [PATCH] upgrade to umbraco 13.2.2 --- .../Options/TinyMceConfig.cs | 4 + .../TinyBlockEditorValidatorBase.cs | 3 + .../PropertyEditors/TinyBlockEditorValues.cs | 2 + .../TinyBlockValuePropertyValueEditorBase.cs | 198 +++++++++--------- .../TinyMceUmbracoPremiumConfiguration.cs | 2 + ...inyMceUmbracoPremiumConfigurationEditor.cs | 2 + .../TinyMceUmbracoPremiumEditor.cs | 13 +- .../TinyRichTextEditorBlockDataConverter.cs | 2 + .../TinyRichTextEditorBlockValidator.cs | 3 + .../TinyRichTextEditorPastedImages.cs | 3 + .../TinyMCE.Umbraco.Premium.csproj | 6 +- .../TinyMceUmbracoPremiumValueConverter.cs | 32 ++- .../PreValues/tinymce.rte.prevalues.html | 2 +- .../TinyMCE.Umbraco.Premium/package.manifest | 1 - .../premium.rte.controller.js | 184 ---------------- .../premuim.rte.component.js | 3 +- src/Umbraco.Cms.Demo/Umbraco.Cms.Demo.csproj | 2 +- 17 files changed, 167 insertions(+), 295 deletions(-) delete mode 100644 src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/premium.rte.controller.js diff --git a/src/TinyMCE.Umbraco.Premium/Options/TinyMceConfig.cs b/src/TinyMCE.Umbraco.Premium/Options/TinyMceConfig.cs index d555765..aa9f2e8 100644 --- a/src/TinyMCE.Umbraco.Premium/Options/TinyMceConfig.cs +++ b/src/TinyMCE.Umbraco.Premium/Options/TinyMceConfig.cs @@ -7,6 +7,10 @@ namespace TinyMCE.Umbraco.Premium.Options { + /// + /// Custom configuration model used in the appSettings.config or anywhere the + /// enviroment variables are defined. + /// public class TinyMceConfig { public string apikey { get; set; } = ""; diff --git a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockEditorValidatorBase.cs b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockEditorValidatorBase.cs index 6119c0d..244cc1c 100644 --- a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockEditorValidatorBase.cs +++ b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockEditorValidatorBase.cs @@ -6,6 +6,9 @@ namespace TinyMCE.Umbraco.Premium.PropertyEditors; +/// +/// Based on Umbraco-CMS\src\Umbraco.Infrastructure\PropertyEditors\BlockEditorValidatorBase.cs +/// internal abstract class TinyBlockEditorValidatorBase : ComplexEditorValidator { private readonly IContentTypeService _contentTypeService; diff --git a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockEditorValues.cs b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockEditorValues.cs index b77c3e3..5bc28c4 100644 --- a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockEditorValues.cs +++ b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockEditorValues.cs @@ -11,6 +11,8 @@ namespace TinyMCE.Umbraco.Premium.PropertyEditors; /// /// Used to deserialize json values and clean up any values based on the existence of element types and layout structure +/// +/// Based on Umbraco-CMS\src\Umbraco.Infrastructure\PropertyEditors\BlockEditorValues.cs /// internal class TinyBlockEditorValues { diff --git a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockValuePropertyValueEditorBase.cs b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockValuePropertyValueEditorBase.cs index d7e3896..99de8c5 100644 --- a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockValuePropertyValueEditorBase.cs +++ b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyBlockValuePropertyValueEditorBase.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Blocks; @@ -10,58 +11,69 @@ namespace TinyMCE.Umbraco.Premium.PropertyEditors { - internal abstract class TinyBlockValuePropertyValueEditorBase : DataValueEditor, IDataValueReference, IDataValueTags + /// + /// Based on Umbraco-CMS\src\Umbraco.Infrastructure\PropertyEditors\BlockValuePropertyValueEditorBase.cs + /// + internal abstract class TinyBlockValuePropertyValueEditorBase : DataValueEditor, IDataValueReference, IDataValueTags { - private readonly IDataTypeService _dataTypeService; - private readonly PropertyEditorCollection _propertyEditors; - private readonly ILogger _logger; + private readonly IDataTypeConfigurationCache _dataTypeConfigurationCache; + private readonly PropertyEditorCollection _propertyEditors; + private readonly ILogger _logger; + private readonly DataValueReferenceFactoryCollection _dataValueReferenceFactoryCollection; - protected TinyBlockValuePropertyValueEditorBase( + protected TinyBlockValuePropertyValueEditorBase( DataEditorAttribute attribute, PropertyEditorCollection propertyEditors, - IDataTypeService dataTypeService, - ILocalizedTextService textService, + IDataTypeConfigurationCache dataTypeConfigurationCache, + ILocalizedTextService textService, ILogger logger, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, - IIOHelper ioHelper) + IIOHelper ioHelper, + DataValueReferenceFactoryCollection dataValueReferenceFactoryCollection) : base(textService, shortStringHelper, jsonSerializer, ioHelper, attribute) { - _propertyEditors = propertyEditors; - _dataTypeService = dataTypeService; - _logger = logger; - } + _propertyEditors = propertyEditors; + _dataTypeConfigurationCache = dataTypeConfigurationCache; + _logger = logger; + _dataValueReferenceFactoryCollection = dataValueReferenceFactoryCollection; + } - /// - public abstract IEnumerable GetReferences(object? value); + /// + public abstract IEnumerable GetReferences(object? value); protected IEnumerable GetBlockValueReferences(BlockValue blockValue) { - var result = new List(); - - // loop through all content and settings data - foreach (BlockItemData row in blockValue.ContentData.Concat(blockValue.SettingsData)) - { - foreach (KeyValuePair prop in row.PropertyValues) - { - IDataEditor? propEditor = _propertyEditors[prop.Value.PropertyType.PropertyEditorAlias]; - - IDataValueEditor? valueEditor = propEditor?.GetValueEditor(); - if (!(valueEditor is IDataValueReference reference)) - { - continue; - } - - var val = prop.Value.Value?.ToString(); - - IEnumerable refs = reference.GetReferences(val); - - result.AddRange(refs); - } - } - - return result; - } + var result = new HashSet(); + BlockItemData.BlockPropertyValue[] propertyValues = blockValue.ContentData.Concat(blockValue.SettingsData) + .SelectMany(x => x.PropertyValues.Values).ToArray(); + foreach (IGrouping valuesByPropertyEditorAlias in propertyValues.GroupBy(x => x.PropertyType.PropertyEditorAlias, x => x.Value)) + { + if (!_propertyEditors.TryGet(valuesByPropertyEditorAlias.Key, out IDataEditor? dataEditor)) + { + continue; + } + + var districtValues = valuesByPropertyEditorAlias.Distinct().ToArray(); + + if (dataEditor.GetValueEditor() is IDataValueReference reference) + { + foreach (UmbracoEntityReference value in districtValues.SelectMany(reference.GetReferences)) + { + result.Add(value); + } + } + + IEnumerable references = _dataValueReferenceFactoryCollection.GetReferences(dataEditor, districtValues); + + foreach (UmbracoEntityReference value in references) + { + result.Add(value); + } + } + + return result; + } /// public abstract IEnumerable GetTags(object? value, object? dataTypeConfiguration, int? languageId); @@ -82,9 +94,9 @@ protected IEnumerable GetBlockValueTags(BlockValue blockValue, int? langua continue; } - object? configuration = _dataTypeService.GetDataType(prop.Value.PropertyType.DataTypeKey)?.Configuration; + object? configuration = _dataTypeConfigurationCache.GetConfiguration(prop.Value.PropertyType.DataTypeKey); - result.AddRange(tagsProvider.GetTags(prop.Value.Value, configuration, languageId)); + result.AddRange(tagsProvider.GetTags(prop.Value.Value, configuration, languageId)); } } @@ -105,56 +117,44 @@ protected void MapBlockValueToEditor(IProperty property, BlockValue blockValue) private void MapBlockItemDataToEditor(IProperty property, List items) { - var valEditors = new Dictionary(); - - foreach (BlockItemData row in items) - { - foreach (KeyValuePair prop in row.PropertyValues) - { - // create a temp property with the value - // - force it to be culture invariant as the block editor can't handle culture variant element properties - prop.Value.PropertyType.Variations = ContentVariation.Nothing; - var tempProp = new Property(prop.Value.PropertyType); - tempProp.SetValue(prop.Value.Value); - - IDataEditor? propEditor = _propertyEditors[prop.Value.PropertyType.PropertyEditorAlias]; - if (propEditor == null) - { - // NOTE: This logic was borrowed from Nested Content and I'm unsure why it exists. - // if the property editor doesn't exist I think everything will break anyways? - // update the raw value since this is what will get serialized out - row.RawPropertyValues[prop.Key] = tempProp.GetValue()?.ToString(); - continue; - } - - IDataType? dataType = _dataTypeService.GetDataType(prop.Value.PropertyType.DataTypeId); - if (dataType == null) - { - // deal with weird situations by ignoring them (no comment) - row.PropertyValues.Remove(prop.Key); - _logger.LogWarning( - "ToEditor removed property value {PropertyKey} in row {RowId} for property type {PropertyTypeAlias}", - prop.Key, - row.Key, - property.PropertyType.Alias); - continue; - } - - if (!valEditors.TryGetValue(dataType.Id, out IDataValueEditor? valEditor)) - { - var tempConfig = dataType.Configuration; - valEditor = propEditor.GetValueEditor(tempConfig); - - valEditors.Add(dataType.Id, valEditor); - } - - var convValue = valEditor.ToEditor(tempProp); - - // update the raw value since this is what will get serialized out - row.RawPropertyValues[prop.Key] = convValue; - } - } - } + var valEditors = new Dictionary(); + + foreach (BlockItemData row in items) + { + foreach (KeyValuePair prop in row.PropertyValues) + { + // create a temp property with the value + // - force it to be culture invariant as the block editor can't handle culture variant element properties + prop.Value.PropertyType.Variations = ContentVariation.Nothing; + var tempProp = new Property(prop.Value.PropertyType); + tempProp.SetValue(prop.Value.Value); + + IDataEditor? propEditor = _propertyEditors[prop.Value.PropertyType.PropertyEditorAlias]; + if (propEditor == null) + { + // NOTE: This logic was borrowed from Nested Content and I'm unsure why it exists. + // if the property editor doesn't exist I think everything will break anyways? + // update the raw value since this is what will get serialized out + row.RawPropertyValues[prop.Key] = tempProp.GetValue()?.ToString(); + continue; + } + + Guid dataTypeKey = prop.Value.PropertyType.DataTypeKey; + if (!valEditors.TryGetValue(dataTypeKey, out IDataValueEditor? valEditor)) + { + var configuration = _dataTypeConfigurationCache.GetConfiguration(dataTypeKey); + valEditor = propEditor.GetValueEditor(configuration); + + valEditors.Add(dataTypeKey, valEditor); + } + + var convValue = valEditor.ToEditor(tempProp); + + // update the raw value since this is what will get serialized out + row.RawPropertyValues[prop.Key] = convValue; + } + } + } private void MapBlockItemDataFromEditor(List items) { @@ -162,21 +162,21 @@ private void MapBlockItemDataFromEditor(List items) { foreach (KeyValuePair prop in row.PropertyValues) { - // Fetch the property types prevalue - var propConfiguration = _dataTypeService.GetDataType(prop.Value.PropertyType.DataTypeId)?.Configuration; + // Fetch the property types prevalue + var configuration = _dataTypeConfigurationCache.GetConfiguration(prop.Value.PropertyType.DataTypeKey); - // Lookup the property editor - IDataEditor? propEditor = _propertyEditors[prop.Value.PropertyType.PropertyEditorAlias]; + // Lookup the property editor + IDataEditor? propEditor = _propertyEditors[prop.Value.PropertyType.PropertyEditorAlias]; if (propEditor == null) { continue; } - // Create a fake content property data object - var contentPropData = new ContentPropertyData(prop.Value.Value, propConfiguration); + // Create a fake content property data object + var contentPropData = new ContentPropertyData(prop.Value.Value, configuration); - // Get the property editor to do it's conversion - var newValue = propEditor.GetValueEditor().FromEditor(contentPropData, prop.Value.Value); + // Get the property editor to do it's conversion + var newValue = propEditor.GetValueEditor().FromEditor(contentPropData, prop.Value.Value); // update the raw value since this is what will get serialized out row.RawPropertyValues[prop.Key] = newValue; diff --git a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumConfiguration.cs b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumConfiguration.cs index 149b625..adfe64f 100644 --- a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumConfiguration.cs +++ b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumConfiguration.cs @@ -5,6 +5,8 @@ namespace TinyMCE.Umbraco.Premium.PropertyEditors; /// /// Represents the configuration for the rich text value editor. +/// +/// Extends Umbraco-CMS\src\Umbraco.Core\PropertyEditors\RichTextConfiguration.cs /// public class TinyMceUmbracoPremiumConfiguration : RichTextConfiguration { diff --git a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumConfigurationEditor.cs b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumConfigurationEditor.cs index 58f170c..b32312e 100644 --- a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumConfigurationEditor.cs +++ b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumConfigurationEditor.cs @@ -8,6 +8,8 @@ namespace TinyMCE.Umbraco.Premium.PropertyEditors; /// /// Represents the configuration editor for the rich text value editor. +/// +/// Based on Umbraco-CMS\src\Umbraco.Core\PropertyEditors\RichTextConfigurationEditor.cs /// public class TinyMceUmbracoPremiumConfigurationEditor : ConfigurationEditor { diff --git a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumEditor.cs b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumEditor.cs index b6bc75f..14db2a3 100644 --- a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumEditor.cs +++ b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyMceUmbracoPremiumEditor.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Logging; using System.Diagnostics.CodeAnalysis; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Media; @@ -24,6 +25,9 @@ namespace TinyMCE.Umbraco.Premium.PropertyEditors /// /// Represents the TinyMCE.Umbraco.Premium Rich Text property editor. + /// + /// Based on Umbraco-CMS\src\Umbraco.Infrastructure\PropertyEditors\RichTextPropertyEditor.cs + /// with modifications /// [DataEditor( Constants.PropertyEditors.Aliases.TinyMceUmbracoPremiumRte, @@ -185,8 +189,8 @@ internal class TinyMceUmbracoPremiumPropertyValueEditor : TinyBlockValueProperty public TinyMceUmbracoPremiumPropertyValueEditor( DataEditorAttribute attribute, PropertyEditorCollection propertyEditors, - IDataTypeService dataTypeService, - ILogger logger, + IDataTypeConfigurationCache dataTypeReadCache, + ILogger logger, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, @@ -198,8 +202,9 @@ public TinyMceUmbracoPremiumPropertyValueEditor( IHtmlSanitizer htmlSanitizer, IHtmlMacroParameterParser macroParameterParser, IContentTypeService contentTypeService, - IPropertyValidationService propertyValidationService) - : base(attribute, propertyEditors, dataTypeService, localizedTextService, logger, shortStringHelper, jsonSerializer, ioHelper) + IPropertyValidationService propertyValidationService, + DataValueReferenceFactoryCollection dataValueReferenceFactoryCollection) + : base(attribute, propertyEditors, dataTypeReadCache, localizedTextService, logger, shortStringHelper, jsonSerializer, ioHelper, dataValueReferenceFactoryCollection) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _imageSourceParser = imageSourceParser; diff --git a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorBlockDataConverter.cs b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorBlockDataConverter.cs index 805ec87..a1c1c7f 100644 --- a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorBlockDataConverter.cs +++ b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorBlockDataConverter.cs @@ -6,6 +6,8 @@ namespace TinyMCE.Umbraco.Premium.PropertyEditors; /// /// Data converter for blocks in the richtext property editor +/// +/// Based on Umbraco-CMS\src\Umbraco.Infrastructure\Models\Blocks\RichTextEditorBlockDataConverter.cs /// internal sealed class TinyRichTextEditorBlockDataConverter : BlockEditorDataConverter { diff --git a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorBlockValidator.cs b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorBlockValidator.cs index 39b8471..4e6275f 100644 --- a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorBlockValidator.cs +++ b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorBlockValidator.cs @@ -10,6 +10,9 @@ namespace TinyMCE.Umbraco.Premium.PropertyEditors; +/// +/// Based on Umbraco-CMS\src\Umbraco.Infrastructure\PropertyEditors\RichTextEditorBlockValidator.cs +/// internal class TinyRichTextEditorBlockValidator : TinyBlockEditorValidatorBase { private readonly TinyBlockEditorValues _blockEditorValues; diff --git a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorPastedImages.cs b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorPastedImages.cs index 141d0fb..ea84c9e 100644 --- a/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorPastedImages.cs +++ b/src/TinyMCE.Umbraco.Premium/PropertyEditors/TinyRichTextEditorPastedImages.cs @@ -26,6 +26,9 @@ namespace TinyMCE.Umbraco.Premium.PropertyEditors; +/// +/// Based on Umbraco-CMS\src\Umbraco.Infrastructure\PropertyEditors\RichTextEditorPastedImages.cs +/// public sealed class TinyRichTextEditorPastedImages { private const string TemporaryImageDataAttribute = "data-tmpimg"; diff --git a/src/TinyMCE.Umbraco.Premium/TinyMCE.Umbraco.Premium.csproj b/src/TinyMCE.Umbraco.Premium/TinyMCE.Umbraco.Premium.csproj index 87e5122..3a005ef 100644 --- a/src/TinyMCE.Umbraco.Premium/TinyMCE.Umbraco.Premium.csproj +++ b/src/TinyMCE.Umbraco.Premium/TinyMCE.Umbraco.Premium.csproj @@ -21,9 +21,9 @@ - - - + + + diff --git a/src/TinyMCE.Umbraco.Premium/ValueConverters/TinyMceUmbracoPremiumValueConverter.cs b/src/TinyMCE.Umbraco.Premium/ValueConverters/TinyMceUmbracoPremiumValueConverter.cs index 5a29c86..191889b 100644 --- a/src/TinyMCE.Umbraco.Premium/ValueConverters/TinyMceUmbracoPremiumValueConverter.cs +++ b/src/TinyMCE.Umbraco.Premium/ValueConverters/TinyMceUmbracoPremiumValueConverter.cs @@ -31,6 +31,8 @@ namespace TinyMCE.Umbraco.Premium.ValueConverters /// Value converter for the TinyMCE Umbraco Premium RTE so that it always returns IHtmlString so that Html.Raw doesn't have to be used. /// /// NOTE: extending the normal RTE ValueConverter so that locallinks and other key items are converted. + /// + /// Extends Umbraco-CMS\src\Umbraco.Infrastructure\PropertyEditors\ValueConverters\RteMacroRenderingValueConverter.cs /// public class TinyMceUmbracoPremiumValueConverter : RteMacroRenderingValueConverter, IDeliveryApiPropertyValueConverter { @@ -84,6 +86,14 @@ public bool IsRichTextBlockModelNull(object intermediateValue) return isNull; } + + /// + /// Did it this way because there was no IRichTextEditorIntermediateValue interface. + /// + /// TODO: create a new model with this interface? + /// + /// + /// public RichTextBlockModel GetRichTextBlockModelProperty(object intermediateValue) { foreach (var v in intermediateValue.GetType().GetProperties()) @@ -101,6 +111,14 @@ public RichTextBlockModel GetRichTextBlockModelProperty(object intermediateValue return RichTextBlockModel.Empty; } + /// + /// Did it this way because there was no IRichTextEditorIntermediateValue interface. + /// + /// TODO: create a new model with this interface? + /// + /// + /// + /// public object SetRichTextBlockModelProperty(object intermediateValue, RichTextBlockModel richTextBlockModel) { foreach (var v in intermediateValue.GetType().GetProperties()) @@ -119,6 +137,7 @@ public object SetRichTextBlockModelProperty(object intermediateValue, RichTextBl { var intermediateValue = base.ConvertSourceToIntermediate(owner,propertyType,source,preview); // Have to do it this way because the RichTextEditorIntermediateValue model is private in Umbraco and if we don't use that nothing renders + // NOTE: in v13.2.2 there is now an interface IRichTextEditorIntermediateValue that we may be able to leverage if (intermediateValue == null) { @@ -132,22 +151,28 @@ public object SetRichTextBlockModelProperty(object intermediateValue, RichTextBl if(!intermediateRichTextBlockModel.Any()) { // Copying what Umbraco does here because most of the classes are internal or private and the block rendering doesn't work because they call the wrong converter + // from the RteMacroRenderingValueConverter.ConvertSourceToIntermediate() method in Umbraco if (RichTextPropertyEditorHelper.TryParseRichTextEditorValue(source, _jsonSerializer, _logger, out RichTextEditorValue? richTextEditorValue) is false) { return null; } + // from the RteMacroRenderingValueConverter.ParseRichTextBlockModel() method in Umbraco RichTextConfiguration? configuration = propertyType.DataType.ConfigurationAs(); if (configuration?.Blocks?.Any() is not true) { return null; } + // Pulled from BlockPropertyValueCreatorBase.CreateBlockModel() BlockEditorData converted = _blockDataConverter.Convert(richTextEditorValue.Blocks); + + // Used in this method only var referenceCacheLevel = PropertyCacheLevel.Element; var richTextBlockModel = RichTextBlockModel.Empty; + /////// // Pulled from BlockPropertyValueCreatorBase.CreateBlockModel() IEnumerable? layout = converted.Layout?.ToObject>(); if (layout is null) @@ -251,6 +276,7 @@ public object SetRichTextBlockModelProperty(object intermediateValue, RichTextBl } var blockItems = layout.Select(CreateBlockItem).Where(x => x != null).ToList(); + /////// if (blockItems == null) { @@ -272,8 +298,12 @@ public object SetRichTextBlockModelProperty(object intermediateValue, RichTextBl } } + /// /// Pulled from BlockPropertyValueCreatorBase - // Cache constructors locally (it's tied to the current IPublishedSnapshot and IPublishedModelFactory) + /// + /// Umbraco-CMS\src\Umbraco.Infrastructure\PropertyEditors\ValueConverters\BlockPropertyValueCreatorBase.cs + /// + /// ed to the current IPublishedSnapshot and IPublishedModelFactory) public class BlockItemActivator where T : IBlockReference { diff --git a/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/PreValues/tinymce.rte.prevalues.html b/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/PreValues/tinymce.rte.prevalues.html index 375189d..d02514e 100644 --- a/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/PreValues/tinymce.rte.prevalues.html +++ b/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/PreValues/tinymce.rte.prevalues.html @@ -1,4 +1,4 @@ -
+
diff --git a/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/package.manifest b/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/package.manifest index c421dd8..49f6dd4 100644 --- a/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/package.manifest +++ b/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/package.manifest @@ -7,7 +7,6 @@ "~/App_Plugins/TinyMCE.Umbraco.Premium/plugins.list.js", "~/App_Plugins/TinyMCE.Umbraco.Premium/Dialogs/editconfig.controller.js", "~/App_Plugins/TinyMCE.Umbraco.Premium/PreValues/tinymce.rte.prevalues.controller.js", - //"~/App_Plugins/TinyMCE.Umbraco.Premium/premium.rte.controller.js", "~/App_Plugins/TinyMCE.Umbraco.Premium/premuim.rte.component.js", "~/App_Plugins/TinyMCE.Umbraco.Premium/Defaults/advtemplate.templates.js", "~/App_Plugins/TinyMCE.Umbraco.Premium/Defaults/mergetags.templates.js", diff --git a/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/premium.rte.controller.js b/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/premium.rte.controller.js deleted file mode 100644 index b7f3c0f..0000000 --- a/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/premium.rte.controller.js +++ /dev/null @@ -1,184 +0,0 @@ -angular.module("umbraco") - .controller("TinyMce.Umbraco.Premium.PropertyEditors.RTEController", - function ($scope, $q, assetsService, $timeout, tinyMceService, angularHelper, tinyMceAssets, $element) { - - // Copied and modified from the Umbraco rte.controller.js - - var unsubscribe = []; - $scope.isLoading = true; - - //To id the html textarea we need to use the datetime ticks because we can have multiple rte's per a single property alias - // because now we have to support having 2x (maybe more at some stage) content editors being displayed at once. This is because - // we have this mini content editor panel that can be launched with MNTP. - $scope.textAreaHtmlId = $scope.model.alias + "_" + String.CreateGuid(); - - var editorConfig = $scope.model.config ? $scope.model.config.editor : null; - if (!editorConfig || Utilities.isString(editorConfig)) { - editorConfig = tinyMceService.defaultPrevalues(); - } - - var width = editorConfig.dimensions ? parseInt(editorConfig.dimensions.width, 10) || null : null; - var height = editorConfig.dimensions ? parseInt(editorConfig.dimensions.height, 10) || null : null; - - $scope.containerWidth = "auto"; - $scope.containerHeight = "auto"; - $scope.containerOverflow = "inherit"; - - var promises = []; - - // we need to make sure that the element is initialized before we can init TinyMCE, because we find the placeholder by ID, so it needs to be appended to document before. - var initPromise = $q((resolve, reject) => { - this.$onInit = resolve; - }); - - promises.push(initPromise); - - //queue file loading - tinyMceAssets.forEach(function (tinyJsAsset) { - promises.push(assetsService.loadJs(tinyJsAsset, $scope)); - }); - - //stores a reference to the editor - var tinyMceEditor = null; - - promises.push(tinyMceService.getTinyMceEditorConfig({ - htmlId: $scope.textAreaHtmlId, - stylesheets: editorConfig.stylesheets, - toolbar: editorConfig.toolbar, - mode: editorConfig.mode - })); - - //wait for queue to end - $q.all(promises).then(function (result) { - - var standardConfig = result[promises.length - 1]; - var standardConfigKeys = _.keys(standardConfig); - - // Override with prevalue custom config if present - if (editorConfig.customConfig) { - Utilities.extend(standardConfig, editorConfig.customConfig); - } - - // Override with prevalue plugins if present - if (editorConfig.plugins) { - standardConfig.plugins = _.union(standardConfig.plugins, editorConfig.plugins); - _.each(editorConfig.pluginsToExclude, function (alias) { - standardConfig.plugins = _.without(standardConfig.plugins, alias); - }); - } - - /////////////////// - // Insert custom config for each plugin with default configuration so something shows up after adding it - if (standardConfig.plugins.indexOf("advtemplate")) { - if (_.indexOf(standardConfigKeys, "advtemplate_templates") < 0) { - if (window.tinymcepremium.Config.advtemplate_templates != null) { - Utilities.extend(standardConfig, window.tinymcepremium.Config.advtemplate_templates); - } - } - } - if (standardConfig.plugins.indexOf("mergetags")) { - if (_.indexOf(standardConfigKeys, "mergetags_list") < 0) { - if (window.tinymcepremium.Config.mergetags_list != null) { - Utilities.extend(standardConfig, window.tinymcepremium.Config.mergetags_list); - } - } - } - if (standardConfig.plugins.indexOf("ai")) { - if (_.indexOf(standardConfigKeys, "ai_request") < 0) { - if (window.tinymcepremium.Config.ai_request != null) { - Utilities.extend(standardConfig, window.tinymcepremium.Config.ai_request); - } - } - } - if (standardConfig.plugins.indexOf("powerpaste")) { - // remove the "paste" plugin per TinyMCE docs - standardConfig.plugins = _.without(standardConfig.plugins, "paste"); - } - if (standardConfig.plugins.indexOf("editimage")) { - // add the the "image" plugin per TinyMCE docs - standardConfig.plugins = _.union(standardConfig.plugins,["image"]); - } - if (standardConfig.plugins.indexOf("mediaembed")) { - // add the "media" plugin per TinyMCE docs - standardConfig.plugins = _.union(standardConfig.plugins, ["media"]); - } - /////////////////// - - if (height !== null) { - standardConfig.plugins.splice(standardConfig.plugins.indexOf("autoresize"), 1); - } - - //create a baseline Config to extend upon - var baseLineConfigObj = { - maxImageSize: editorConfig.maxImageSize, - width: width, - height: height - }; - - baseLineConfigObj.setup = function (editor) { - - //set the reference - tinyMceEditor = editor; - - tinyMceEditor.on('init', function (e) { - $timeout(function () { - $scope.isLoading = false; - }); - }); - tinyMceEditor.on("focus", function () { - $element[0].dispatchEvent(new CustomEvent('umb-rte-focus', { composed: true, bubbles: true })); - }); - tinyMceEditor.on("blur", function () { - $element[0].dispatchEvent(new CustomEvent('umb-rte-blur', { composed: true, bubbles: true })); - }); - - //initialize the standard editor functionality for Umbraco - tinyMceService.initializeEditor({ - editor: editor, - toolbar: editorConfig.toolbar, - model: $scope.model, - currentFormInput: $scope.rteForm.modelValue - }); - - }; - - Utilities.extend(baseLineConfigObj, standardConfig); - - // Readonly mode - baseLineConfigObj.toolbar = $scope.readonly ? false : baseLineConfigObj.toolbar; - baseLineConfigObj.readonly = $scope.readonly ? 1 : baseLineConfigObj.readonly; - - // We need to wait for DOM to have rendered before we can find the element by ID. - $timeout(function () { - tinymce.init(baseLineConfigObj); - }, 150); - - //listen for formSubmitting event (the result is callback used to remove the event subscription) - unsubscribe.push($scope.$on("formSubmitting", function () { - if (tinyMceEditor !== undefined && tinyMceEditor != null && !$scope.isLoading) { - $scope.model.value = tinyMceEditor.getContent(); - } - })); - - $scope.focus = function () { - tinyMceEditor.focus(); - } - - //when the element is disposed we need to unsubscribe! - // NOTE: this is very important otherwise if this is part of a modal, the listener still exists because the dom - // element might still be there even after the modal has been hidden. - $scope.$on('$destroy', function () { - for (var i = 0; i < unsubscribe.length; i++) { - unsubscribe[i](); - } - if (tinyMceEditor !== undefined && tinyMceEditor != null) { - if ($element) { - $element[0]?.dispatchEvent(new CustomEvent('blur', { composed: true, bubbles: true })); - } - tinyMceEditor.destroy() - } - }); - - }); - - }); diff --git a/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/premuim.rte.component.js b/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/premuim.rte.component.js index 7fca399..7e1c58e 100644 --- a/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/premuim.rte.component.js +++ b/src/TinyMCE.Umbraco.Premium/wwwroot/App_Plugins/TinyMCE.Umbraco.Premium/premuim.rte.component.js @@ -12,6 +12,7 @@ * TinyMCE.Umbraco.Premium.PropertyEditors.tinyMcePremiumRtePropertyEditor * * Copied and modified from the Umbraco rte.component.js + * Umbraco-CMS\src\Umbraco.Web.UI.Client\src\views\propertyeditors\rte\rte.component.js */ angular .module("umbraco") @@ -210,7 +211,7 @@ }) }) - // Unsure if needed: + // Unsure if needed, commenting out for now as we license in a different way: // Handle additional assets loading depending on the configuration before initializing the editor diff --git a/src/Umbraco.Cms.Demo/Umbraco.Cms.Demo.csproj b/src/Umbraco.Cms.Demo/Umbraco.Cms.Demo.csproj index 46ccdde..8eb69df 100644 --- a/src/Umbraco.Cms.Demo/Umbraco.Cms.Demo.csproj +++ b/src/Umbraco.Cms.Demo/Umbraco.Cms.Demo.csproj @@ -17,7 +17,7 @@ - +