From b97dd4660873d54475474352d3e1e00064fc617a Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 19 Jan 2023 11:02:33 +0100 Subject: [PATCH 1/5] V11: fix issue where editing a macro was not possible (#13702) * remove the onSetup for the macro button since we want to always be able to interact with the macro button (either insert or edit) * let the onAction method find the currently selected macro by asking the active editor for its selection instead of relying on the NodeChanged event --- .../src/common/services/tinymce.service.js | 37 +++++-------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 36c1259cc3..ea284ee2ce 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -726,7 +726,6 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s createInsertMacro: function (editor, callback) { let self = this; - let activeMacroElement = null; //track an active macro element /** Adds custom rules for the macro plugin and custom serialization */ editor.on('preInit', function (args) { @@ -755,11 +754,17 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s }); /** - * Because the macro gets wrapped in a P tag because of the way 'enter' works, this + * Because the macro got wrapped in a P tag because of the way 'enter' works in older versions of Umbraco, this * method will return the macro element if not wrapped in a p, or the p if the macro * element is the only one inside of it even if we are deep inside an element inside the macro */ - function getRealMacroElem(element) { + function getRealMacroElem() { + // Ask the editor for the currently selected element + const element = editor.selection.getNode(); + if (!element) { + return null; + } + var e = $(element).closest(".umb-macro-holder"); if (e.length > 0) { if (e.get(0).parentNode.nodeName === "P") { @@ -777,32 +782,9 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s editor.ui.registry.addButton('umbmacro', { icon: 'preferences', tooltip: 'Insert macro', - onSetup: function (buttonApi) { - /** - * Check if the macro is currently selected and toggle the menu button - */ - function onNodeChanged(evt) { - - //set our macro button active when on a node of class umb-macro-holder - activeMacroElement = getRealMacroElem(evt.element); - - //set the button active/inactive - buttonApi.setEnabled(activeMacroElement === null); - } - - //set onNodeChanged event listener - editor.on('NodeChange', onNodeChanged); - - return function () { - //remove the event listener - editor.off('NodeChange', onNodeChanged); - } - - }, /** The insert macro button click event handler */ onAction: function () { - var dialogData = { //flag for use in rte so we only show macros flagged for the editor richTextEditor: true @@ -810,6 +792,7 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s //when we click we could have a macro already selected and in that case we'll want to edit the current parameters //so we'll need to extract them and submit them to the dialog. + const activeMacroElement = getRealMacroElem(); if (activeMacroElement) { //we have a macro selected so we'll need to parse it's alias and parameters var contents = $(activeMacroElement).contents(); @@ -823,7 +806,7 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s var parsed = macroService.parseMacroSyntax(syntax); dialogData = { macroData: parsed, - activeMacroElement: activeMacroElement //pass the active element along so we can retrieve it later + activeMacroElement //pass the active element along so we can retrieve it later }; } From a8acefcaba59af6425c530711908268744be7922 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 19 Jan 2023 10:38:39 +0100 Subject: [PATCH 2/5] introduce lint option for gulp so we only lint when building and not watching, which makes dev, watch and fastdev even faster --- src/Umbraco.Web.UI.Client/gulp/config.js | 9 ++++++--- .../gulp/util/processJs.js | 19 +++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/gulp/config.js b/src/Umbraco.Web.UI.Client/gulp/config.js index 4d6fea42f7..50ec4b8d84 100755 --- a/src/Umbraco.Web.UI.Client/gulp/config.js +++ b/src/Umbraco.Web.UI.Client/gulp/config.js @@ -5,17 +5,20 @@ module.exports = { build: { sourcemaps: false, embedtemplates: true, - minify: true + minify: true, + lint: true }, dev: { sourcemaps: true, embedtemplates: true, - minify: false + minify: false, + lint: false }, test: { sourcemaps: false, embedtemplates: true, - minify: true + minify: true, + lint: true } }, sources: { diff --git a/src/Umbraco.Web.UI.Client/gulp/util/processJs.js b/src/Umbraco.Web.UI.Client/gulp/util/processJs.js index f892a50292..23b7ae50b7 100644 --- a/src/Umbraco.Web.UI.Client/gulp/util/processJs.js +++ b/src/Umbraco.Web.UI.Client/gulp/util/processJs.js @@ -13,11 +13,11 @@ var rename = require('gulp-rename'); var _ = require('lodash'); module.exports = function (files, out) { - + _.forEach(config.roots, function(root){ console.log("JS: ", files, " -> ", root + config.targets.js + out) }) - + var task = gulp.src(files); // check for js errors @@ -25,10 +25,13 @@ module.exports = function (files, out) { warnIgnored: true, quiet: true })); - // outputs the lint results to the console - task = task.pipe(eslint.format()); - // fail after all errors have been discovered - task = task.pipe(eslint.failAfterError()); + + if (config.compile.current.lint === true) { + // outputs the lint results to the console + task = task.pipe(eslint.format()); + // fail after all errors have been discovered + task = task.pipe(eslint.failAfterError()); + } // sort files in stream by path or any custom sort comparator task = task.pipe(babel()) @@ -38,7 +41,7 @@ module.exports = function (files, out) { if(config.compile.current.embedtemplates === true) { task = task.pipe(embedTemplates({ basePath: "./src/", minimize: { loose: true } })); } - + task = task.pipe(concat(out)).pipe(wrap('(function(){\n%= body %\n})();')) // NOTE: if you change something here, you probably also need to change it in the js task @@ -64,7 +67,7 @@ module.exports = function (files, out) { _.forEach(config.roots, function(root){ task = task.pipe(gulp.dest(root + config.targets.js)); }) - + return task; From 7aee15d6d1359ce4eb1b3a5c01d25b62151150e0 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Fri, 20 Jan 2023 08:13:37 +0100 Subject: [PATCH 3/5] V11: Prevalues as toggles have problems in datatype settings view (#13709) * format preValues with DataTypeHelper.createPreValuesProps before rendering so they have the 'alias' prop used for input-id to umb-toggle * preValues are now formatted on fetch so we do not need to do it again --- .../datatypesettings/datatypesettings.controller.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js index e2a6e30405..171f7d9c86 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js @@ -76,7 +76,7 @@ // get pre values dataTypeResource.getPreValues(newDataType.selectedEditor).then(function(preValues) { - newDataType.preValues = preValues; + newDataType.preValues = dataTypeHelper.createPreValueProps(preValues); vm.dataType = newDataType; vm.loadingDataType = false; }); @@ -89,6 +89,7 @@ vm.loadingDataType = true; dataTypeResource.getById($scope.model.id).then(function (dataType) { vm.dataType = dataType; + vm.dataType.preValues = dataTypeHelper.createPreValueProps(dataType.preValues); vm.loadingDataType = false; }); } @@ -106,9 +107,7 @@ vm.saveButtonState = "busy"; - var preValues = dataTypeHelper.createPreValueProps(vm.dataType.preValues); - - dataTypeResource.save(vm.dataType, preValues, $scope.model.create).then( + dataTypeResource.save(vm.dataType, vm.dataType.preValues, $scope.model.create).then( function(newDataType) { $scope.model.dataType = newDataType; From 435b6f0650b46d9b3f0cd712e5835b753d4754c5 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Fri, 20 Jan 2023 08:13:37 +0100 Subject: [PATCH 4/5] V11: Prevalues as toggles have problems in datatype settings view (#13709) * format preValues with DataTypeHelper.createPreValuesProps before rendering so they have the 'alias' prop used for input-id to umb-toggle * preValues are now formatted on fetch so we do not need to do it again (cherry picked from commit 7aee15d6d1359ce4eb1b3a5c01d25b62151150e0) --- .../datatypesettings/datatypesettings.controller.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js index e2a6e30405..171f7d9c86 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js @@ -76,7 +76,7 @@ // get pre values dataTypeResource.getPreValues(newDataType.selectedEditor).then(function(preValues) { - newDataType.preValues = preValues; + newDataType.preValues = dataTypeHelper.createPreValueProps(preValues); vm.dataType = newDataType; vm.loadingDataType = false; }); @@ -89,6 +89,7 @@ vm.loadingDataType = true; dataTypeResource.getById($scope.model.id).then(function (dataType) { vm.dataType = dataType; + vm.dataType.preValues = dataTypeHelper.createPreValueProps(dataType.preValues); vm.loadingDataType = false; }); } @@ -106,9 +107,7 @@ vm.saveButtonState = "busy"; - var preValues = dataTypeHelper.createPreValueProps(vm.dataType.preValues); - - dataTypeResource.save(vm.dataType, preValues, $scope.model.create).then( + dataTypeResource.save(vm.dataType, vm.dataType.preValues, $scope.model.create).then( function(newDataType) { $scope.model.dataType = newDataType; From 17248ce494d9a4ad5fd1288e86713989e3460275 Mon Sep 17 00:00:00 2001 From: Mole Date: Mon, 23 Jan 2023 08:19:15 +0100 Subject: [PATCH 5/5] V11: Add improved log message on compilation failure using InMemoryAuto (#13678) * Add improved log message when in memory compilation fails. * Move LogCompilationFailure into its own method And hopefully make codescene happeh * Reduce nesting * Replace null check with linq --- .../CollectibleRuntimeViewCompiler.cs | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.Common/ModelsBuilder/InMemoryAuto/CollectibleRuntimeViewCompiler.cs b/src/Umbraco.Web.Common/ModelsBuilder/InMemoryAuto/CollectibleRuntimeViewCompiler.cs index d266b51dd1..3c934231f3 100644 --- a/src/Umbraco.Web.Common/ModelsBuilder/InMemoryAuto/CollectibleRuntimeViewCompiler.cs +++ b/src/Umbraco.Web.Common/ModelsBuilder/InMemoryAuto/CollectibleRuntimeViewCompiler.cs @@ -2,6 +2,7 @@ using System.Diagnostics; using System.Reflection; using System.Text; +using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc.Razor.Compilation; using Microsoft.AspNetCore.Razor.Hosting; using Microsoft.AspNetCore.Razor.Language; @@ -13,6 +14,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; +using Umbraco.Extensions; namespace Umbraco.Cms.Web.Common.ModelsBuilder.InMemoryAuto; @@ -375,13 +377,17 @@ internal class CollectibleRuntimeViewCompiler : IViewCompiler pdbStream, options: _compilationOptionsProvider.EmitOptions); - if (!result.Success) + if (result.Success is false) { - throw CompilationExceptionFactory.Create( + UmbracoCompilationException compilationException = CompilationExceptionFactory.Create( codeDocument, generatedCode, assemblyName, result.Diagnostics); + + LogCompilationFailure(compilationException); + + throw compilationException; } assemblyStream.Seek(0, SeekOrigin.Begin); @@ -393,6 +399,21 @@ internal class CollectibleRuntimeViewCompiler : IViewCompiler } } + private void LogCompilationFailure(UmbracoCompilationException compilationException) + { + IEnumerable? messages = compilationException.CompilationFailures? + .WhereNotNull() + .SelectMany(x => x.Messages!) + .WhereNotNull() + .Select(x => x.FormattedMessage) + .WhereNotNull(); + + foreach (var message in messages ?? Enumerable.Empty()) + { + _logger.LogError(compilationException, "Compilation error occured with message: {ErrorMessage}", message); + } + } + private CSharpCompilation CreateCompilation(string compilationContent, string assemblyName) { IReadOnlyList refs = _referenceManager.CompilationReferences;