diff --git a/src/Umbraco.Cms.StaticAssets/wwwroot/App_Plugins/Umbraco.BlockGridEditor.DefaultCustomViews/umbBlockGridDemoImageBlock.html b/src/Umbraco.Cms.StaticAssets/wwwroot/App_Plugins/Umbraco.BlockGridEditor.DefaultCustomViews/umbBlockGridDemoImageBlock.html
index 521d7c9b09..c9da7ab143 100644
--- a/src/Umbraco.Cms.StaticAssets/wwwroot/App_Plugins/Umbraco.BlockGridEditor.DefaultCustomViews/umbBlockGridDemoImageBlock.html
+++ b/src/Umbraco.Cms.StaticAssets/wwwroot/App_Plugins/Umbraco.BlockGridEditor.DefaultCustomViews/umbBlockGridDemoImageBlock.html
@@ -19,7 +19,6 @@
justify-content: center;
width: 100%;
height: 100%;
- min-height: 100%;
cursor: pointer;
color: black;
background-color: transparent;
@@ -35,7 +34,6 @@
color: #2152A3;// TODO: Set right colors:
}
img {
- pointer-events: none;
object-fit: cover;
height: 100%;
width: 100%;
diff --git a/src/Umbraco.Core/Models/Blocks/BlockGridItem.cs b/src/Umbraco.Core/Models/Blocks/BlockGridItem.cs
index 59021f5e38..097882c5ab 100644
--- a/src/Umbraco.Core/Models/Blocks/BlockGridItem.cs
+++ b/src/Umbraco.Core/Models/Blocks/BlockGridItem.cs
@@ -9,7 +9,7 @@ namespace Umbraco.Cms.Core.Models.Blocks
///
/// Represents a layout item for the Block Grid editor.
///
- ///
+ ///
[DataContract(Name = "block", Namespace = "")]
public class BlockGridItem : IBlockReference
{
@@ -116,7 +116,6 @@ namespace Umbraco.Cms.Core.Models.Blocks
/// Represents a layout item with a generic content type for the Block List editor.
///
/// The type of the content.
- ///
public class BlockGridItem : BlockGridItem
where T : IPublishedElement
{
@@ -149,7 +148,6 @@ namespace Umbraco.Cms.Core.Models.Blocks
///
/// The type of the content.
/// The type of the settings.
- ///
public class BlockGridItem : BlockGridItem
where TContent : IPublishedElement
where TSettings : IPublishedElement
diff --git a/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs b/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs
index 26a2e9fb60..ea75f369af 100644
--- a/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs
+++ b/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs
@@ -1,4 +1,5 @@
using System.Globalization;
+using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using Microsoft.Extensions.FileProviders;
@@ -166,7 +167,7 @@ public class LocalizedTextServiceFileSources
}
///
- /// returns all xml sources for all culture files found in the folder
+ /// Returns all xml sources for all culture files found in the folder.
///
///
public IDictionary> GetXmlSources() => _xmlSources.Value;
@@ -179,7 +180,15 @@ public class LocalizedTextServiceFileSources
{
result.AddRange(
new PhysicalDirectoryContents(_fileSourceFolder.FullName)
- .Where(x => !x.IsDirectory && x.Name.EndsWith(".xml")));
+ .Where(x => !x.IsDirectory && !x.Name.Contains("user") && x.Name.EndsWith(".xml"))); // Filter out *.user.xml
+ }
+
+ if (_supplementFileSources is not null)
+ {
+ // Get only the .xml files and filter out the user defined language files (*.user.xml) that overwrite the default
+ result.AddRange(_supplementFileSources
+ .Where(x => !x.FileInfo.Name.Contains("user") && x.FileInfo.Name.EndsWith(".xml"))
+ .Select(x => x.FileInfo));
}
if (_directoryContents.Exists)
@@ -236,8 +245,8 @@ public class LocalizedTextServiceFileSources
// now load in supplementary
IEnumerable found = _supplementFileSources.Where(x =>
{
- var extension = Path.GetExtension(x.File.FullName);
- var fileCultureName = Path.GetFileNameWithoutExtension(x.File.FullName).Replace("_", "-")
+ var extension = Path.GetExtension(x.FileInfo.Name);
+ var fileCultureName = Path.GetFileNameWithoutExtension(x.FileInfo.Name).Replace("_", "-")
.Replace(".user", string.Empty);
return extension.InvariantEquals(".xml") && (
fileCultureName.InvariantEquals(culture.Name)
@@ -246,16 +255,16 @@ public class LocalizedTextServiceFileSources
foreach (LocalizedTextServiceSupplementaryFileSource supplementaryFile in found)
{
- using (FileStream fs = supplementaryFile.File.OpenRead())
+ using (Stream stream = supplementaryFile.FileInfo.CreateReadStream())
{
XDocument xChildDoc;
try
{
- xChildDoc = XDocument.Load(fs);
+ xChildDoc = XDocument.Load(stream);
}
catch (Exception ex)
{
- _logger.LogError(ex, "Could not load file into XML {File}", supplementaryFile.File.FullName);
+ _logger.LogError(ex, "Could not load file into XML {File}", supplementaryFile.FileInfo.Name);
continue;
}
diff --git a/src/Umbraco.Core/Services/LocalizedTextServiceSupplementaryFileSource.cs b/src/Umbraco.Core/Services/LocalizedTextServiceSupplementaryFileSource.cs
index cff9a55234..4f89eac5ff 100644
--- a/src/Umbraco.Core/Services/LocalizedTextServiceSupplementaryFileSource.cs
+++ b/src/Umbraco.Core/Services/LocalizedTextServiceSupplementaryFileSource.cs
@@ -1,14 +1,27 @@
+using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.FileProviders.Physical;
+
namespace Umbraco.Cms.Core.Services;
public class LocalizedTextServiceSupplementaryFileSource
{
+ [Obsolete("Use other ctor. Will be removed in Umbraco 12")]
public LocalizedTextServiceSupplementaryFileSource(FileInfo file, bool overwriteCoreKeys)
+ : this(new PhysicalFileInfo(file), overwriteCoreKeys)
{
- File = file ?? throw new ArgumentNullException("file");
+ }
+
+ public LocalizedTextServiceSupplementaryFileSource(IFileInfo file, bool overwriteCoreKeys)
+ {
+ FileInfo = file ?? throw new ArgumentNullException(nameof(file));
+ File = file is PhysicalFileInfo && file.PhysicalPath is not null ? new FileInfo(file.PhysicalPath) : null!;
OverwriteCoreKeys = overwriteCoreKeys;
}
+ [Obsolete("Use FileInfo instead. Will be removed in Umbraco 12")]
public FileInfo File { get; }
+ public IFileInfo FileInfo { get; }
+
public bool OverwriteCoreKeys { get; }
}
diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs
index dd5b77abec..c9208b5bdc 100644
--- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs
+++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs
@@ -102,7 +102,14 @@ public static partial class UmbracoBuilderExtensions
IServiceProvider container)
{
IHostingEnvironment hostingEnvironment = container.GetRequiredService();
+
+ // TODO: (for >= v13) Rethink whether all language files (.xml and .user.xml) should be located in ~/config/lang
+ // instead of ~/umbraco/config/lang and ~/config/lang.
+ // Currently when extending Umbraco, a new language file that the backoffice will be available in, should be placed
+ // in ~/umbraco/config/lang, while 'user' translation files for overrides are in ~/config/lang (according to our docs).
+ // Such change will be breaking and we would need to document this clearly.
var subPath = WebPath.Combine(Constants.SystemDirectories.Umbraco, "config", "lang");
+
var mainLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(subPath));
return new LocalizedTextServiceFileSources(
diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs
index 9d677bce66..60a946a553 100644
--- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs
+++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.LocalizedText.cs
@@ -1,6 +1,8 @@
+using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
+using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
@@ -42,20 +44,30 @@ namespace Umbraco.Extensions
// gets all langs files in /app_plugins real or virtual locations
IEnumerable pluginLangFileSources = GetPluginLanguageFileSources(webFileProvider, Cms.Core.Constants.SystemDirectories.AppPlugins, false);
- // user defined langs that overwrite the default, these should not be used by plugin creators
+ // user defined language files that overwrite the default, these should not be used by plugin creators
var userConfigLangFolder = Cms.Core.Constants.SystemDirectories.Config
.TrimStart(Cms.Core.Constants.CharArrays.Tilde);
- IEnumerable userLangFileSources = contentFileProvider.GetDirectoryContents(userConfigLangFolder)
- .Where(x => x.IsDirectory && x.Name.InvariantEquals("lang"))
- .Select(x => new DirectoryInfo(x.PhysicalPath!))
- .SelectMany(x => x.GetFiles("*.user.xml", SearchOption.TopDirectoryOnly))
- .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true));
+ var configLangFileSources = new List();
+
+ foreach (IFileInfo langFileSource in contentFileProvider.GetDirectoryContents(userConfigLangFolder))
+ {
+ if (langFileSource.IsDirectory && langFileSource.Name.InvariantEquals("lang"))
+ {
+ foreach (IFileInfo langFile in contentFileProvider.GetDirectoryContents($"{userConfigLangFolder}/{langFileSource.Name}"))
+ {
+ if (langFile.Name.InvariantEndsWith(".xml") && langFile.PhysicalPath is not null)
+ {
+ configLangFileSources.Add(new LocalizedTextServiceSupplementaryFileSource(langFile, true));
+ }
+ }
+ }
+ }
return
localPluginFileSources
.Concat(pluginLangFileSources)
- .Concat(userLangFileSources);
+ .Concat(configLangFileSources);
}
@@ -83,13 +95,12 @@ namespace Umbraco.Extensions
foreach (var langFolder in GetLangFolderPaths(fileProvider, pluginFolderPath))
{
// request all the files out of the path, these will have physicalPath set.
- IEnumerable localizationFiles = fileProvider
+ IEnumerable localizationFiles = fileProvider
.GetDirectoryContents(langFolder)
.Where(x => !string.IsNullOrEmpty(x.PhysicalPath))
- .Where(x => x.Name.InvariantEndsWith(".xml"))
- .Select(x => new FileInfo(x.PhysicalPath!));
+ .Where(x => x.Name.InvariantEndsWith(".xml"));
- foreach (FileInfo file in localizationFiles)
+ foreach (IFileInfo file in localizationFiles)
{
yield return new LocalizedTextServiceSupplementaryFileSource(file, overwriteCoreKeys);
}
diff --git a/src/Umbraco.Web.Common/Extensions/BlockGridTemplateExtensions.cs b/src/Umbraco.Web.Common/Extensions/BlockGridTemplateExtensions.cs
index 4cae63426b..ee0375da4f 100644
--- a/src/Umbraco.Web.Common/Extensions/BlockGridTemplateExtensions.cs
+++ b/src/Umbraco.Web.Common/Extensions/BlockGridTemplateExtensions.cs
@@ -15,6 +15,21 @@ public static class BlockGridTemplateExtensions
public const string DefaultItemsTemplate = "items";
public const string DefaultItemAreasTemplate = "areas";
+ #region Async
+
+ ///
+ /// Renders a block grid model into a grid layout
+ ///
+ ///
+ /// By default this method uses a set of built-in partial views for rendering the blocks and areas in the grid model.
+ /// These partial views are embedded in the static assets (Umbraco.Cms.StaticAssets), so they won't show up in the
+ /// Views folder on your local disk.
+ ///
+ /// If you need to tweak the grid rendering output, you can copy the partial views from GitHub to your local disk.
+ /// The partial views are found in "/src/Umbraco.Cms.StaticAssets/Views/Partials/blockgrid/" on GitHub and should
+ /// be copied to "Views/Partials/BlockGrid/" on your local disk.
+ ///
+ ///
public static async Task GetBlockGridHtmlAsync(this IHtmlHelper html, BlockGridModel? model, string template = DefaultTemplate)
{
if (model?.Count == 0)
@@ -22,17 +37,69 @@ public static class BlockGridTemplateExtensions
return new HtmlString(string.Empty);
}
- var view = $"{DefaultFolder}{template}";
- return await html.PartialAsync(view, model);
+ return await html.PartialAsync(DefaultFolderTemplate(template), model);
}
+ ///
public static async Task GetBlockGridHtmlAsync(this IHtmlHelper html, IPublishedProperty property, string template = DefaultTemplate)
=> await GetBlockGridHtmlAsync(html, property.GetValue() as BlockGridModel, template);
+ ///
public static async Task GetBlockGridHtmlAsync(this IHtmlHelper html, IPublishedContent contentItem, string propertyAlias)
=> await GetBlockGridHtmlAsync(html, contentItem, propertyAlias, DefaultTemplate);
public static async Task GetBlockGridHtmlAsync(this IHtmlHelper html, IPublishedContent contentItem, string propertyAlias, string template)
+ {
+ IPublishedProperty prop = GetRequiredProperty(contentItem, propertyAlias);
+ return await GetBlockGridHtmlAsync(html, prop.GetValue() as BlockGridModel, template);
+ }
+
+ public static async Task GetBlockGridItemsHtmlAsync(this IHtmlHelper html, IEnumerable items, string template = DefaultItemsTemplate)
+ => await html.PartialAsync(DefaultFolderTemplate(template), items);
+
+ public static async Task GetBlockGridItemAreasHtmlAsync(this IHtmlHelper html, BlockGridItem item, string template = DefaultItemAreasTemplate)
+ => await html.PartialAsync(DefaultFolderTemplate(template), item);
+
+ #endregion
+
+ #region Sync
+
+ ///
+ public static IHtmlContent GetBlockGridHtml(this IHtmlHelper html, BlockGridModel? model, string template = DefaultTemplate)
+ {
+ if (model?.Count == 0)
+ {
+ return new HtmlString(string.Empty);
+ }
+
+ return html.Partial(DefaultFolderTemplate(template), model);
+ }
+
+ ///
+ public static IHtmlContent GetBlockGridHtml(this IHtmlHelper html, IPublishedProperty property, string template = DefaultTemplate)
+ => GetBlockGridHtml(html, property.GetValue() as BlockGridModel, template);
+
+ ///
+ public static IHtmlContent GetBlockGridHtml(this IHtmlHelper html, IPublishedContent contentItem, string propertyAlias)
+ => GetBlockGridHtml(html, contentItem, propertyAlias, DefaultTemplate);
+
+ public static IHtmlContent GetBlockGridHtml(this IHtmlHelper html, IPublishedContent contentItem, string propertyAlias, string template)
+ {
+ IPublishedProperty prop = GetRequiredProperty(contentItem, propertyAlias);
+ return GetBlockGridHtml(html, prop.GetValue() as BlockGridModel, template);
+ }
+
+ public static IHtmlContent GetBlockGridItemsHtml(this IHtmlHelper html, IEnumerable items, string template = DefaultItemsTemplate)
+ => html.Partial(DefaultFolderTemplate(template), items);
+
+ public static IHtmlContent GetBlockGridItemAreasHtml(this IHtmlHelper html, BlockGridItem item, string template = DefaultItemAreasTemplate)
+ => html.Partial(DefaultFolderTemplate(template), item);
+
+ #endregion
+
+ private static string DefaultFolderTemplate(string template) => $"{DefaultFolder}{template}";
+
+ private static IPublishedProperty GetRequiredProperty(IPublishedContent contentItem, string propertyAlias)
{
ArgumentNullException.ThrowIfNull(propertyAlias);
@@ -43,18 +110,12 @@ public static class BlockGridTemplateExtensions
nameof(propertyAlias));
}
- IPublishedProperty? prop = contentItem.GetProperty(propertyAlias);
- if (prop == null)
+ IPublishedProperty? property = contentItem.GetProperty(propertyAlias);
+ if (property == null)
{
throw new InvalidOperationException("No property type found with alias " + propertyAlias);
}
- return await GetBlockGridHtmlAsync(html, prop.GetValue() as BlockGridModel, template);
+ return property;
}
-
- public static async Task GetBlockGridItemsHtmlAsync(this IHtmlHelper html, IEnumerable items, string template = DefaultItemsTemplate)
- => await html.PartialAsync($"{DefaultFolder}{template}", items);
-
- public static async Task GetBlockGridItemAreasHtmlAsync(this IHtmlHelper html, BlockGridItem item, string template = DefaultItemAreasTemplate)
- => await html.PartialAsync($"{DefaultFolder}{template}", item);
}
diff --git a/src/Umbraco.Web.Common/Extensions/BlockListTemplateExtensions.cs b/src/Umbraco.Web.Common/Extensions/BlockListTemplateExtensions.cs
index 17b620ab51..edf3055159 100644
--- a/src/Umbraco.Web.Common/Extensions/BlockListTemplateExtensions.cs
+++ b/src/Umbraco.Web.Common/Extensions/BlockListTemplateExtensions.cs
@@ -10,6 +10,33 @@ public static class BlockListTemplateExtensions
public const string DefaultFolder = "blocklist/";
public const string DefaultTemplate = "default";
+ #region Async
+
+ public static async Task GetBlockListHtmlAsync(this IHtmlHelper html, BlockListModel? model, string template = DefaultTemplate)
+ {
+ if (model?.Count == 0)
+ {
+ return new HtmlString(string.Empty);
+ }
+
+ return await html.PartialAsync(DefaultFolderTemplate(template), model);
+ }
+
+ public static async Task GetBlockListHtmlAsync(this IHtmlHelper html, IPublishedProperty property, string template = DefaultTemplate)
+ => await GetBlockListHtmlAsync(html, property.GetValue() as BlockListModel, template);
+
+ public static async Task GetBlockListHtmlAsync(this IHtmlHelper html, IPublishedContent contentItem, string propertyAlias)
+ => await GetBlockListHtmlAsync(html, contentItem, propertyAlias, DefaultTemplate);
+
+ public static async Task GetBlockListHtmlAsync(this IHtmlHelper html, IPublishedContent contentItem, string propertyAlias, string template)
+ {
+ IPublishedProperty property = GetRequiredProperty(contentItem, propertyAlias);
+ return await GetBlockListHtmlAsync(html, property.GetValue() as BlockListModel, template);
+ }
+ #endregion
+
+ #region Sync
+
public static IHtmlContent GetBlockListHtml(this IHtmlHelper html, BlockListModel? model, string template = DefaultTemplate)
{
if (model?.Count == 0)
@@ -17,8 +44,7 @@ public static class BlockListTemplateExtensions
return new HtmlString(string.Empty);
}
- var view = DefaultFolder + template;
- return html.Partial(view, model);
+ return html.Partial(DefaultFolderTemplate(template), model);
}
public static IHtmlContent GetBlockListHtml(this IHtmlHelper html, IPublishedProperty property, string template = DefaultTemplate)
@@ -29,10 +55,17 @@ public static class BlockListTemplateExtensions
public static IHtmlContent GetBlockListHtml(this IHtmlHelper html, IPublishedContent contentItem, string propertyAlias, string template)
{
- if (propertyAlias == null)
- {
- throw new ArgumentNullException(nameof(propertyAlias));
- }
+ IPublishedProperty property = GetRequiredProperty(contentItem, propertyAlias);
+ return GetBlockListHtml(html, property.GetValue() as BlockListModel, template);
+ }
+
+ #endregion
+
+ private static string DefaultFolderTemplate(string template) => $"{DefaultFolder}{template}";
+
+ private static IPublishedProperty GetRequiredProperty(IPublishedContent contentItem, string propertyAlias)
+ {
+ ArgumentNullException.ThrowIfNull(propertyAlias);
if (string.IsNullOrWhiteSpace(propertyAlias))
{
@@ -41,12 +74,12 @@ public static class BlockListTemplateExtensions
nameof(propertyAlias));
}
- IPublishedProperty? prop = contentItem.GetProperty(propertyAlias);
- if (prop == null)
+ IPublishedProperty? property = contentItem.GetProperty(propertyAlias);
+ if (property == null)
{
throw new InvalidOperationException("No property type found with alias " + propertyAlias);
}
- return GetBlockListHtml(html, prop.GetValue() as BlockListModel, template);
+ return property;
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
index ae9f0121ca..872aad3f53 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
@@ -232,6 +232,7 @@
appendRuntimeData();
init();
+ startWatches($scope.content);
syncTreeNode($scope.content, $scope.content.path, true);
@@ -565,7 +566,6 @@
$scope.page.loading = true;
loadContent().then(function () {
- startWatches($scope.content);
$scope.page.loading = false;
});
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js
index 71bf151b89..7ed5e4120f 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js
@@ -64,6 +64,8 @@
setActiveVariant();
} else if (changes.segment && !changes.segment.isFirstChange() && changes.segment.currentValue !== changes.segment.previousValue) {
setActiveVariant();
+ } else if (changes.content) {
+ setActiveVariant();
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.less b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.less
index 45cba81a0b..fee768235a 100644
--- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.less
+++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.less
@@ -130,13 +130,18 @@ umb-block-card {
right: 10px;
opacity: 0;
transition: opacity 120ms;
+ margin-right: 10px;
+
.__action {
- display: inline-block;
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
border-radius: 50%;
width: 28px;
height: 28px;
background-color: white;
color:@ui-action-type;
+
&:hover {
color: @ui-action-type-hover;
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-property-info-button/umb-property-info-button.less b/src/Umbraco.Web.UI.Client/src/views/components/umb-property-info-button/umb-property-info-button.less
index 33e1156648..a892f1ca38 100644
--- a/src/Umbraco.Web.UI.Client/src/views/components/umb-property-info-button/umb-property-info-button.less
+++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-property-info-button/umb-property-info-button.less
@@ -3,16 +3,20 @@ umb-property-info-button {
display: inline-block;
vertical-align: text-bottom;
+ .control-label + & {
+ margin-left: 3px;
+ }
+
> .__button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
+ text-align: center;
width: 15px;
height: 15px;
- padding-top: 1px;
- padding-left: 1px;
+ padding: 2px 1px 1px 1px;
margin-top: -1px;
font-size: 12px;
font-weight: 700;
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridui.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridui.less
index f23632389c..6cfdb05482 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridui.less
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridui.less
@@ -234,26 +234,29 @@ ng-form.ng-invalid-val-server-match-content > .umb-block-grid__block:not(.--acti
&:not(.--hovering-area):focus,
&:not(.--hovering-area):focus-within,
&.--active {
+
+ /** Avoid displaying hover when dragging-mode */
+ --umb-block-grid--block_ui-opacity: calc(1 - var(--umb-block-grid--dragging-mode, 0));
> .umb-block-grid__block--context {
- opacity: 1;
+ opacity: var(--umb-block-grid--block_ui-opacity);
}
&:not(.--scale-mode) {
> .umb-block-grid__block--actions {
- opacity: 1;
+ opacity: var(--umb-block-grid--block_ui-opacity);
}
> umb-block-grid-block > umb-block-grid-entries > .umb-block-grid__layout-container > .umb-block-grid__area-actions {
- opacity: 1;
+ opacity: var(--umb-block-grid--block_ui-opacity);
}
}
> .umb-block-grid__scale-handler {
- opacity: 1;
+ opacity: var(--umb-block-grid--block_ui-opacity);
}
> .umb-block-grid__force-left,
> .umb-block-grid__force-right {
- opacity: 1;
+ opacity: var(--umb-block-grid--block_ui-opacity);
}
}
@@ -279,7 +282,8 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl
.umb-block-grid__block--view {
height: 100%;
width: 100%;
- display: block;
+ display: flex;
+ flex-direction: column;
}
.umb-block-grid__block--context {
@@ -583,6 +587,9 @@ umb-block-grid-block {
top: 0px;
position: absolute;
z-index: 1;
+
+ /** Avoid showing inline-create in dragging-mode */
+ opacity: calc(1 - var(--umb-block-grid--dragging-mode, 0));
}
.umb-block-grid__block--inline-create-button.--above {
left: 0;
@@ -633,8 +640,6 @@ umb-block-grid-block {
border-radius: @baseBorderRadius;
box-sizing: border-box;
- clear: both;// needed for layouts using float.
-
&:hover {
border-color: transparent;
> button {
@@ -651,7 +656,6 @@ umb-block-grid-block {
> button {
position: relative;
display: flex;
- //width: 100%;
align-items: center;
justify-content: center;
@@ -687,7 +691,7 @@ umb-block-grid-block {
&.umb-block-grid__clipboard-button {
margin-left: 0;
padding: 5px 12px;
- font-size: 18px;// Align with block action buttons.
+ font-size: 18px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
@@ -739,7 +743,6 @@ umb-block-grid-block {
> button {
position: relative;
display: flex;
- //width: 100%;
align-items: center;
justify-content: center;
@@ -779,7 +782,8 @@ umb-block-grid-block {
background: transparent;
border-radius: 3px;
- border: @blueDark solid 1px;
+ border: solid 1px;
+ border-color: rgba(@blueDark, .5);
border-radius: 3px;
height: 100%;
@@ -865,9 +869,25 @@ umb-block-grid-block {
transition: opacity 240ms;
}
.umb-block-grid__area.--highlight::after {
+ /** Avoid displaying highlight when in dragging-mode */
+ opacity: calc(1 - var(--umb-block-grid--dragging-mode, 0));
+ border-color: @blueDark;
+ box-shadow: 0 0 0 1px rgba(255, 255, 255, .7), inset 0 0 0 1px rgba(255, 255, 255, .7);
+}
+.umb-block-grid__area:has( .umb-block-grid__layout-item-placeholder )::after {
opacity: 1;
border-color: @blueDark;
box-shadow: 0 0 0 1px rgba(255, 255, 255, .7), inset 0 0 0 1px rgba(255, 255, 255, .7);
+
+ /* Moved back to edge for this case */
+ top: 0;
+ bottom: 0;
+
+ animation: umb-block-grid__area-after__border-pulse 400ms ease-in-out alternate infinite;
+ @keyframes umb-block-grid__area-after__border-pulse {
+ 0% { border-color: rgba(@blueDark, 1); }
+ 100% { border-color: rgba(@blueDark, 0.66); }
+ }
}
.umb-block-grid__scalebox-backdrop {
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.overlay.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.overlay.html
index 29b3f4b53f..4b05e4ad43 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.overlay.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.overlay.html
@@ -260,12 +260,12 @@
-
+
Define how many layout columns that will be available for areas. If not defined, the number of layout columns defined for the entire layout will be used.