diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs
index 6a17356a68..acabe0fcc4 100644
--- a/src/Umbraco.Core/Cache/CacheKeys.cs
+++ b/src/Umbraco.Core/Cache/CacheKeys.cs
@@ -19,5 +19,8 @@
public const string UserAllMediaStartNodesPrefix = "AllMediaStartNodes";
public const string UserMediaStartNodePathsPrefix = "MediaStartNodePaths";
public const string UserContentStartNodePathsPrefix = "ContentStartNodePaths";
+
+ public const string ContentRecycleBinCacheKey = "recycleBin_content";
+ public const string MediaRecycleBinCacheKey = "recycleBin_media";
}
}
diff --git a/src/Umbraco.Core/Cache/ContentCacheRefresher.cs b/src/Umbraco.Core/Cache/ContentCacheRefresher.cs
index 2165123b88..7b9b2994a9 100644
--- a/src/Umbraco.Core/Cache/ContentCacheRefresher.cs
+++ b/src/Umbraco.Core/Cache/ContentCacheRefresher.cs
@@ -48,6 +48,7 @@ namespace Umbraco.Cms.Core.Cache
public override void Refresh(JsonPayload[] payloads)
{
AppCaches.RuntimeCache.ClearOfType();
+ AppCaches.RuntimeCache.ClearByKey(CacheKeys.ContentRecycleBinCacheKey);
var idsRemoved = new HashSet();
var isolatedCache = AppCaches.IsolatedCaches.GetOrCreate();
diff --git a/src/Umbraco.Core/Cache/MediaCacheRefresher.cs b/src/Umbraco.Core/Cache/MediaCacheRefresher.cs
index dae367204c..5d301fc353 100644
--- a/src/Umbraco.Core/Cache/MediaCacheRefresher.cs
+++ b/src/Umbraco.Core/Cache/MediaCacheRefresher.cs
@@ -43,6 +43,7 @@ namespace Umbraco.Cms.Core.Cache
if (anythingChanged)
{
AppCaches.ClearPartialViewCache();
+ AppCaches.RuntimeCache.ClearByKey(CacheKeys.MediaRecycleBinCacheKey);
var mediaCache = AppCaches.IsolatedCaches.Get();
diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs
index a65b3ae0f5..c53e6ee4d2 100644
--- a/src/Umbraco.Core/Composing/TypeLoader.cs
+++ b/src/Umbraco.Core/Composing/TypeLoader.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
+using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
@@ -77,6 +78,8 @@ namespace Umbraco.Cms.Core.Composing
_fileBasePath = new Lazy(GetFileBasePath);
+ _fileBasePath = new Lazy(GetFileBasePath);
+
if (detectChanges)
{
//first check if the cached hash is string.Empty, if it is then we need
diff --git a/src/Umbraco.Core/Configuration/IPasswordConfiguration.cs b/src/Umbraco.Core/Configuration/IPasswordConfiguration.cs
index 4d042d9270..acfe81ece9 100644
--- a/src/Umbraco.Core/Configuration/IPasswordConfiguration.cs
+++ b/src/Umbraco.Core/Configuration/IPasswordConfiguration.cs
@@ -3,6 +3,7 @@
namespace Umbraco.Cms.Core.Configuration
{
+
///
/// Password configuration
///
diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs
index 815f85b3a6..4254e1791e 100644
--- a/src/Umbraco.Core/Constants-PropertyEditors.cs
+++ b/src/Umbraco.Core/Constants-PropertyEditors.cs
@@ -51,6 +51,11 @@ namespace Umbraco.Cms.Core
///
public const string ColorPicker = "Umbraco.ColorPicker";
+ ///
+ /// EyeDropper Color Picker.
+ ///
+ public const string ColorPickerEyeDropper = "Umbraco.ColorPicker.EyeDropper";
+
///
/// Content Picker.
///
diff --git a/src/Umbraco.Core/Constants-SvgSanitizer.cs b/src/Umbraco.Core/Constants-SvgSanitizer.cs
deleted file mode 100644
index 048bf404d4..0000000000
--- a/src/Umbraco.Core/Constants-SvgSanitizer.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System.Collections.Generic;
-
-namespace Umbraco.Cms.Core
-{
- public static partial class Constants
- {
- ///
- /// Defines the alias identifiers for Umbraco's core application sections.
- ///
- public static class SvgSanitizer
- {
- ///
- /// Allowlist for SVG attributes.
- ///
- public static readonly IList Attributes = new [] { "accent-height", "accumulate", "additive", "alignment-baseline", "allowReorder", "alphabetic", "amplitude", "arabic-form", "ascent", "attributeName", "attributeType", "autoReverse", "azimuth", "baseFrequency", "baseline-shift", "baseProfile", "bbox", "begin", "bias", "by", "calcMode", "cap-height", "class", "clip", "clipPathUnits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "contentScriptType", "contentStyleType", "cursor", "cx", "cy", "d", "decelerate", "descent", "diffuseConstant", "direction", "display", "divisor", "dominant-baseline", "dur", "dx", "dy", "edgeMode", "elevation", "enable-background", "end", "exponent", "externalResourcesRequired", "Section", "fill", "fill-opacity", "fill-rule", "filter", "filterRes", "filterUnits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "format", "from", "fr", "fx", "fy", "g1", "g2", "glyph-name", "glyph-orientation-horizontal", "glyph-orientation-vertical", "glyphRef", "gradientTransform", "gradientUnits", "hanging", "height", "href", "hreflang", "horiz-adv-x", "horiz-origin-x", "ISection", "id", "ideographic", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kernelMatrix", "kernelUnitLength", "kerning", "keyPoints", "keySplines", "keyTimes", "lang", "lengthAdjust", "letter-spacing", "lighting-color", "limitingConeAngle", "local", "MSection", "marker-end", "marker-mid", "marker-start", "markerHeight", "markerUnits", "markerWidth", "mask", "maskContentUnits", "maskUnits", "mathematical", "max", "media", "method", "min", "mode", "NSection", "name", "numOctaves", "offset", "opacity", "operator", "order", "orient", "orientation", "origin", "overflow", "overline-position", "overline-thickness", "panose-1", "paint-order", "path", "pathLength", "patternContentUnits", "patternTransform", "patternUnits", "ping", "pointer-events", "points", "pointsAtX", "pointsAtY", "pointsAtZ", "preserveAlpha", "preserveAspectRatio", "primitiveUnits", "r", "radius", "referrerPolicy", "refX", "refY", "rel", "rendering-intent", "repeatCount", "repeatDur", "requiredExtensions", "requiredFeatures", "restart", "result", "rotate", "rx", "ry", "scale", "seed", "shape-rendering", "slope", "spacing", "specularConstant", "specularExponent", "speed", "spreadMethod", "startOffset", "stdDeviation", "stemh", "stemv", "stitchTiles", "stop-color", "stop-opacity", "strikethrough-position", "strikethrough-thickness", "string", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "surfaceScale", "systemLanguage", "tabindex", "tableValues", "target", "targetX", "targetY", "text-anchor", "text-decoration", "text-rendering", "textLength", "to", "transform", "type", "u1", "u2", "underline-position", "underline-thickness", "unicode", "unicode-bidi", "unicode-range", "units-per-em", "v-alphabetic", "v-hanging", "v-ideographic", "v-mathematical", "values", "vector-effect", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "viewBox", "viewTarget", "visibility", "width", "widths", "word-spacing", "writing-mode", "x", "x-height", "x1", "x2", "xChannelSelector", "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show", "xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "y", "y1", "y2", "yChannelSelector", "z", "zoomAndPan" };
-
- ///
- /// Allowlist for SVG tabs.
- ///
- public static readonly IList Tags = new [] { "a", "altGlyph", "altGlyphDef", "altGlyphItem", "animate", "animateColor", "animateMotion", "animateTransform", "circle", "clipPath", "color-profile", "cursor", "defs", "desc", "discard", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "font", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignObject", "g", "glyph", "glyphRef", "hatch", "hatchpath", "hkern", "image", "line", "linearGradient", "marker", "mask", "mesh", "meshgradient", "meshpatch", "meshrow", "metadata", "missing-glyph", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "set", "solidcolor", "stop", "svg", "switch", "symbol", "text", "textPath", "title", "tref", "tspan", "unknown", "use", "view", "vkern" };
- }
- }
-}
diff --git a/src/Umbraco.Core/Extensions/PasswordConfigurationExtensions.cs b/src/Umbraco.Core/Extensions/PasswordConfigurationExtensions.cs
index a16a6f30a1..0c15da6bdb 100644
--- a/src/Umbraco.Core/Extensions/PasswordConfigurationExtensions.cs
+++ b/src/Umbraco.Core/Extensions/PasswordConfigurationExtensions.cs
@@ -24,7 +24,7 @@ namespace Umbraco.Extensions
// TODO: This doesn't make a ton of sense with asp.net identity and also there's a bunch of other settings
// that we can consider with IPasswordConfiguration, but these are currently still based on how membership providers worked.
- {"minNonAlphaNumericChars", passwordConfiguration.RequireNonLetterOrDigit ? 2 : 0},
+ {"minNonAlphaNumericChars", passwordConfiguration.GetMinNonAlphaNumericChars()},
// A flag to indicate if the current password box should be shown or not, only a user that has access to change other user/member passwords
// doesn't have to specify the current password for the user/member. A user changing their own password must specify their current password.
@@ -32,5 +32,10 @@ namespace Umbraco.Extensions
};
}
+ public static int GetMinNonAlphaNumericChars(this IPasswordConfiguration passwordConfiguration)
+ {
+ return passwordConfiguration.RequireNonLetterOrDigit ? 2 : 0;
+ }
+
}
}
diff --git a/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs b/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs
index f609123370..433278b8c0 100644
--- a/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs
+++ b/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs
@@ -262,7 +262,7 @@ namespace Umbraco.Extensions
// else... if we have a property, at least let the converter return its own
// vision of 'no value' (could be an empty enumerable) - otherwise, default
- return property == null ? default : property.Value(publishedValueFallback, culture, segment);
+ return property == null ? default : property.Value(publishedValueFallback, culture, segment, fallback, defaultValue);
}
#endregion
@@ -634,6 +634,64 @@ namespace Umbraco.Extensions
#endregion
+ #region Axes: breadcrumbs
+
+ ///
+ /// Gets the breadcrumbs (ancestors and self, top to bottom) for the specified .
+ ///
+ /// The content.
+ /// Indicates whether the specified content should be included.
+ ///
+ /// The breadcrumbs (ancestors and self, top to bottom) for the specified .
+ ///
+ public static IEnumerable Breadcrumbs(this IPublishedContent content, bool andSelf = true)
+ {
+ return content.AncestorsOrSelf(andSelf, null).Reverse();
+ }
+
+ ///
+ /// Gets the breadcrumbs (ancestors and self, top to bottom) for the specified at a level higher or equal to .
+ ///
+ /// The content.
+ /// The minimum level.
+ /// Indicates whether the specified content should be included.
+ ///
+ /// The breadcrumbs (ancestors and self, top to bottom) for the specified at a level higher or equal to .
+ ///
+ public static IEnumerable Breadcrumbs(this IPublishedContent content, int minLevel, bool andSelf = true)
+ {
+ return content.AncestorsOrSelf(andSelf, n => n.Level >= minLevel).Reverse();
+ }
+
+ ///
+ /// Gets the breadcrumbs (ancestors and self, top to bottom) for the specified at a level higher or equal to the specified root content type .
+ ///
+ /// The root content type.
+ /// The content.
+ /// Indicates whether the specified content should be included.
+ ///
+ /// The breadcrumbs (ancestors and self, top to bottom) for the specified at a level higher or equal to the specified root content type .
+ ///
+ public static IEnumerable Breadcrumbs(this IPublishedContent content, bool andSelf = true)
+ where T : class, IPublishedContent
+ {
+ static IEnumerable TakeUntil(IEnumerable source, Func predicate)
+ {
+ foreach (var item in source)
+ {
+ yield return item;
+ if (predicate(item))
+ {
+ yield break;
+ }
+ }
+ }
+
+ return TakeUntil(content.AncestorsOrSelf(andSelf, null), n => n is T).Reverse();
+ }
+
+ #endregion
+
#region Axes: descendants, descendants-or-self
///
@@ -1065,15 +1123,37 @@ namespace Umbraco.Extensions
#region Axes: custom
///
- /// Gets the root content for this content.
+ /// Gets the root content (ancestor or self at level 1) for the specified .
///
/// The content.
- /// The 'site' content ie AncestorOrSelf(1).
+ ///
+ /// The root content (ancestor or self at level 1) for the specified .
+ ///
+ ///
+ /// This is the same as calling with maxLevel set to 1.
+ ///
public static IPublishedContent Root(this IPublishedContent content)
{
return content.AncestorOrSelf(1);
}
+ ///
+ /// Gets the root content (ancestor or self at level 1) for the specified if it's of the specified content type .
+ ///
+ /// The content type.
+ /// The content.
+ ///
+ /// The root content (ancestor or self at level 1) for the specified of content type .
+ ///
+ ///
+ /// This is the same as calling with maxLevel set to 1.
+ ///
+ public static T Root(this IPublishedContent content)
+ where T : class, IPublishedContent
+ {
+ return content.AncestorOrSelf(1);
+ }
+
#endregion
#region Writer and creator
diff --git a/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs b/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs
index e95322b32a..46000ab3aa 100644
--- a/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs
+++ b/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs
@@ -1,6 +1,5 @@
-// Copyright (c) Umbraco.
+// Copyright (c) Umbraco.
// See LICENSE for more details.
-
using Umbraco.Cms.Core.Models.PublishedContent;
namespace Umbraco.Extensions
@@ -33,9 +32,16 @@ namespace Umbraco.Extensions
// we have a value
// try to cast or convert it
var value = property.GetValue(culture, segment);
- if (value is T valueAsT) return valueAsT;
+ if (value is T valueAsT)
+ {
+ return valueAsT;
+ }
+
var valueConverted = value.TryConvertTo();
- if (valueConverted) return valueConverted.Result;
+ if (valueConverted)
+ {
+ return valueConverted.Result;
+ }
// cannot cast nor convert the value, nothing we can return but 'default'
// note: we don't want to fallback in that case - would make little sense
@@ -44,14 +50,28 @@ namespace Umbraco.Extensions
// we don't have a value, try fallback
if (publishedValueFallback.TryGetValue(property, culture, segment, fallback, defaultValue, out var fallbackValue))
+ {
return fallbackValue;
+ }
// we don't have a value - neither direct nor fallback
// give a chance to the converter to return something (eg empty enumerable)
var noValue = property.GetValue(culture, segment);
- if (noValue is T noValueAsT) return noValueAsT;
+ if (noValue == null)
+ {
+ return default;
+ }
+
+ if (noValue is T noValueAsT)
+ {
+ return noValueAsT;
+ }
+
var noValueConverted = noValue.TryConvertTo();
- if (noValueConverted) return noValueConverted.Result;
+ if (noValueConverted)
+ {
+ return noValueConverted.Result;
+ }
// cannot cast noValue nor convert it, nothing we can return but 'default'
return default;
diff --git a/src/Umbraco.Core/Extensions/StringExtensions.cs b/src/Umbraco.Core/Extensions/StringExtensions.cs
index 452e409d34..3b42426cd6 100644
--- a/src/Umbraco.Core/Extensions/StringExtensions.cs
+++ b/src/Umbraco.Core/Extensions/StringExtensions.cs
@@ -22,6 +22,7 @@ namespace Umbraco.Extensions
///
public static class StringExtensions
{
+ private const char DefaultEscapedStringEscapeChar = '\\';
private static readonly char[] ToCSharpHexDigitLower = "0123456789abcdef".ToCharArray();
private static readonly char[] ToCSharpEscapeChars;
@@ -1437,5 +1438,44 @@ namespace Umbraco.Extensions
{
return shortStringHelper.CleanStringForSafeFileName(text, culture);
}
+
+ ///
+ /// Splits a string with an escape character that allows for the split character to exist in a string
+ ///
+ /// The string to split
+ /// The character to split on
+ /// The character which can be used to escape the character to split on
+ /// The string split into substrings delimited by the split character
+ public static IEnumerable EscapedSplit(this string value, char splitChar, char escapeChar = DefaultEscapedStringEscapeChar)
+ {
+ if (value == null) yield break;
+
+ var sb = new StringBuilder(value.Length);
+ var escaped = false;
+
+ foreach (var chr in value.ToCharArray())
+ {
+ if (escaped)
+ {
+ escaped = false;
+ sb.Append(chr);
+ }
+ else if (chr == splitChar)
+ {
+ yield return sb.ToString();
+ sb.Clear();
+ }
+ else if (chr == escapeChar)
+ {
+ escaped = true;
+ }
+ else
+ {
+ sb.Append(chr);
+ }
+ }
+
+ yield return sb.ToString();
+ }
}
}
diff --git a/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs
index aa38e8afed..825ff09a69 100644
--- a/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs
+++ b/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs
@@ -53,7 +53,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security
{
string message;
var success = false;
- Uri url = _hostingEnvironment.ApplicationMainUrl;
+ var url = _hostingEnvironment.ApplicationMainUrl.GetLeftPart(UriPartial.Authority);;
// Access the site home page and check for the headers
var request = new HttpRequestMessage(HttpMethod.Head, url);
@@ -73,7 +73,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security
}
catch (Exception ex)
{
- message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url.ToString(), ex.Message });
+ message = _textService.Localize("healthcheck/healthCheckInvalidUrl", new[] { url.ToString(), ex.Message });
}
return
diff --git a/src/Umbraco.Core/IO/FileSystemWrapper.cs b/src/Umbraco.Core/IO/FileSystemWrapper.cs
index 5802c327d5..34276131c7 100644
--- a/src/Umbraco.Core/IO/FileSystemWrapper.cs
+++ b/src/Umbraco.Core/IO/FileSystemWrapper.cs
@@ -23,94 +23,94 @@ namespace Umbraco.Cms.Core.IO
internal IFileSystem InnerFileSystem { get; set; }
- public IEnumerable GetDirectories(string path)
+ public virtual IEnumerable GetDirectories(string path)
{
return InnerFileSystem.GetDirectories(path);
}
- public void DeleteDirectory(string path)
+ public virtual void DeleteDirectory(string path)
{
InnerFileSystem.DeleteDirectory(path);
}
- public void DeleteDirectory(string path, bool recursive)
+ public virtual void DeleteDirectory(string path, bool recursive)
{
InnerFileSystem.DeleteDirectory(path, recursive);
}
- public bool DirectoryExists(string path)
+ public virtual bool DirectoryExists(string path)
{
return InnerFileSystem.DirectoryExists(path);
}
- public void AddFile(string path, Stream stream)
+ public virtual void AddFile(string path, Stream stream)
{
InnerFileSystem.AddFile(path, stream);
}
- public void AddFile(string path, Stream stream, bool overrideExisting)
+ public virtual void AddFile(string path, Stream stream, bool overrideExisting)
{
InnerFileSystem.AddFile(path, stream, overrideExisting);
}
- public IEnumerable GetFiles(string path)
+ public virtual IEnumerable GetFiles(string path)
{
return InnerFileSystem.GetFiles(path);
}
- public IEnumerable GetFiles(string path, string filter)
+ public virtual IEnumerable GetFiles(string path, string filter)
{
return InnerFileSystem.GetFiles(path, filter);
}
- public Stream OpenFile(string path)
+ public virtual Stream OpenFile(string path)
{
return InnerFileSystem.OpenFile(path);
}
- public void DeleteFile(string path)
+ public virtual void DeleteFile(string path)
{
InnerFileSystem.DeleteFile(path);
}
- public bool FileExists(string path)
+ public virtual bool FileExists(string path)
{
return InnerFileSystem.FileExists(path);
}
- public string GetRelativePath(string fullPathOrUrl)
+ public virtual string GetRelativePath(string fullPathOrUrl)
{
return InnerFileSystem.GetRelativePath(fullPathOrUrl);
}
- public string GetFullPath(string path)
+ public virtual string GetFullPath(string path)
{
return InnerFileSystem.GetFullPath(path);
}
- public string GetUrl(string path)
+ public virtual string GetUrl(string path)
{
return InnerFileSystem.GetUrl(path);
}
- public DateTimeOffset GetLastModified(string path)
+ public virtual DateTimeOffset GetLastModified(string path)
{
return InnerFileSystem.GetLastModified(path);
}
- public DateTimeOffset GetCreated(string path)
+ public virtual DateTimeOffset GetCreated(string path)
{
return InnerFileSystem.GetCreated(path);
}
- public long GetSize(string path)
+ public virtual long GetSize(string path)
{
return InnerFileSystem.GetSize(path);
}
- public bool CanAddPhysical => InnerFileSystem.CanAddPhysical;
+ public virtual bool CanAddPhysical => InnerFileSystem.CanAddPhysical;
- public void AddFile(string path, string physicalPath, bool overrideIfExists = true, bool copy = false)
+ public virtual void AddFile(string path, string physicalPath, bool overrideIfExists = true, bool copy = false)
{
InnerFileSystem.AddFile(path, physicalPath, overrideIfExists, copy);
}
diff --git a/src/Umbraco.Core/Logging/ProfilingLogger.cs b/src/Umbraco.Core/Logging/ProfilingLogger.cs
index 3abb3d348f..6a6bcfd850 100644
--- a/src/Umbraco.Core/Logging/ProfilingLogger.cs
+++ b/src/Umbraco.Core/Logging/ProfilingLogger.cs
@@ -95,6 +95,8 @@ namespace Umbraco.Cms.Core.Logging
public void LogTrace(string messageTemplate, params object[] propertyValues)
=> Logger.LogTrace(messageTemplate, propertyValues);
+
+
#endregion
}
}
diff --git a/src/Umbraco.Core/Mapping/IMapDefinition.cs b/src/Umbraco.Core/Mapping/IMapDefinition.cs
index c90896ebc7..3d4270c93e 100644
--- a/src/Umbraco.Core/Mapping/IMapDefinition.cs
+++ b/src/Umbraco.Core/Mapping/IMapDefinition.cs
@@ -8,6 +8,6 @@
///
/// Defines maps.
///
- void DefineMaps(UmbracoMapper mapper);
+ void DefineMaps(IUmbracoMapper mapper);
}
}
diff --git a/src/Umbraco.Core/Mapping/IUmbracoMapper.cs b/src/Umbraco.Core/Mapping/IUmbracoMapper.cs
new file mode 100644
index 0000000000..7a0448b036
--- /dev/null
+++ b/src/Umbraco.Core/Mapping/IUmbracoMapper.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections.Generic;
+
+namespace Umbraco.Cms.Core.Mapping
+{
+ public interface IUmbracoMapper
+ {
+ ///
+ /// Defines a mapping.
+ ///
+ /// The source type.
+ /// The target type.
+ void Define();
+
+ ///
+ /// Defines a mapping.
+ ///
+ /// The source type.
+ /// The target type.
+ /// A mapping method.
+ void Define(Action map);
+
+ ///
+ /// Defines a mapping.
+ ///
+ /// The source type.
+ /// The target type.
+ /// A constructor method.
+ void Define(Func ctor);
+
+ ///
+ /// Defines a mapping.
+ ///
+ /// The source type.
+ /// The target type.
+ /// A constructor method.
+ /// A mapping method.
+ void Define(Func ctor, Action map);
+
+ ///
+ /// Maps a source object to a new target object.
+ ///
+ /// The target type.
+ /// The source object.
+ /// The target object.
+ TTarget Map(object source);
+
+ ///
+ /// Maps a source object to a new target object.
+ ///
+ /// The target type.
+ /// The source object.
+ /// A mapper context preparation method.
+ /// The target object.
+ TTarget Map(object source, Action f);
+
+ ///
+ /// Maps a source object to a new target object.
+ ///
+ /// The target type.
+ /// The source object.
+ /// A mapper context.
+ /// The target object.
+ TTarget Map(object source, MapperContext context);
+
+ ///
+ /// Maps a source object to a new target object.
+ ///
+ /// The source type.
+ /// The target type.
+ /// The source object.
+ /// The target object.
+ TTarget Map(TSource source);
+
+ ///
+ /// Maps a source object to a new target object.
+ ///
+ /// The source type.
+ /// The target type.
+ /// The source object.
+ /// A mapper context preparation method.
+ /// The target object.
+ TTarget Map(TSource source, Action f);
+
+ ///
+ /// Maps a source object to a new target object.
+ ///
+ /// The source type.
+ /// The target type.
+ /// The source object.
+ /// A mapper context.
+ /// The target object.
+ TTarget Map(TSource source, MapperContext context);
+
+ ///
+ /// Maps a source object to an existing target object.
+ ///
+ /// The source type.
+ /// The target type.
+ /// The source object.
+ /// The target object.
+ /// The target object.
+ TTarget Map(TSource source, TTarget target);
+
+ ///
+ /// Maps a source object to an existing target object.
+ ///
+ /// The source type.
+ /// The target type.
+ /// The source object.
+ /// The target object.
+ /// A mapper context preparation method.
+ /// The target object.
+ TTarget Map(TSource source, TTarget target, Action f);
+
+ ///
+ /// Maps a source object to an existing target object.
+ ///
+ /// The source type.
+ /// The target type.
+ /// The source object.
+ /// The target object.
+ /// A mapper context.
+ /// The target object.
+ TTarget Map(TSource source, TTarget target, MapperContext context);
+
+ ///
+ /// Maps an enumerable of source objects to a new list of target objects.
+ ///
+ /// The type of the source objects.
+ /// The type of the target objects.
+ /// The source objects.
+ /// A list containing the target objects.
+ List MapEnumerable(IEnumerable source);
+
+ ///
+ /// Maps an enumerable of source objects to a new list of target objects.
+ ///
+ /// The type of the source objects.
+ /// The type of the target objects.
+ /// The source objects.
+ /// A mapper context preparation method.
+ /// A list containing the target objects.
+ List MapEnumerable(IEnumerable source, Action f);
+
+ ///
+ /// Maps an enumerable of source objects to a new list of target objects.
+ ///
+ /// The type of the source objects.
+ /// The type of the target objects.
+ /// The source objects.
+ /// A mapper context.
+ /// A list containing the target objects.
+ List MapEnumerable(IEnumerable source, MapperContext context);
+ }
+}
diff --git a/src/Umbraco.Core/Mapping/MapperContext.cs b/src/Umbraco.Core/Mapping/MapperContext.cs
index f44cae2253..0e529b23a1 100644
--- a/src/Umbraco.Core/Mapping/MapperContext.cs
+++ b/src/Umbraco.Core/Mapping/MapperContext.cs
@@ -8,13 +8,13 @@ namespace Umbraco.Cms.Core.Mapping
///
public class MapperContext
{
- private readonly UmbracoMapper _mapper;
+ private readonly IUmbracoMapper _mapper;
private IDictionary _items;
///
/// Initializes a new instance of the class.
///
- public MapperContext(UmbracoMapper mapper)
+ public MapperContext(IUmbracoMapper mapper)
{
_mapper = mapper;
}
diff --git a/src/Umbraco.Core/Models/ContentEditing/SearchResult.cs b/src/Umbraco.Core/Models/ContentEditing/SearchResult.cs
index d7de53baeb..5ca02d1bc7 100644
--- a/src/Umbraco.Core/Models/ContentEditing/SearchResult.cs
+++ b/src/Umbraco.Core/Models/ContentEditing/SearchResult.cs
@@ -16,6 +16,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
public int FieldCount => Values?.Count ?? 0;
[DataMember(Name = "values")]
- public IReadOnlyDictionary Values { get; set; }
+ public IReadOnlyDictionary> Values { get; set; }
}
}
diff --git a/src/Umbraco.Core/Models/Mapping/AuditMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/AuditMapDefinition.cs
index 811e2e57a2..072611da4c 100644
--- a/src/Umbraco.Core/Models/Mapping/AuditMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/AuditMapDefinition.cs
@@ -5,7 +5,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
{
public class AuditMapDefinition : IMapDefinition
{
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new AuditLog(), Map);
}
diff --git a/src/Umbraco.Core/Models/Mapping/CodeFileMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/CodeFileMapDefinition.cs
index 6adfcf0fc5..d2fd28f510 100644
--- a/src/Umbraco.Core/Models/Mapping/CodeFileMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/CodeFileMapDefinition.cs
@@ -5,7 +5,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
{
public class CodeFileMapDefinition : IMapDefinition
{
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new EntityBasic(), Map);
mapper.Define((source, context) => new CodeFileDisplay(), Map);
diff --git a/src/Umbraco.Core/Models/Mapping/ContentPropertyMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/ContentPropertyMapDefinition.cs
index 5893d1e1e5..797232fc60 100644
--- a/src/Umbraco.Core/Models/Mapping/ContentPropertyMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/ContentPropertyMapDefinition.cs
@@ -24,7 +24,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
_contentPropertyDisplayMapper = new ContentPropertyDisplayMapper(cultureDictionary, dataTypeService, entityService, textService, loggerFactory.CreateLogger(), propertyEditors);
}
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define>((source, context) => new Tab(), Map);
mapper.Define((source, context) => new ContentPropertyBasic(), Map);
diff --git a/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs
index 3716e9c6a9..850bc59e76 100644
--- a/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs
@@ -52,7 +52,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
_hostingEnvironment = hostingEnvironment;
}
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new ContentType(_shortStringHelper, source.ParentId), Map);
mapper.Define((source, context) => new MediaType(_shortStringHelper, source.ParentId), Map);
diff --git a/src/Umbraco.Core/Models/Mapping/DataTypeMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/DataTypeMapDefinition.cs
index c1b60d7d9c..b1302e50ad 100644
--- a/src/Umbraco.Core/Models/Mapping/DataTypeMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/DataTypeMapDefinition.cs
@@ -34,7 +34,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
Constants.DataTypes.DefaultMembersListView
};
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new PropertyEditorBasic(), Map);
mapper.Define((source, context) => new DataTypeConfigurationFieldDisplay(), Map);
diff --git a/src/Umbraco.Core/Models/Mapping/DictionaryMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/DictionaryMapDefinition.cs
index aef6473ca5..4c000f0173 100644
--- a/src/Umbraco.Core/Models/Mapping/DictionaryMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/DictionaryMapDefinition.cs
@@ -20,7 +20,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
_localizationService = localizationService;
}
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new EntityBasic(), Map);
mapper.Define((source, context) => new DictionaryDisplay(), Map);
diff --git a/src/Umbraco.Core/Models/Mapping/LanguageMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/LanguageMapDefinition.cs
index fa88f958a9..9c14d4249d 100644
--- a/src/Umbraco.Core/Models/Mapping/LanguageMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/LanguageMapDefinition.cs
@@ -8,7 +8,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
{
public class LanguageMapDefinition : IMapDefinition
{
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new EntityBasic(), Map);
mapper.Define((source, context) => new ContentEditing.Language(), Map);
diff --git a/src/Umbraco.Core/Models/Mapping/MacroMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/MacroMapDefinition.cs
index eb5d55d0b6..24dbe35d37 100644
--- a/src/Umbraco.Core/Models/Mapping/MacroMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/MacroMapDefinition.cs
@@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
_logger = logger;
}
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new EntityBasic(), Map);
mapper.Define((source, context) => new MacroDisplay(), Map);
diff --git a/src/Umbraco.Core/Models/Mapping/MemberMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/MemberMapDefinition.cs
index 81cf573bbc..c2c3e14f5d 100644
--- a/src/Umbraco.Core/Models/Mapping/MemberMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/MemberMapDefinition.cs
@@ -7,7 +7,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
public class MemberMapDefinition : IMapDefinition
{
///
- public void DefineMaps(UmbracoMapper mapper) => mapper.Define(Map);
+ public void DefineMaps(IUmbracoMapper mapper) => mapper.Define(Map);
private static void Map(MemberSave source, IMember target, MapperContext context)
{
diff --git a/src/Umbraco.Core/Models/Mapping/RedirectUrlMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/RedirectUrlMapDefinition.cs
index dda5f2a939..f4715b3a6b 100644
--- a/src/Umbraco.Core/Models/Mapping/RedirectUrlMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/RedirectUrlMapDefinition.cs
@@ -13,7 +13,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
_publishedUrlProvider = publishedUrlProvider;
}
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new ContentRedirectUrl(), Map);
}
diff --git a/src/Umbraco.Core/Models/Mapping/RelationMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/RelationMapDefinition.cs
index cddb862d50..41caa526e2 100644
--- a/src/Umbraco.Core/Models/Mapping/RelationMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/RelationMapDefinition.cs
@@ -16,7 +16,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
_relationService = relationService;
}
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new RelationTypeDisplay(), Map);
mapper.Define((source, context) => new RelationDisplay(), Map);
diff --git a/src/Umbraco.Core/Models/Mapping/SectionMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/SectionMapDefinition.cs
index f3c1991a8e..af1bafed4c 100644
--- a/src/Umbraco.Core/Models/Mapping/SectionMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/SectionMapDefinition.cs
@@ -15,7 +15,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
_textService = textService;
}
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new Section(), Map);
diff --git a/src/Umbraco.Core/Models/Mapping/TagMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/TagMapDefinition.cs
index a23ce1ed69..7bd436fa54 100644
--- a/src/Umbraco.Core/Models/Mapping/TagMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/TagMapDefinition.cs
@@ -4,7 +4,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
{
public class TagMapDefinition : IMapDefinition
{
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new TagModel(), Map);
}
diff --git a/src/Umbraco.Core/Models/Mapping/TemplateMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/TemplateMapDefinition.cs
index 8ca26244e3..624868f3f4 100644
--- a/src/Umbraco.Core/Models/Mapping/TemplateMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/TemplateMapDefinition.cs
@@ -13,7 +13,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
_shortStringHelper = shortStringHelper;
}
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new TemplateDisplay(), Map);
mapper.Define((source, context) => new Template(_shortStringHelper, source.Name, source.Alias), Map);
diff --git a/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs
index 767ed8d58a..76f9e7f64f 100644
--- a/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs
+++ b/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs
@@ -48,7 +48,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
_imageUrlGenerator = imageUrlGenerator;
}
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new UserGroup(_shortStringHelper) { CreateDate = DateTime.UtcNow }, Map);
mapper.Define(Map);
diff --git a/src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerConfiguration.cs b/src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerConfiguration.cs
new file mode 100644
index 0000000000..9c2dffb61d
--- /dev/null
+++ b/src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerConfiguration.cs
@@ -0,0 +1,14 @@
+namespace Umbraco.Cms.Core.PropertyEditors
+{
+ ///
+ /// Represents the configuration for the Eye Dropper picker value editor.
+ ///
+ public class EyeDropperColorPickerConfiguration
+ {
+ [ConfigurationField("showAlpha", "Show alpha", "boolean", Description = "Allow alpha transparency selection.")]
+ public bool ShowAlpha { get; set; }
+
+ [ConfigurationField("showPalette", "Show palette", "boolean", Description = "Show a palette next to the color picker.")]
+ public bool ShowPalette { get; set; }
+ }
+}
diff --git a/src/Umbraco.Core/PropertyEditors/ListViewConfiguration.cs b/src/Umbraco.Core/PropertyEditors/ListViewConfiguration.cs
index 96af838710..d7fbcf63ea 100644
--- a/src/Umbraco.Core/PropertyEditors/ListViewConfiguration.cs
+++ b/src/Umbraco.Core/PropertyEditors/ListViewConfiguration.cs
@@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
Layouts = new[]
{
new Layout { Name = "List", Icon = "icon-list", IsSystem = 1, Selected = true, Path = "views/propertyeditors/listview/layouts/list/list.html" },
- new Layout { Name = "grid", Icon = "icon-thumbnails-small", IsSystem = 1, Selected = true, Path = "views/propertyeditors/listview/layouts/grid/grid.html" }
+ new Layout { Name = "Grid", Icon = "icon-thumbnails-small", IsSystem = 1, Selected = true, Path = "views/propertyeditors/listview/layouts/grid/grid.html" }
};
IncludeProperties = new[]
diff --git a/src/Umbraco.Core/Security/PasswordGenerator.cs b/src/Umbraco.Core/Security/PasswordGenerator.cs
index 1347d77ab7..55a6ba1a51 100644
--- a/src/Umbraco.Core/Security/PasswordGenerator.cs
+++ b/src/Umbraco.Core/Security/PasswordGenerator.cs
@@ -24,7 +24,7 @@ namespace Umbraco.Cms.Core.Security
{
var password = PasswordStore.GeneratePassword(
_passwordConfiguration.RequiredLength,
- _passwordConfiguration.RequireNonLetterOrDigit ? 2 : 0);
+ _passwordConfiguration.GetMinNonAlphaNumericChars());
var random = new Random();
diff --git a/src/Umbraco.Core/Services/ContentServiceExtensions.cs b/src/Umbraco.Core/Services/ContentServiceExtensions.cs
index ffa0a38489..89b70ed00f 100644
--- a/src/Umbraco.Core/Services/ContentServiceExtensions.cs
+++ b/src/Umbraco.Core/Services/ContentServiceExtensions.cs
@@ -94,25 +94,5 @@ namespace Umbraco.Extensions
{
contentService.SetPermissions(new EntityPermissionSet(contentId, new EntityPermissionCollection()));
}
-
- ///
- /// Returns true if there is any content in the recycle bin
- ///
- ///
- ///
- public static bool RecycleBinSmells(this IContentService contentService)
- {
- return contentService.CountChildren(Constants.System.RecycleBinContent) > 0;
- }
-
- ///
- /// Returns true if there is any media in the recycle bin
- ///
- ///
- ///
- public static bool RecycleBinSmells(this IMediaService mediaService)
- {
- return mediaService.CountChildren(Constants.System.RecycleBinMedia) > 0;
- }
}
}
diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs
index 2e6aa32c01..c7b930bc6e 100644
--- a/src/Umbraco.Core/Services/IContentService.cs
+++ b/src/Umbraco.Core/Services/IContentService.cs
@@ -317,6 +317,11 @@ namespace Umbraco.Cms.Core.Services
/// Optional Id of the User emptying the Recycle Bin
OperationResult EmptyRecycleBin(int userId = Constants.Security.SuperUserId);
+ ///
+ /// Returns true if there is any content in the recycle bin
+ ///
+ bool RecycleBinSmells();
+
///
/// Sorts documents.
///
diff --git a/src/Umbraco.Core/Services/IMediaService.cs b/src/Umbraco.Core/Services/IMediaService.cs
index 32862e1f87..fc4d4fd612 100644
--- a/src/Umbraco.Core/Services/IMediaService.cs
+++ b/src/Umbraco.Core/Services/IMediaService.cs
@@ -161,6 +161,11 @@ namespace Umbraco.Cms.Core.Services
/// Optional Id of the User emptying the Recycle Bin
OperationResult EmptyRecycleBin(int userId = Constants.Security.SuperUserId);
+ ///
+ /// Returns true if there is any media in the recycle bin
+ ///
+ bool RecycleBinSmells();
+
///
/// Deletes all media of specified type. All children of deleted media is moved to Recycle Bin.
///
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 27e3098a31..59bf33d110 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -51,4 +51,4 @@
-
+
\ No newline at end of file
diff --git a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs
index 3da6b854f8..d05bb8f07f 100644
--- a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs
+++ b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs
@@ -29,7 +29,7 @@ namespace Umbraco.Cms.Infrastructure.Examine
private readonly IEntityService _entityService;
private readonly IUmbracoTreeSearcherFields _treeSearcherFields;
private readonly AppCaches _appCaches;
- private readonly UmbracoMapper _umbracoMapper;
+ private readonly IUmbracoMapper _umbracoMapper;
private readonly IPublishedUrlProvider _publishedUrlProvider;
public BackOfficeExamineSearcher(IExamineManager examineManager,
@@ -38,7 +38,7 @@ namespace Umbraco.Cms.Infrastructure.Examine
IEntityService entityService,
IUmbracoTreeSearcherFields treeSearcherFields,
AppCaches appCaches,
- UmbracoMapper umbracoMapper,
+ IUmbracoMapper umbracoMapper,
IPublishedUrlProvider publishedUrlProvider)
{
_examineManager = examineManager;
diff --git a/src/Umbraco.Examine.Lucene/UmbracoExamineIndex.cs b/src/Umbraco.Examine.Lucene/UmbracoExamineIndex.cs
index a5c98cdeba..851dfbd152 100644
--- a/src/Umbraco.Examine.Lucene/UmbracoExamineIndex.cs
+++ b/src/Umbraco.Examine.Lucene/UmbracoExamineIndex.cs
@@ -127,7 +127,7 @@ namespace Umbraco.Cms.Infrastructure.Examine
using (ExecutionContext.SuppressFlow())
{
base.PerformIndexItems(values, onComplete);
- }
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.MappingProfiles.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.MappingProfiles.cs
index 80a89da097..42ce7f7932 100644
--- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.MappingProfiles.cs
+++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.MappingProfiles.cs
@@ -14,7 +14,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
///
public static IUmbracoBuilder AddCoreMappingProfiles(this IUmbracoBuilder builder)
{
- builder.Services.AddUnique();
+ builder.Services.AddUnique();
builder.WithCollectionBuilder()
.Add()
diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs
index 05bd0bf26f..a7ddf3378f 100644
--- a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs
+++ b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs
@@ -115,7 +115,7 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps
return new
{
minCharLength = _passwordConfiguration.RequiredLength,
- minNonAlphaNumericLength = _passwordConfiguration.RequireNonLetterOrDigit ? 1 : 0,
+ minNonAlphaNumericLength = _passwordConfiguration.GetMinNonAlphaNumericChars(),
quickInstallAvailable = DatabaseConfigureStep.IsSqlCeAvailable()
};
}
diff --git a/src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs b/src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs
index 7010dac185..515709cfe5 100644
--- a/src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs
+++ b/src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs
@@ -113,29 +113,36 @@ namespace Umbraco.Cms.Core.Manifest
if(jobject["editor"]["view"] is JValue view)
jobject["editor"]["view"] = RewriteVirtualUrl(view);
- if (jobject["prevalues"] is JObject config)
+ var prevalues = jobject["prevalues"] as JObject;
+ var defaultConfig = jobject["defaultConfig"] as JObject;
+ if (prevalues != null || defaultConfig != null)
{
// explicitly assign a configuration editor of type ConfigurationEditor
// (else the deserializer will try to read it before setting it)
// (and besides it's an interface)
target.ExplicitConfigurationEditor = new ConfigurationEditor();
- // see note about validators, above - same applies to field validators
- if (config["fields"] is JArray jarray)
+ var config = new JObject();
+ if (prevalues != null)
{
- foreach (var field in jarray)
+ config = prevalues;
+ // see note about validators, above - same applies to field validators
+ if (config["fields"] is JArray jarray)
{
- if (field["validation"] is JObject fvalidation)
- field["validation"] = RewriteValidators(fvalidation);
+ foreach (var field in jarray)
+ {
+ if (field["validation"] is JObject fvalidation)
+ field["validation"] = RewriteValidators(fvalidation);
- if(field["view"] is JValue fview)
- field["view"] = RewriteVirtualUrl(fview);
+ if(field["view"] is JValue fview)
+ field["view"] = RewriteVirtualUrl(fview);
+ }
}
}
// in the manifest, default configuration is at editor level
// move it down to configuration editor level so it can be deserialized properly
- if (jobject["defaultConfig"] is JObject defaultConfig)
+ if (defaultConfig != null)
{
config["defaultConfig"] = defaultConfig;
jobject.Remove("defaultConfig");
diff --git a/src/Umbraco.Core/Mapping/UmbracoMapper.cs b/src/Umbraco.Infrastructure/Mapping/UmbracoMapper.cs
similarity index 95%
rename from src/Umbraco.Core/Mapping/UmbracoMapper.cs
rename to src/Umbraco.Infrastructure/Mapping/UmbracoMapper.cs
index 42efa9b007..9710c47987 100644
--- a/src/Umbraco.Core/Mapping/UmbracoMapper.cs
+++ b/src/Umbraco.Infrastructure/Mapping/UmbracoMapper.cs
@@ -4,6 +4,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Cms.Core.Exceptions;
+using Umbraco.Cms.Core.Scoping;
using Umbraco.Extensions;
namespace Umbraco.Cms.Core.Mapping
@@ -30,7 +31,7 @@ namespace Umbraco.Cms.Core.Mapping
/// using the Map{TTarget}(object source, ...) TSource is defined as source.GetType().
/// In both cases, TTarget is explicit and not typeof(target).
///
- public class UmbracoMapper
+ public class UmbracoMapper : IUmbracoMapper
{
// note
//
@@ -43,12 +44,17 @@ namespace Umbraco.Cms.Core.Mapping
private readonly ConcurrentDictionary>> _maps
= new ConcurrentDictionary>>();
+ private readonly IScopeProvider _scopeProvider;
+
///
/// Initializes a new instance of the class.
///
///
- public UmbracoMapper(MapDefinitionCollection profiles)
+ ///
+ public UmbracoMapper(MapDefinitionCollection profiles, IScopeProvider scopeProvider)
{
+ _scopeProvider = scopeProvider;
+
foreach (var profile in profiles)
profile.DefineMaps(this);
}
@@ -204,7 +210,10 @@ namespace Umbraco.Cms.Core.Mapping
if (ctor != null && map != null)
{
var target = ctor(source, context);
- map(source, target, context);
+ using (var scope = _scopeProvider.CreateScope(autoComplete: true))
+ {
+ map(source, target, context);
+ }
return (TTarget)target;
}
@@ -249,11 +258,14 @@ namespace Umbraco.Cms.Core.Mapping
{
var targetList = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(targetGenericArg));
- foreach (var sourceItem in source)
+ using (var scope = _scopeProvider.CreateScope(autoComplete: true))
{
- var targetItem = ctor(sourceItem, context);
- map(sourceItem, targetItem, context);
- targetList.Add(targetItem);
+ foreach (var sourceItem in source)
+ {
+ var targetItem = ctor(sourceItem, context);
+ map(sourceItem, targetItem, context);
+ targetList.Add(targetItem);
+ }
}
object target = targetList;
@@ -316,7 +328,10 @@ namespace Umbraco.Cms.Core.Mapping
// if there is a direct map, map
if (map != null)
{
- map(source, target, context);
+ using (var scope = _scopeProvider.CreateScope(autoComplete: true))
+ {
+ map(source, target, context);
+ }
return target;
}
diff --git a/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs
index 4bdd37d6b0..9d511eb877 100644
--- a/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs
+++ b/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs
@@ -12,7 +12,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
{
public class EntityMapDefinition : IMapDefinition
{
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define((source, context) => new EntityBasic(), Map);
mapper.Define((source, context) => new EntityBasic(), Map);
diff --git a/src/Umbraco.Infrastructure/ModelsBuilder/Building/TextBuilder.cs b/src/Umbraco.Infrastructure/ModelsBuilder/Building/TextBuilder.cs
index 40a3aaf9f2..d9f37fd2bd 100644
--- a/src/Umbraco.Infrastructure/ModelsBuilder/Building/TextBuilder.cs
+++ b/src/Umbraco.Infrastructure/ModelsBuilder/Building/TextBuilder.cs
@@ -248,7 +248,7 @@ namespace Umbraco.Cms.Infrastructure.ModelsBuilder.Building
WriteGeneratedCodeAttribute(sb, "\t\t");
sb.AppendFormat("\t\t[ImplementPropertyType(\"{0}\")]\n", property.Alias);
- sb.Append("\t\tpublic ");
+ sb.Append("\t\tpublic virtual ");
WriteClrType(sb, property.ClrTypeName);
sb.AppendFormat(" {0} => ",
@@ -309,14 +309,14 @@ namespace Umbraco.Cms.Infrastructure.ModelsBuilder.Building
if (mixinStatic)
{
- sb.Append("\t\tpublic ");
+ sb.Append("\t\tpublic virtual ");
WriteClrType(sb, property.ClrTypeName);
sb.AppendFormat(" {0} => {1}(this, _publishedValueFallback);\n",
property.ClrName, MixinStaticGetterName(property.ClrName));
}
else
{
- sb.Append("\t\tpublic ");
+ sb.Append("\t\tpublic virtual ");
WriteClrType(sb, property.ClrTypeName);
sb.AppendFormat(" {0} => this.Value",
property.ClrName);
diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/IDocumentRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/IDocumentRepository.cs
index c9076577b7..03d5fd12e2 100644
--- a/src/Umbraco.Infrastructure/Persistence/Repositories/IDocumentRepository.cs
+++ b/src/Umbraco.Infrastructure/Persistence/Repositories/IDocumentRepository.cs
@@ -73,5 +73,10 @@ namespace Umbraco.Cms.Core.Persistence.Repositories
///
///
void AddOrUpdatePermissions(ContentPermissionSet permission);
+
+ ///
+ /// Returns true if there is any content in the recycle bin
+ ///
+ bool RecycleBinSmells();
}
}
diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/IMediaRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/IMediaRepository.cs
index 0ed7dc7297..d07f2a68c7 100644
--- a/src/Umbraco.Infrastructure/Persistence/Repositories/IMediaRepository.cs
+++ b/src/Umbraco.Infrastructure/Persistence/Repositories/IMediaRepository.cs
@@ -6,5 +6,6 @@ namespace Umbraco.Cms.Core.Persistence.Repositories
public interface IMediaRepository : IContentRepository, IReadRepository
{
IMedia GetMediaByPath(string mediaPath);
+ bool RecycleBinSmells();
}
}
diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs
index b693a0d85a..80f1cbc8f6 100644
--- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs
+++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs
@@ -176,9 +176,11 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
while (compositionIx < compositionDtos.Count && compositionDtos[compositionIx].ChildId == contentType.Id)
{
var parentDto = compositionDtos[compositionIx];
- if (!contentTypes.TryGetValue(parentDto.ParentId, out var parentContentType)) continue;
- contentType.AddContentType(parentContentType);
compositionIx++;
+
+ if (!contentTypes.TryGetValue(parentDto.ParentId, out var parentContentType))
+ continue;
+ contentType.AddContentType(parentContentType);
}
}
}
diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs
index cb157c0f33..dd30f85872 100644
--- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs
+++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs
@@ -934,6 +934,15 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
public override int RecycleBinId => Cms.Core.Constants.System.RecycleBinContent;
+ public bool RecycleBinSmells()
+ {
+ var cache = _appCaches.RuntimeCache;
+ var cacheKey = CacheKeys.ContentRecycleBinCacheKey;
+
+ // always cache either true or false
+ return cache.GetCacheItem(cacheKey, () => CountChildren(RecycleBinId) > 0);
+ }
+
#endregion
#region Read Repository implementation for Guid keys
diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MediaRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MediaRepository.cs
index ceeffd033c..80804004b8 100644
--- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MediaRepository.cs
+++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MediaRepository.cs
@@ -27,6 +27,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
///
public class MediaRepository : ContentRepositoryBase, IMediaRepository
{
+ private readonly AppCaches _cache;
private readonly IMediaTypeRepository _mediaTypeRepository;
private readonly ITagRepository _tagRepository;
private readonly MediaUrlGeneratorCollection _mediaUrlGenerators;
@@ -51,6 +52,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
IEventAggregator eventAggregator)
: base(scopeAccessor, cache, logger, languageRepository, relationRepository, relationTypeRepository, propertyEditorCollection, dataValueReferenceFactories, dataTypeService, eventAggregator)
{
+ _cache = cache;
_mediaTypeRepository = mediaTypeRepository ?? throw new ArgumentNullException(nameof(mediaTypeRepository));
_tagRepository = tagRepository ?? throw new ArgumentNullException(nameof(tagRepository));
_mediaUrlGenerators = mediaUrlGenerators;
@@ -387,6 +389,15 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
public override int RecycleBinId => Cms.Core.Constants.System.RecycleBinMedia;
+ public bool RecycleBinSmells()
+ {
+ var cache = _cache.RuntimeCache;
+ var cacheKey = CacheKeys.MediaRecycleBinCacheKey;
+
+ // always cache either true or false
+ return cache.GetCacheItem(cacheKey, () => CountChildren(RecycleBinId) > 0);
+ }
+
#endregion
#region Read Repository implementation for Guid keys
@@ -513,7 +524,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
var cached = IsolatedCache.GetCacheItem(RepositoryCacheKeys.GetKey(dto.NodeId));
if (cached != null && cached.VersionId == dto.ContentVersionDto.Id)
{
- content[i] = (Core.Models.Media) cached;
+ content[i] = (Core.Models.Media)cached;
continue;
}
}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerConfigurationEditor.cs
new file mode 100644
index 0000000000..514200ff68
--- /dev/null
+++ b/src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerConfigurationEditor.cs
@@ -0,0 +1,54 @@
+
+using System.Collections.Generic;
+using Umbraco.Cms.Core.IO;
+using Umbraco.Extensions;
+
+namespace Umbraco.Cms.Core.PropertyEditors
+{
+ internal class EyeDropperColorPickerConfigurationEditor : ConfigurationEditor
+ {
+ public EyeDropperColorPickerConfigurationEditor(IIOHelper ioHelper)
+ : base(ioHelper)
+ {
+ }
+
+ ///
+ public override Dictionary ToConfigurationEditor(EyeDropperColorPickerConfiguration configuration)
+ {
+ return new Dictionary
+ {
+ { "showAlpha", configuration.ShowAlpha },
+ { "showPalette", configuration.ShowPalette }
+ };
+ }
+
+ ///
+ public override EyeDropperColorPickerConfiguration FromConfigurationEditor(IDictionary editorValues, EyeDropperColorPickerConfiguration configuration)
+ {
+ var output = new EyeDropperColorPickerConfiguration();
+
+ var showAlpha = true;
+ var showPalette = true;
+
+ if (editorValues.TryGetValue("showAlpha", out var alpha))
+ {
+ var attempt = alpha.TryConvertTo();
+ if (attempt.Success)
+ showAlpha = attempt.Result;
+ }
+
+ if (editorValues.TryGetValue("showPalette", out var palette))
+ {
+ var attempt = palette.TryConvertTo();
+ if (attempt.Success)
+ showPalette = attempt.Result;
+ }
+
+ return new EyeDropperColorPickerConfiguration
+ {
+ ShowAlpha = showAlpha,
+ ShowPalette = showPalette
+ };
+ }
+ }
+}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs
new file mode 100644
index 0000000000..23fdeaeb6d
--- /dev/null
+++ b/src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs
@@ -0,0 +1,43 @@
+using Microsoft.Extensions.Logging;
+using Umbraco.Cms.Core.IO;
+using Umbraco.Cms.Core.Serialization;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Strings;
+
+namespace Umbraco.Cms.Core.PropertyEditors
+{
+ [DataEditor(
+ Constants.PropertyEditors.Aliases.ColorPickerEyeDropper,
+ "Eye Dropper Color Picker",
+ "eyedropper",
+ Icon = "icon-colorpicker",
+ Group = Constants.PropertyEditors.Groups.Pickers)]
+ public class EyeDropperColorPickerPropertyEditor : DataEditor
+ {
+ private readonly IIOHelper _ioHelper;
+
+ public EyeDropperColorPickerPropertyEditor(
+ ILoggerFactory loggerFactory,
+ IDataTypeService dataTypeService,
+ ILocalizationService localizationService,
+ ILocalizedTextService localizedTextService,
+ IShortStringHelper shortStringHelper,
+ IJsonSerializer jsonSerializer,
+ IIOHelper ioHelper,
+ EditorType type = EditorType.PropertyValue)
+ : base(
+ loggerFactory,
+ dataTypeService,
+ localizationService,
+ localizedTextService,
+ shortStringHelper,
+ jsonSerializer,
+ type)
+ {
+ _ioHelper = ioHelper;
+ }
+
+ ///
+ protected override IConfigurationEditor CreateConfigurationEditor() => new EyeDropperColorPickerConfigurationEditor(_ioHelper);
+ }
+}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs
index f1e6a16bd4..4f03cf33a8 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs
@@ -137,7 +137,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
}
catch (Exception ex)
{
- _logger.LogError("Error getting links", ex);
+ _logger.LogError(ex, "Error getting links");
}
return base.ToEditor(property, culture, segment);
@@ -173,7 +173,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
}
catch (Exception ex)
{
- _logger.LogError("Error saving links", ex);
+ _logger.LogError(ex, "Error saving links");
}
return base.FromEditor(editorValue, currentValue);
diff --git a/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs b/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs
index 737f3550f6..c2c3262047 100644
--- a/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs
+++ b/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs
@@ -321,14 +321,14 @@ namespace Umbraco.Cms.Infrastructure.Runtime
// so now we update the row with our appdomain id
InsertLockRecord(_lockId, db);
- _logger.LogDebug("Acquired with ID {LockId}", _lockId);
- return true;
- }
- else if (mainDomRows.Count == 1 && !mainDomRows[0].Value.StartsWith(tempId))
- {
- // in this case, the prefixed ID is different which means
- // another new AppDomain has come online and is wanting to take over. In that case, we will not
- // acquire.
+ _logger.LogDebug("Acquired with ID {LockId}", _lockId);
+ return true;
+ }
+ else if (mainDomRows.Count == 1 && !mainDomRows[0].Value.StartsWith(tempId))
+ {
+ // in this case, the prefixed ID is different which means
+ // another new AppDomain has come online and is wanting to take over. In that case, we will not
+ // acquire.
_logger.LogDebug("Cannot acquire, another booting application detected.");
return false;
diff --git a/src/Umbraco.Infrastructure/Search/UmbracoTreeSearcher.cs b/src/Umbraco.Infrastructure/Search/UmbracoTreeSearcher.cs
index 4e13bbf3bb..b401e51f85 100644
--- a/src/Umbraco.Infrastructure/Search/UmbracoTreeSearcher.cs
+++ b/src/Umbraco.Infrastructure/Search/UmbracoTreeSearcher.cs
@@ -24,7 +24,7 @@ namespace Umbraco.Cms.Infrastructure.Search
{
private readonly ILocalizationService _languageService;
private readonly IEntityService _entityService;
- private readonly UmbracoMapper _mapper;
+ private readonly IUmbracoMapper _mapper;
private readonly ISqlContext _sqlContext;
private readonly IBackOfficeExamineSearcher _backOfficeExamineSearcher;
private readonly IPublishedUrlProvider _publishedUrlProvider;
@@ -33,7 +33,7 @@ namespace Umbraco.Cms.Infrastructure.Search
public UmbracoTreeSearcher(
ILocalizationService languageService,
IEntityService entityService,
- UmbracoMapper mapper,
+ IUmbracoMapper mapper,
ISqlContext sqlContext,
IBackOfficeExamineSearcher backOfficeExamineSearcher,
IPublishedUrlProvider publishedUrlProvider)
diff --git a/src/Umbraco.Infrastructure/Security/BackOfficeUserStore.cs b/src/Umbraco.Infrastructure/Security/BackOfficeUserStore.cs
index e8d6303837..e6a58efa88 100644
--- a/src/Umbraco.Infrastructure/Security/BackOfficeUserStore.cs
+++ b/src/Umbraco.Infrastructure/Security/BackOfficeUserStore.cs
@@ -30,7 +30,7 @@ namespace Umbraco.Cms.Core.Security
private readonly IEntityService _entityService;
private readonly IExternalLoginService _externalLoginService;
private readonly GlobalSettings _globalSettings;
- private readonly UmbracoMapper _mapper;
+ private readonly IUmbracoMapper _mapper;
private readonly AppCaches _appCaches;
///
@@ -42,7 +42,7 @@ namespace Umbraco.Cms.Core.Security
IEntityService entityService,
IExternalLoginService externalLoginService,
IOptions globalSettings,
- UmbracoMapper mapper,
+ IUmbracoMapper mapper,
BackOfficeErrorDescriber describer,
AppCaches appCaches)
: base(describer)
diff --git a/src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs b/src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs
index 5c7332ebcc..b51c434dc6 100644
--- a/src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs
+++ b/src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs
@@ -32,7 +32,7 @@ namespace Umbraco.Cms.Core.Security
_appCaches = appCaches;
}
- public void DefineMaps(UmbracoMapper mapper)
+ public void DefineMaps(IUmbracoMapper mapper)
{
mapper.Define(
(source, context) =>
diff --git a/src/Umbraco.Infrastructure/Security/MemberUserStore.cs b/src/Umbraco.Infrastructure/Security/MemberUserStore.cs
index f63338383f..a449255273 100644
--- a/src/Umbraco.Infrastructure/Security/MemberUserStore.cs
+++ b/src/Umbraco.Infrastructure/Security/MemberUserStore.cs
@@ -22,7 +22,7 @@ namespace Umbraco.Cms.Core.Security
{
private const string genericIdentityErrorCode = "IdentityErrorUserStore";
private readonly IMemberService _memberService;
- private readonly UmbracoMapper _mapper;
+ private readonly IUmbracoMapper _mapper;
private readonly IScopeProvider _scopeProvider;
///
@@ -34,7 +34,7 @@ namespace Umbraco.Cms.Core.Security
/// The error describer
public MemberUserStore(
IMemberService memberService,
- UmbracoMapper mapper,
+ IUmbracoMapper mapper,
IScopeProvider scopeProvider,
IdentityErrorDescriber describer)
: base(describer)
diff --git a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs
index 19e7a5d3e6..63edbb6ed8 100644
--- a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs
+++ b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs
@@ -2151,6 +2151,15 @@ namespace Umbraco.Cms.Core.Services.Implement
return OperationResult.Succeed(eventMessages);
}
+ public bool RecycleBinSmells()
+ {
+ using (var scope = ScopeProvider.CreateScope(autoComplete: true))
+ {
+ scope.ReadLock(Constants.Locks.ContentTree);
+ return _documentRepository.RecycleBinSmells();
+ }
+ }
+
#endregion
#region Others
diff --git a/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs b/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs
index f8f495ec7b..831cbb1b01 100644
--- a/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs
+++ b/src/Umbraco.Infrastructure/Services/Implement/MediaService.cs
@@ -1074,6 +1074,15 @@ namespace Umbraco.Cms.Core.Services.Implement
return OperationResult.Succeed(messages);
}
+ public bool RecycleBinSmells()
+ {
+ using (var scope = ScopeProvider.CreateScope(autoComplete: true))
+ {
+ scope.ReadLock(Constants.Locks.MediaTree);
+ return _mediaRepository.RecycleBinSmells();
+ }
+ }
+
#endregion
#region Others
diff --git a/src/Umbraco.Infrastructure/TagQuery.cs b/src/Umbraco.Infrastructure/TagQuery.cs
index ea2e41005d..9b49394392 100644
--- a/src/Umbraco.Infrastructure/TagQuery.cs
+++ b/src/Umbraco.Infrastructure/TagQuery.cs
@@ -16,12 +16,12 @@ namespace Umbraco.Cms.Core
{
private readonly ITagService _tagService;
private readonly IPublishedContentQuery _contentQuery;
- private readonly UmbracoMapper _mapper;
+ private readonly IUmbracoMapper _mapper;
///
/// Initializes a new instance of the class.
///
- public TagQuery(ITagService tagService, IPublishedContentQuery contentQuery, UmbracoMapper mapper)
+ public TagQuery(ITagService tagService, IPublishedContentQuery contentQuery, IUmbracoMapper mapper)
{
_tagService = tagService ?? throw new ArgumentNullException(nameof(tagService));
_contentQuery = contentQuery ?? throw new ArgumentNullException(nameof(contentQuery));
diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts
index 25f2a83007..1c0dd7a47a 100644
--- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts
+++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts
@@ -754,7 +754,7 @@ context('Content', () => {
cy.umbracoTreeItem("content", [name]).click();
// Click add
cy.get(':nth-child(2) > .preview-row > .preview-col > .preview-cell').click(); // Choose 1 column layout.
- cy.get('.umb-column > .templates-preview > :nth-child(2) > .ng-binding').click(); // Choose headline
+ cy.get('.umb-column > .templates-preview > :nth-child(2) > small').click(); // Choose headline
cy.get('.umb-cell-placeholder').click();
// Click macro
cy.get(':nth-child(4) > .umb-card-grid-item > :nth-child(1)').click();
diff --git a/src/Umbraco.Tests.Benchmarks/LoggerAllocationBenchmark.cs b/src/Umbraco.Tests.Benchmarks/LoggerAllocationBenchmark.cs
new file mode 100644
index 0000000000..97c23dc2f6
--- /dev/null
+++ b/src/Umbraco.Tests.Benchmarks/LoggerAllocationBenchmark.cs
@@ -0,0 +1,57 @@
+using BenchmarkDotNet.Attributes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Umbraco.Tests.Benchmarks.Config;
+
+namespace Umbraco.Tests.Benchmarks
+{
+ [QuickRunWithMemoryDiagnoserConfig]
+ public class LoggerAllocationBenchmark
+ {
+ private string rawQuery = "";
+ private int totalItemCount;
+ [Benchmark(Baseline = true)]
+ public void Baseline()
+ {
+ for (int i = 0; i < 1000; i++)
+ {
+ OriginalDebugSignature(GetType(), "DeleteFromIndex with query: {Query} (found {TotalItems} results)", rawQuery, totalItemCount);
+ }
+
+ }
+
+ [Benchmark()]
+ public void NewOverload2()
+ {
+ for (int i = 0; i < 1000; i++)
+ {
+ NewDebugSignature(GetType(), "DeleteFromIndex with query: {Query} (found {TotalItems} results)", rawQuery, totalItemCount);
+ }
+ }
+ public void OriginalDebugSignature(Type reporting, string messageTemplate, params object[] propertyValues)
+ {
+
+ }
+
+ public void NewDebugSignature(Type reporting, string messageTemplate, T1 param1, T2 param2)
+ {
+
+ }
+
+ // BenchmarkDotNet=v0.11.3, OS=Windows 10.0.18362
+ //Intel Core i5-8265U CPU 1.60GHz(Kaby Lake R), 1 CPU, 8 logical and 4 physical cores
+ // [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.8.4180.0
+ // Job-JIATTD : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.8.4180.0
+
+ //IterationCount=3 IterationTime=100.0000 ms LaunchCount = 1
+ //WarmupCount=3
+
+ // Method | Mean | Error | StdDev | Ratio | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op |
+ //------------- |----------:|----------:|----------:|------:|------------:|------------:|------------:|--------------------:|
+ // Baseline | 14.599 us | 1.0882 us | 0.0596 us | 1.00 | 10.0420 | - | - | 32048 B |
+ // NewOverload2 | 1.775 us | 0.4056 us | 0.0222 us | 0.12 | - | - | - | - |
+ }
+}
diff --git a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj
index d1d88fc870..a4e916a1e1 100644
--- a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj
+++ b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj
@@ -55,6 +55,7 @@
+
diff --git a/src/Umbraco.Tests.Integration/TestServerTest/TestAuthHandler.cs b/src/Umbraco.Tests.Integration/TestServerTest/TestAuthHandler.cs
index 500e3aa633..788d5856c2 100644
--- a/src/Umbraco.Tests.Integration/TestServerTest/TestAuthHandler.cs
+++ b/src/Umbraco.Tests.Integration/TestServerTest/TestAuthHandler.cs
@@ -31,7 +31,7 @@ namespace Umbraco.Cms.Tests.Integration.TestServerTest
ISystemClock clock,
IBackOfficeSignInManager backOfficeSignInManager,
IUserService userService,
- UmbracoMapper umbracoMapper)
+ IUmbracoMapper umbracoMapper)
: base(options, logger, encoder, clock)
{
_backOfficeSignInManager = backOfficeSignInManager;
diff --git a/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/ContentTypeModelMappingTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/ContentTypeModelMappingTests.cs
index ac9dbfa81d..87ab2857e4 100644
--- a/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/ContentTypeModelMappingTests.cs
+++ b/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/ContentTypeModelMappingTests.cs
@@ -26,14 +26,14 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Mapping
public class ContentTypeModelMappingTests : UmbracoIntegrationTest
{
private IDataTypeService _dataTypeService;
- private UmbracoMapper _sut;
+ private IUmbracoMapper _sut;
private IFileService _fileService;
private IConfigurationEditorJsonSerializer _serializer;
[SetUp]
public void SetupTest()
{
- _sut = Services.GetRequiredService();
+ _sut = Services.GetRequiredService();
_dataTypeService = Services.GetRequiredService();
_fileService = Services.GetRequiredService();
_serializer = Services.GetRequiredService();
diff --git a/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UmbracoMapperTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UmbracoMapperTests.cs
index fb27ac5495..276a6f0f4c 100644
--- a/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UmbracoMapperTests.cs
+++ b/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UmbracoMapperTests.cs
@@ -26,7 +26,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Mapping
[SetUp]
public void SetUp()
{
- _sut = Services.GetRequiredService();
+ _sut = Services.GetRequiredService();
_dataTypeService = Services.GetRequiredService();
_propertyEditorCollection = Services.GetRequiredService();
@@ -37,7 +37,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Mapping
_localizedTextService = Services.GetRequiredService();
}
- private UmbracoMapper _sut;
+ private IUmbracoMapper _sut;
private IDataTypeService _dataTypeService;
private PropertyEditorCollection _propertyEditorCollection;
private MediaBuilder _mediaBuilder;
diff --git a/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UserModelMapperTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UserModelMapperTests.cs
index 5b96ebed3c..12f2b42b41 100644
--- a/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UserModelMapperTests.cs
+++ b/src/Umbraco.Tests.Integration/Umbraco.Core/Mapping/UserModelMapperTests.cs
@@ -17,10 +17,10 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Mapping
[UmbracoTest(Mapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
public class UserModelMapperTests : UmbracoIntegrationTest
{
- private UmbracoMapper _sut;
+ private IUmbracoMapper _sut;
[SetUp]
- public void Setup() => _sut = Services.GetRequiredService();
+ public void Setup() => _sut = Services.GetRequiredService();
[Test]
public void Map_UserGroupSave_To_IUserGroup()
diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs
index 98bd28c084..fd27dda811 100644
--- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs
+++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs
@@ -34,7 +34,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repos
private IFileSystems FileSystems => GetRequiredService();
- private UmbracoMapper Mapper => GetRequiredService();
+ private IUmbracoMapper Mapper => GetRequiredService();
private IContentTypeService ContentTypeService => GetRequiredService();
diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs
index 0d5db3a42a..fc9cae55a2 100644
--- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs
+++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs
@@ -1010,8 +1010,8 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services
Assert.AreEqual(2, _msgCount);
Assert.AreEqual(2, _events.Count);
- int i = 0;
- int m = 0;
+ var i = 0;
+ var m = 0;
Assert.AreEqual($"{m:000}: ContentRepository/Remove/{content.Id}", _events[i++].ToString());
m++;
Assert.AreEqual($"{m:000}: ContentCacheRefresher/Remove/{content.Id}", _events[i].ToString());
@@ -1035,15 +1035,13 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services
Assert.AreEqual(3, _msgCount);
Assert.AreEqual(4, _events.Count);
- int i = 0;
- int m = 0;
-#pragma warning disable SA1003 // Symbols should be spaced correctly (justification: suppression necessary here as it's used in an interpolated string format.
+ var i = 0;
+ var m = 0;
Assert.AreEqual($"{m++:000}: ContentRepository/Remove/{content1.Id}", _events[i++].ToString());
Assert.AreEqual($"{m:000}: ContentRepository/Remove/{content2.Id}", _events[i++].ToString());
m++;
Assert.AreEqual($"{m:000}: ContentCacheRefresher/Remove/{content1.Id}", _events[i++].ToString());
Assert.AreEqual($"{m:000}: ContentCacheRefresher/Remove/{content2.Id}", _events[i].ToString());
-#pragma warning restore SA1003 // Symbols should be spaced correctly
}
[Test]
@@ -1068,10 +1066,9 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services
Assert.AreEqual(14, _msgCount);
Assert.AreEqual(14, _events.Count);
- int i = 0;
- int m = 0;
+ var i = 0;
+ var m = 0;
-#pragma warning disable SA1003 // Symbols should be spaced correctly (justification: suppression necessary here as it's used in an interpolated string format.
Assert.AreEqual($"{m++:000}: ContentRepository/Remove/{content5C[1].Id}", _events[i++].ToString());
Assert.AreEqual($"{m++:000}: ContentRepository/Remove/{content5C[0].Id}", _events[i++].ToString());
Assert.AreEqual($"{m++:000}: ContentRepository/Remove/{content1C[3].Id}", _events[i++].ToString());
@@ -1087,7 +1084,6 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services
Assert.AreEqual($"{m:000}: ContentRepository/Remove/{content1.Id}", _events[i++].ToString());
m++;
Assert.AreEqual($"{m:000}: ContentCacheRefresher/Remove/{content1.Id}", _events[i].ToString());
-#pragma warning restore SA1003 // Symbols should be spaced correctly
}
#endregion
diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/StandardMvc-Package.xml b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/StandardMvc-Package.xml
index a4787dd570..f0013771c3 100644
--- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/StandardMvc-Package.xml
+++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/StandardMvc-Package.xml
@@ -210,7 +210,7 @@ Google Maps - A map macro that you can use within Rich Text Areas
Built by Creative Founds
Creative Founds design and build first class software solutions that deliver big results. We provide ASP.NET web and mobile applications, Umbraco development service & technical consultancy.
]]>
Umbraco Development
@@ -218,7 +218,7 @@ Google Maps - A map macro that you can use within Rich Text Areas
Contact Us
-
We'd love to hear how this package has helped you and how it can be improved. Get in touch on the project website or via twitter
]]>
+
We'd love to hear how this package has helped you and how it can be improved. Get in touch on the project website or via twitter
]]>
Standard Website MVC, Company Address, Glasgow, Postcode
@@ -418,7 +418,7 @@ Google Maps - A map macro that you can use within Rich Text Areas
Standard Website MVC
Well hello! This website package demonstrates all the standard functionality of Umbraco. It's a great starting point for starting point for further development or as a prototype.
@@ -37,7 +40,7 @@ Use this directive to render a tabs navigation.
(function () {
"use strict";
- function Controller() {
+ function Controller(eventsService) {
var vm = this;
@@ -62,7 +65,7 @@ Use this directive to render a tabs navigation.
selectedTab.active = true;
};
- eventsService.on("tab.tabChange", function(name, args){
+ eventsService.on("app.tabChange", function(name, args){
console.log("args", args);
});
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreesearchbox.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreesearchbox.directive.js
index 3e2e7e362e..2ae17fdc6b 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreesearchbox.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreesearchbox.directive.js
@@ -15,6 +15,7 @@ function treeSearchBox(localizationService, searchService, $q) {
datatypeKey: "@",
hideSearchCallback: "=",
searchCallback: "=",
+ inputId: "@",
autoFocus: "="
},
restrict: "E", // restrict to an element
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js
index 1682ef968e..35ca2a8588 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js
@@ -11,6 +11,7 @@
vm.cancelChange = cancelChange;
vm.showOldPass = showOldPass;
vm.showCancelBtn = showCancelBtn;
+ vm.newPasswordKeyUp = newPasswordKeyUp;
var unsubscribe = [];
@@ -34,6 +35,11 @@
vm.config.minPasswordLength = 0;
}
+ // Check non-alpha pwd settings for tooltip display
+ if (vm.config.minNonAlphaNumericChars === undefined) {
+ vm.config.minNonAlphaNumericChars = 0;
+ }
+
//set the model defaults
if (!Utilities.isObject(vm.passwordValues)) {
//if it's not an object then just create a new one
@@ -120,6 +126,9 @@
return vm.config.disableToggle !== true && vm.config.hasPassword;
};
+ function newPasswordKeyUp(event) {
+ vm.passwordVal = event.target.value;
+ }
}
var component = {
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
index c7894da171..55878db2e9 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
@@ -44,9 +44,7 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location
this.isShowingValidation = () => $scope.showValidation === true;
- this.notify = function () {
- notify($scope);
- }
+ this.notify = notify;
this.isValid = function () {
return !$scope.formCtrl.$invalid;
@@ -112,6 +110,7 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location
});
//watch the list of validation errors to notify the application of any validation changes
+ // TODO: Wouldn't it be easier/faster to watch formCtrl.$invalid ?
scope.$watch(() => angularHelper.countAllFormErrors(formCtrl),
function (e) {
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 26c0403f85..f9e2af584f 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
@@ -177,8 +177,9 @@ function valPropertyMsg(serverValidationManager, localizationService, angularHel
watcher = scope.$watchCollection(
() => formCtrl,
function (updatedFormController) {
- var ngModels = [];
- collectAllNgModelControllersRecursively(updatedFormController.$getControls(), ngModels);
+ let childControls = updatedFormController.$getControls();
+ let ngModels = [];
+ collectAllNgModelControllersRecursively(childControls, ngModels);
ngModels.forEach(x => {
if (!x.$validators.serverValidityResetter) {
x.$validators.serverValidityResetter = resetServerValidityValidator(x);
@@ -201,7 +202,7 @@ function valPropertyMsg(serverValidationManager, localizationService, angularHel
hasError = false;
formCtrl.$setValidity('valPropertyMsg', true);
scope.errorMsg = "";
-
+
}
// This deals with client side validation changes and is executed anytime validators change on the containing
@@ -264,6 +265,8 @@ function valPropertyMsg(serverValidationManager, localizationService, angularHel
//listen for form validation changes.
//The alternative is to add a watch to formCtrl.$invalid but that would lead to many more watches then
// subscribing to this single watch.
+ // TODO: Really? Since valFormManager is watching a countof all errors which is more overhead than watching formCtrl.$invalid
+ // and there's a TODO there that it should just watch formCtrl.$invalid
valFormManager.onValidationStatusChanged(function (evt, args) {
checkValidationStatus();
});
diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js
index ea7f3a6d4c..9a05e3cd7f 100644
--- a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js
+++ b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js
@@ -193,7 +193,7 @@ angular.module('umbraco.mocks').
"defaultdialogs_recycleBinDeleting": "The items in the recycle bin are now being deleted. Please do not close this window while this operation takes place",
"defaultdialogs_recycleBinIsEmpty": "The recycle bin is now empty",
"defaultdialogs_recycleBinWarning": "When items are deleted from the recycle bin, they will be gone forever",
- "defaultdialogs_regexSearchError": "regexlib.com's webservice is currently experiencing some problems, which we have no control over. We are very sorry for this inconvenience.",
+ "defaultdialogs_regexSearchError": "regexlib.com's webservice is currently experiencing some problems, which we have no control over. We are very sorry for this inconvenience.",
"defaultdialogs_regexSearchHelp": "Search for a regular expression to add validation to a form field. Exemple: 'email, 'zip-code' 'url'",
"defaultdialogs_removeMacro": "Remove Macro",
"defaultdialogs_requiredField": "Required Field",
@@ -355,7 +355,7 @@ angular.module('umbraco.mocks').
"installer_databaseHeader": "Database configuration",
"installer_databaseInstall": " Press the install button to install the Umbraco %0% database ",
"installer_databaseInstallDone": "Umbraco %0% has now been copied to your database. Press Next to proceed.",
- "installer_databaseNotFound": "
Database not found! Please check that the information in the 'connection string' of the \"web.config\" file is correct.
To proceed, please edit the 'web.config' file (using Visual Studio or your favourite text editor), scroll to the bottom, add the connection string for your database in the key named 'UmbracoDbDSN' and save the file.
Database not found! Please check that the information in the 'connection string' of the \"web.config\" file is correct.
To proceed, please edit the 'web.config' file (using Visual Studio or your favourite text editor), scroll to the bottom, add the connection string for your database in the key named 'UmbracoDbDSN' and save the file.
",
"installer_databaseText": "To complete this step, you must know some information regarding your database server ('connection string'). Please contact your ISP if necessary. If you're installing on a local machine or server you might need information from your system administrator.",
"installer_databaseUpgrade": "
Press the upgrade button to upgrade your database to Umbraco %0%
Don't worry - no content will be deleted and everything will continue working afterwards!
",
"installer_databaseUpgradeDone": "Your database has been upgraded to the final version %0%. Press Next to proceed. ",
@@ -420,7 +420,7 @@ angular.module('umbraco.mocks').
"login_greeting6": "Happy friendly Friday",
"login_greeting7": "Happy shiny Saturday",
"login_instruction": "Log in below:",
- "login_bottomText": "
",
"main_dashboard": "Dashboard",
"main_sections": "Sections",
"main_tree": "Content",
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
index a693b7d20e..6398cc55e7 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
@@ -432,13 +432,15 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter, loca
throw "args.id cannot be null";
}
+ var promise = localizationService.localize("contentType_moveFailed");
+
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostMove"),
{
parentId: args.parentId,
id: args.id
}, { responseType: 'text' }),
- 'Failed to move content');
+ promise);
},
/**
@@ -475,13 +477,15 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter, loca
throw "args.id cannot be null";
}
+ var promise = localizationService.localize("contentType_copyFailed");
+
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCopy"),
{
parentId: args.parentId,
id: args.id
}, { responseType: 'text' }),
- 'Failed to copy content');
+ promise);
},
/**
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js
index d194ae2c73..e3fab86067 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js
@@ -208,7 +208,7 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter, locali
throw "args.id cannot be null";
}
- var promise = localizationService.localize("media_moveFailed");
+ var promise = localizationService.localize("mediaType_moveFailed");
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostMove"),
@@ -230,7 +230,7 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter, locali
throw "args.id cannot be null";
}
- var promise = localizationService.localize("media_copyFailed");
+ var promise = localizationService.localize("mediaType_copyFailed");
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostCopy"),
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js
index 2314fa6d6c..bf02d9618e 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js
@@ -3,7 +3,7 @@
* @name umbraco.resources.memberTypeResource
* @description Loads in data for member types
**/
-function memberTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
+function memberTypeResource($q, $http, umbRequestHelper, umbDataFormatter, localizationService) {
return {
@@ -102,8 +102,29 @@ function memberTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("memberTypeApiBaseUrl", "PostSave"), saveModel),
'Failed to save data for member type id ' + contentType.id);
- }
+ },
+ copy: function (args) {
+ if (!args) {
+ throw "args cannot be null";
+ }
+ if (!args.parentId) {
+ throw "args.parentId cannot be null";
+ }
+ if (!args.id) {
+ throw "args.id cannot be null";
+ }
+
+ var promise = localizationService.localize("memberType_copyFailed");
+
+ return umbRequestHelper.resourcePromise(
+ $http.post(umbRequestHelper.getApiUrl("memberTypeApiBaseUrl", "PostCopy"),
+ {
+ parentId: args.parentId,
+ id: args.id
+ }, { responseType: 'text' }),
+ promise);
+ }
};
}
angular.module('umbraco.resources').factory('memberTypeResource', memberTypeResource);
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js
index 326123f797..b0a2465f42 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js
@@ -187,7 +187,7 @@ When building a custom infinite editor view you can use the same components as a
* @methodOf umbraco.services.editorService
*
* @description
- * Method to return all open editors
+ * Method to return all open editors.
*/
function getEditors() {
return editors;
@@ -199,7 +199,7 @@ When building a custom infinite editor view you can use the same components as a
* @methodOf umbraco.services.editorService
*
* @description
- * Method to return the number of open editors
+ * Method to return the number of open editors.
*/
function getNumberOfEditors() {
return editors.length;
@@ -250,8 +250,8 @@ When building a custom infinite editor view you can use the same components as a
* Method to open a new editor in infinite editing.
*
* @param {object} editor rendering options.
- * @param {string} editor.view Path to view.
- * @param {string} editor.size Sets the size of the editor ("small" || "medium"). If nothing is set it will use full width.
+ * @param {string} editor.view URL to view.
+ * @param {string} editor.size Sets the size of the editor (`small` or `medium`). If nothing is set it will use full width.
*/
function open(editor) {
@@ -286,7 +286,7 @@ When building a custom infinite editor view you can use the same components as a
* @methodOf umbraco.services.editorService
*
* @description
- * Method to close the latest opened editor
+ * Method to close the latest opened editor.
*/
function close() {
@@ -321,7 +321,7 @@ When building a custom infinite editor view you can use the same components as a
* @methodOf umbraco.services.editorService
*
* @description
- * Method to close all open editors
+ * Method to close all open editors.
*/
function closeAll() {
@@ -342,6 +342,7 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens a content editor in infinite editing, the submit callback returns the updated content item.
+ *
* @param {object} editor rendering options.
* @param {string} editor.id The id of the content item.
* @param {boolean} editor.create Create new content item.
@@ -351,7 +352,6 @@ When building a custom infinite editor view you can use the same components as a
* @param {string} editor.documentTypeAlias If editor.create is true, provide document type alias for the creation of the content item.
* @param {boolean} editor.allowSaveAndClose If editor is being used in infinite editing allows the editor to close when the save action is performed.
* @param {boolean} editor.allowPublishAndClose If editor is being used in infinite editing allows the editor to close when the publish action is performed.
- *
* @returns {object} editor object
*/
function contentEditor(editor) {
@@ -395,7 +395,6 @@ When building a custom infinite editor view you can use the same components as a
* @param {boolean} editor.multiPicker Pick one or multiple items.
* @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
* @param {function} editor.close Callback function when the close button is clicked.
- *
* @returns {object} editor object
*/
function contentTypePicker(editor) {
@@ -418,7 +417,6 @@ When building a custom infinite editor view you can use the same components as a
* @param {boolean} editor.multiPicker Pick one or multiple items.
* @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
* @param {function} editor.close Callback function when the close button is clicked.
- *
* @returns {object} editor object.
*/
function mediaTypePicker(editor) {
@@ -458,13 +456,14 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens a copy editor in infinite editing, the submit callback returns an array of selected items.
+ *
+ * @param {object} editor rendering options.
* @param {string} editor.section The node entity type.
* @param {string} editor.currentNode The current node id.
- * @param {function} editor.submit Saves, submits, and closes the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
-
function copy(editor) {
editor.view = "views/common/infiniteeditors/copy/copy.html";
if (!editor.size) editor.size = "small";
@@ -478,13 +477,14 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens a move editor in infinite editing.
+ *
+ * @param {object} editor rendering options.
* @param {string} editor.section The node entity type.
* @param {string} editor.currentNode The current node id.
- * @param {function} editor.submit Saves, submits, and closes the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
-
function move(editor) {
editor.view = "views/common/infiniteeditors/move/move.html";
if (!editor.size) editor.size = "small";
@@ -498,11 +498,12 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens an embed editor in infinite editing.
- * @param {function} editor.submit Saves, submits, and closes the editor.
- * @param {function} editor.close Closes the editor.
+ *
+ * @param {object} editor rendering options.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
-
function embed(editor) {
editor.view = "views/common/infiniteeditors/embed/embed.html";
if (!editor.size) editor.size = "small";
@@ -516,12 +517,13 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens a rollback editor in infinite editing.
+ *
+ * @param {object} editor rendering options.
* @param {string} editor.node The node to rollback.
- * @param {function} editor.submit Saves, submits, and closes the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
-
function rollback(editor) {
editor.view = "views/common/infiniteeditors/rollback/rollback.html";
if (!editor.size) editor.size = "medium";
@@ -535,11 +537,12 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens an embed editor in infinite editing.
+ *
* @param {object} editor rendering options.
* @param {string} editor.icon The icon class.
* @param {string} editor.color The color class.
- * @param {function} editor.submit Saves, submits, and closes the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function linkPicker(editor) {
@@ -555,11 +558,12 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens a media editor in infinite editing, the submit callback returns the updated media item.
+ *
* @param {object} editor rendering options.
* @param {string} editor.id The id of the media item.
* @param {boolean} editor.create Create new media item.
- * @param {function} editor.submit Saves, submits, and closes the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function mediaEditor(editor) {
@@ -574,6 +578,7 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens a media picker in infinite editing, the submit callback returns an array of selected media items.
+ *
* @param {object} editor rendering options.
* @param {number} editor.startNodeId Set the startnode of the picker (optional).
* @param {boolean} editor.multiPicker Pick one or multiple items.
@@ -581,8 +586,8 @@ When building a custom infinite editor view you can use the same components as a
* @param {boolean} editor.disableFolderSelect Disable folder selection.
* @param {boolean} editor.disableFocalPoint Disable focal point editor for selected media.
* @param {array} editor.updatedMediaNodes A list of ids for media items that have been updated through the media picker.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function mediaPicker(editor) {
@@ -599,10 +604,11 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the media crop details editor in infinite editing, the submit callback returns the updated media object.
+ *
* @param {object} editor rendering options.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
- * @returns {object} editor object
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
+ * @returns {object} editor object.
*/
function mediaCropDetails(editor) {
editor.view = "views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html";
@@ -616,11 +622,12 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens an icon picker in infinite editing, the submit callback returns the selected icon.
+ *
* @param {object} editor rendering options.
- * @param {string} editor.icon The CSS class representing the icon - eg. "icon-autofill".
- * @param {string} editor.color The CSS class representing the color - eg. "color-red".
- * @param {callback} editor.submit Submits the editor.
- * @param {callback} editor.close Closes the editor.
+ * @param {string} editor.icon The CSS class representing the icon - eg. `icon-autofill.
+ * @param {string} editor.color The CSS class representing the color - eg. color-red.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function iconPicker(editor) {
@@ -636,14 +643,15 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the document type editor in infinite editing, the submit callback returns the alias of the saved document type.
+ *
* @param {object} editor rendering options.
* @param {number} editor.id Indicates the ID of the document type to be edited. Alternatively the ID may be set to `-1` in combination with `create` being set to `true` to open the document type editor for creating a new document type.
* @param {boolean} editor.create Set to `true` to open the document type editor for creating a new document type.
* @param {boolean} editor.noTemplate If `true` and in combination with `create` being set to `true`, the document type editor will not create a corresponding template by default. This is similar to selecting the "Document Type without a template" in the Create dialog.
* @param {boolean} editor.isElement If `true` and in combination with `create` being set to `true`, the "Is an Element type" option will be selected by default in the document type editor.
* @param {boolean} editor.allowVaryByCulture If `true` and in combination with `create`, the "Allow varying by culture" option will be selected by default in the document type editor.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function documentTypeEditor(editor) {
@@ -658,10 +666,11 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the media type editor in infinite editing, the submit callback returns the saved media type.
+ *
* @param {object} editor rendering options.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
- * @returns {object} editor object
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
+ * @returns {object} editor object.
*/
function mediaTypeEditor(editor) {
editor.view = "views/mediatypes/edit.html";
@@ -675,9 +684,10 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the member type editor in infinite editing, the submit callback returns the saved member type.
+ *
* @param {object} editor rendering options.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function memberTypeEditor(editor) {
@@ -692,9 +702,10 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the query builder in infinite editing, the submit callback returns the generated query.
+ *
* @param {object} editor rendering options.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function queryBuilder(editor) {
@@ -709,12 +720,13 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the query builder in infinite editing, the submit callback returns the generted query.
+ *
* @param {object} editor rendering options.
* @param {string} options.section tree section to display.
* @param {string} options.treeAlias specific tree to display.
* @param {boolean} options.multiPicker should the tree pick one or multiple items before returning.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function treePicker(editor) {
@@ -730,9 +742,10 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the an editor to set node permissions.
+ *
* @param {object} editor rendering options.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function nodePermissions(editor) {
@@ -748,9 +761,10 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Open an editor to insert code snippets into the code editor.
+ *
* @param {object} editor rendering options.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function insertCodeSnippet(editor) {
@@ -766,6 +780,7 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the user group picker in infinite editing, the submit callback returns an array of the selected user groups.
+ *
* @param {object} editor rendering options.
* @param {function} editor.submit Submits the editor.
* @param {function} editor.close Closes the editor.
@@ -783,10 +798,11 @@ When building a custom infinite editor view you can use the same components as a
* @methodOf umbraco.services.editorService
*
* @description
- * Opens the user group picker in infinite editing, the submit callback returns the saved user group
+ * Opens the user group picker in infinite editing, the submit callback returns the saved user group.
+ *
* @param {object} editor rendering options.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function userGroupEditor(editor) {
@@ -801,10 +817,11 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the template editor in infinite editing, the submit callback returns the saved template.
+ *
* @param {object} editor rendering options.
* @param {string} editor.id The template id.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function templateEditor(editor) {
@@ -819,9 +836,10 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the section picker in infinite editing, the submit callback returns an array of the selected sections.
+ *
* @param {object} editor rendering options.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function sectionPicker(editor) {
@@ -837,9 +855,10 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the insert field editor in infinite editing, the submit callback returns the code snippet.
+ *
* @param {object} editor rendering options.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function insertField(editor) {
@@ -855,9 +874,10 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the template sections editor in infinite editing, the submit callback returns the type to insert.
+ *
* @param {object} editor rendering options.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function templateSections(editor) {
@@ -873,9 +893,10 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens the section picker in infinite editing, the submit callback returns an array of the selected users.
+ *
* @param {object} editor rendering options.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function userPicker(editor) {
@@ -896,8 +917,8 @@ When building a custom infinite editor view you can use the same components as a
* @param {array} editor.availableItems Array of available items.
* @param {array} editor.selectedItems Array of selected items. When passed in the selected items will be filtered from the available items.
* @param {boolean} editor.filter Set to false to hide the filter.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function itemPicker(editor) {
@@ -914,8 +935,9 @@ When building a custom infinite editor view you can use the same components as a
* @description
* Opens a macro picker in infinite editing, the submit callback returns an array of the selected items.
*
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {object} editor rendering options.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function macroPicker(editor) {
@@ -934,8 +956,8 @@ When building a custom infinite editor view you can use the same components as a
*
* @param {object} editor rendering options.
* @param {object} editor.multiPicker Pick one or multiple items.
- * @param {function} editor.submit Submits the editor.
- * @param {function} editor.close Closes the editor.
+ * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
+ * @param {function} editor.close Callback function when the close button is clicked.
* @returns {object} editor object.
*/
function memberGroupPicker(editor) {
@@ -956,7 +978,6 @@ When building a custom infinite editor view you can use the same components as a
* @param {boolean} editor.multiPicker Pick one or multiple items.
* @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
* @param {function} editor.close Callback function when the close button is clicked.
- *
* @returns {object} editor object.
*/
function memberPicker(editor) {
@@ -974,13 +995,13 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Opens a member editor in infinite editing, the submit callback returns the updated member.
+ *
* @param {object} editor rendering options.
* @param {string} editor.id The id (GUID) of the member.
* @param {boolean} editor.create Create new member.
* @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object.
* @param {function} editor.close Callback function when the close button is clicked.
- * @param {string} editor.doctype If editor.create is true, provide member type for the creation of the member.
- *
+ * @param {string} editor.doctype If `editor.create` is `true`, provide member type for the creation of the member.
* @returns {object} editor object.
*/
function memberEditor(editor) {
@@ -998,7 +1019,6 @@ When building a custom infinite editor view you can use the same components as a
* @description
* Internal method to keep track of keyboard shortcuts registered
* to each editor so they can be rebound when an editor closes.
- *
*/
function unbindKeyboardShortcuts() {
const shortcuts = Utilities.copy(keyboardService.keyboardEvent);
@@ -1018,7 +1038,6 @@ When building a custom infinite editor view you can use the same components as a
*
* @description
* Internal method to rebind keyboard shortcuts for the editor in focus.
- *
*/
function rebindKeyboardShortcuts() {
// find the shortcuts from the previous editor
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
index 0a4009264d..2b5447cdf6 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
@@ -252,10 +252,10 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
//each item has a property alias and the file object, we'll ensure that the alias is suffixed to the key
// so we know which property it belongs to on the server side
var file = args.files[f];
- var fileKey = "file_" + file.alias + "_" + (file.culture ? file.culture : "") + "_" + (file.segment ? file.segment : "");
+ var fileKey = "file_" + (file.alias || '').replace(/_/g, '\\_') + "_" + (file.culture ? file.culture.replace(/_/g, '\\_') : "") + "_" + (file.segment ? file.segment.replace(/_/g, '\\_') : "");
if (Utilities.isArray(file.metaData) && file.metaData.length > 0) {
- fileKey += ("_" + file.metaData.join("_"));
+ fileKey += ("_" + _.map(file.metaData, x => ('' + x).replace(/_/g, '\\_')).join("_"));
}
formData.append(fileKey, file.file);
}
diff --git a/src/Umbraco.Web.UI.Client/src/installer/installer.service.js b/src/Umbraco.Web.UI.Client/src/installer/installer.service.js
index ab1535d85b..2f0ae4b8cf 100644
--- a/src/Umbraco.Web.UI.Client/src/installer/installer.service.js
+++ b/src/Umbraco.Web.UI.Client/src/installer/installer.service.js
@@ -19,8 +19,8 @@ angular.module("umbraco.install").factory('installerService', function ($rootSco
"Over 500 000 websites are currently powered by Umbraco",
"At least 2 people have named their cat 'Umbraco'",
"On an average day more than 1000 people download Umbraco",
- "umbraco.tv is the premier source of Umbraco video tutorials to get you started",
- "You can find the world's friendliest CMS community at our.umbraco.com",
+ "umbraco.tv is the premier source of Umbraco video tutorials to get you started",
+ "You can find the world's friendliest CMS community at our.umbraco.com",
"You can become a certified Umbraco developer by attending one of the official courses",
"Umbraco works really well on tablets",
"You have 100% control over your markup and design when crafting a website in Umbraco",
@@ -30,7 +30,7 @@ angular.module("umbraco.install").factory('installerService', function ($rootSco
"At least 4 people have the Umbraco logo tattooed on them",
"'Umbraco' is the Danish name for an allen key",
"Umbraco has been around since 2005, that's a looong time in IT",
- "More than 700 people from all over the world meet each year in Denmark in May for our annual conference CodeGarden",
+ "More than 700 people from all over the world meet each year in Denmark in May for our annual conference CodeGarden",
"While you are installing Umbraco someone else on the other side of the planet is probably doing it too",
"You can extend Umbraco without modifying the source code using either JavaScript or C#",
"Umbraco has been installed in more than 198 countries"
diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/upgrade.html b/src/Umbraco.Web.UI.Client/src/installer/steps/upgrade.html
index 472ceb7135..8ea69b3ee4 100644
--- a/src/Umbraco.Web.UI.Client/src/installer/steps/upgrade.html
+++ b/src/Umbraco.Web.UI.Client/src/installer/steps/upgrade.html
@@ -10,7 +10,7 @@
To compare versions and read a report of changes between versions, use the View Report button below.
diff --git a/src/Umbraco.Web.UI.Client/src/views/contentBlueprints/intro.html b/src/Umbraco.Web.UI.Client/src/views/contentBlueprints/intro.html
index 66695ace91..57c29d31d6 100644
--- a/src/Umbraco.Web.UI.Client/src/views/contentBlueprints/intro.html
+++ b/src/Umbraco.Web.UI.Client/src/views/contentBlueprints/intro.html
@@ -17,7 +17,7 @@
What are Content Templates?
- Content Templates are pre-defined content that can be selected when creating a new content node.
+ Content Templates are pre-defined content that can be selected when creating a new content node.
Hours of Umbraco training videos are only a click away
-
Want to master Umbraco? Spend a couple of minutes learning some best practices by watching one of these videos about using Umbraco. And visit umbraco.tv for even more Umbraco videos
+
Want to master Umbraco? Spend a couple of minutes learning some best practices by watching one of these videos about using Umbraco. And visit umbraco.tv for even more Umbraco videos
-
+ (blank)
-
{{::blueprint.name}}
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.controller.js
index bb87f0463d..a5ccf7a9aa 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.controller.js
@@ -1,5 +1,5 @@
//inject umbracos assetsServce and dialog service
-function MarkdownEditorController($scope, $element, assetsService, editorService, angularHelper, $timeout) {
+function MarkdownEditorController($scope, $element, assetsService, editorService, $timeout) {
//tell the assets service to load the markdown.editor libs from the markdown editors
//plugin folder
@@ -41,6 +41,12 @@ function MarkdownEditorController($scope, $element, assetsService, editorService
editorService.linkPicker(linkPicker);
}
+ function setDirty() {
+ if ($scope.modelValueForm) {
+ $scope.modelValueForm.modelValue.$setDirty();
+ }
+ }
+
assetsService
.load([
"lib/markdown/markdown.converter.js",
@@ -78,7 +84,7 @@ function MarkdownEditorController($scope, $element, assetsService, editorService
if ($scope.model.value !== $("textarea", $element).val()) {
if ($scope.markdownEditorInitComplete) {
//only set dirty after init load to avoid "unsaved" dialogue when we don't want it
- angularHelper.getCurrentForm($scope).$setDirty();
+ setDirty();
} else {
$scope.markdownEditorInitComplete = true;
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.html
index 0834c4705b..6f2592d20a 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/markdowneditor/markdowneditor.html
@@ -1,8 +1,11 @@
-
-
+
+
-
+
+
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
index f3a57224e2..ca46f30bb7 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
@@ -1,7 +1,7 @@
//this controller simply tells the dialogs service to open a mediaPicker window
//with a specified callback, this callback will receive an object with a selection on it
angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerController",
- function ($scope, entityResource, mediaHelper, $timeout, userService, localizationService, editorService, angularHelper, overlayService) {
+ function ($scope, entityResource, mediaHelper, $timeout, userService, localizationService, editorService, overlayService) {
var vm = this;
@@ -13,6 +13,9 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
vm.editItem = editItem;
vm.showAdd = showAdd;
+ vm.mediaItems = [];
+ let selectedIds = [];
+
//check the pre-values for multi-picker
var multiPicker = $scope.model.config.multiPicker && $scope.model.config.multiPicker !== '0' ? true : false;
var onlyImages = $scope.model.config.onlyImages && $scope.model.config.onlyImages !== '0' ? true : false;
@@ -22,9 +25,6 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
$scope.allowAddMedia = false;
function setupViewModel() {
- $scope.mediaItems = [];
- $scope.ids = [];
-
$scope.isMultiPicker = multiPicker;
if ($scope.model.value) {
@@ -77,12 +77,12 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
}
- $scope.mediaItems.push(media);
+ vm.mediaItems.push(media);
if ($scope.model.config.idType === "udi") {
- $scope.ids.push(media.udi);
+ selectedIds.push(media.udi);
} else {
- $scope.ids.push(media.id);
+ selectedIds.push(media.id);
}
});
@@ -92,12 +92,14 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
}
function sync() {
- $scope.model.value = $scope.ids.join();
- removeAllEntriesAction.isDisabled = $scope.ids.length === 0;
+ $scope.model.value = selectedIds.join();
+ removeAllEntriesAction.isDisabled = selectedIds.length === 0;
}
function setDirty() {
- angularHelper.getCurrentForm($scope).$setDirty();
+ if (vm.modelValueForm) {
+ vm.modelValueForm.modelValue.$setDirty();
+ }
}
function reloadUpdatedMediaItems(updatedMediaNodes) {
@@ -105,7 +107,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
// reload. We only reload the images that is already picked but has been updated.
// We have to get the entities from the server because the media
// can be edited without being selected
- $scope.mediaItems.forEach(media => {
+ vm.mediaItems.forEach(media => {
if (updatedMediaNodes.indexOf(media.udi) !== -1) {
media.loading = true;
entityResource.getById(media.udi, "Media")
@@ -155,8 +157,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
}
function remove(index) {
- $scope.mediaItems.splice(index, 1);
- $scope.ids.splice(index, 1);
+ vm.mediaItems.splice(index, 1);
+ selectedIds.splice(index, 1);
sync();
setDirty();
}
@@ -174,7 +176,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
.then(function (mediaEntity) {
// if an image is selecting more than once
// we need to update all the media items
- $scope.mediaItems.forEach(media => {
+ vm.mediaItems.forEach(media => {
if (media.id === model.mediaNode.id) {
angular.extend(media, mediaEntity);
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
@@ -208,13 +210,13 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
}
- $scope.mediaItems.push(media);
+ vm.mediaItems.push(media);
if ($scope.model.config.idType === "udi") {
- $scope.ids.push(media.udi);
+ selectedIds.push(media.udi);
}
else {
- $scope.ids.push(media.id);
+ selectedIds.push(media.id);
}
});
@@ -250,8 +252,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
overlayService.close();
},
submit: function () {
- $scope.mediaItems.length = 0;// AngularJS way to empty the array.
- $scope.ids.length = 0;// AngularJS way to empty the array.
+ vm.mediaItems.length = 0;// AngularJS way to empty the array.
+ selectedIds.length = 0;// AngularJS way to empty the array.
sync();
setDirty();
overlayService.close();
@@ -291,7 +293,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
// TODO: Instead of doing this with a timeout would be better to use a watch like we do in the
// content picker. Then we don't have to worry about setting ids, render models, models, we just set one and let the
// watch do all the rest.
- $scope.ids = $scope.mediaItems.map(media => $scope.model.config.idType === "udi" ? media.udi : media.id);
+ selectedIds = vm.mediaItems.map(media => $scope.model.config.idType === "udi" ? media.udi : media.id);
sync();
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
index c09d7c7613..22a683fa49 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
@@ -1,11 +1,11 @@
-
-
+
+
-
-
+
+
@@ -46,13 +46,15 @@
-
+
-
+
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.controller.js
index 73def3cc65..5362cb1f10 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.controller.js
@@ -18,6 +18,12 @@ function memberGroupPicker($scope, editorService, memberGroupResource){
});
}
+ function setDirty() {
+ if ($scope.modelValueForm) {
+ $scope.modelValueForm.modelValue.$setDirty();
+ }
+ }
+
$scope.openMemberGroupPicker = function() {
var memberGroupPicker = {
multiPicker: true,
@@ -32,6 +38,7 @@ function memberGroupPicker($scope, editorService, memberGroupResource){
if (newGroupIds && newGroupIds.length) {
memberGroupResource.getByIds(newGroupIds).then(function (groups) {
$scope.renderModel = _.union($scope.renderModel, groups);
+ setDirty();
editorService.close();
});
}
@@ -47,10 +54,13 @@ function memberGroupPicker($scope, editorService, memberGroupResource){
editorService.memberGroupPicker(memberGroupPicker);
};
- $scope.remove =function(index){
+ // TODO: I don't believe this is used
+ $scope.remove = function(index){
$scope.renderModel.splice(index, 1);
+ setDirty();
};
+ // TODO: I don't believe this is used
$scope.add = function (item) {
var currIds = _.map($scope.renderModel, function (i) {
return i.id;
@@ -58,11 +68,14 @@ function memberGroupPicker($scope, editorService, memberGroupResource){
if (currIds.indexOf(item) < 0) {
$scope.renderModel.push({ name: item, id: item, icon: 'icon-users' });
+ setDirty();
}
};
+ // TODO: I don't believe this is used
$scope.clear = function() {
$scope.renderModel = [];
+ setDirty();
};
function renderModelIds() {
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html
index b1cafafb0d..5a0788149e 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html
@@ -1,21 +1,22 @@
We have created a bunch of 'how-to' videos, to get you easily started with Umbraco. Learn how to build projects in just a couple of minutes. Easiest CMS in the world.
The Umbraco community is the best of its kind, be sure to visit, and if you have any questions, we're sure that you can get your answers from the community.
diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml
index eda9c33fd3..83ad75acc2 100644
--- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml
+++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml
@@ -280,7 +280,7 @@
Podřízené položkyCílThis translates to the following time on the server:
- What does this mean?]]>
+ What does this mean?]]>Are you sure you want to delete this item?Are you sure you want to delete all items?Property %0% uses editor %1% which is not supported by Nested Content.
@@ -373,7 +373,7 @@
Prohlédnout svůj web- Skrýt
- Jestli se umbraco neotevírá, možná budete muset povolit na tomto webu vyskakovací okna
+ Jestli se Umbraco neotevírá, možná budete muset povolit na tomto webu vyskakovací oknabyl otevřený v novém okněRestartNavštívit
@@ -451,7 +451,7 @@
Položky koše jsou nyní mazány. Nezavírejte, prosím, toto okno, dokud operace probíháKoš je nyní prázdnýOdebrání položek z koše způsobí jejich trvalé odstranění
- regexlib.com má v tuto chvíli nějaké problémy, které jsou mimo naší kontrolu. Omlouváme se za vzniklé nepříjemnosti.]]>
+ regexlib.com má v tuto chvíli nějaké problémy, které jsou mimo naší kontrolu. Omlouváme se za vzniklé nepříjemnosti.]]>Vyhledat regulární výraz pro přidání validace formulářového prvku. Například: 'email, 'PSČ' 'URL'Odstranit makroPole je vyžadování
@@ -837,29 +837,29 @@
Heslo výchozího uživatele bylo úspěšně změněno od doby instalace!
Netřeba nic dalšího dělat. Klikněte na Následující pro pokračování.]]>
Heslo je změněno!Mějte skvělý start, sledujte naše uváděcí videa
- Kliknutím na tlačítko následující (nebo modifikováním umbracoConfigurationStatus v souboru web.config) přijímáte licenci tohoto software tak, jak je uvedena v poli níže. Upozorňujeme, že tato distribuce Umbraca se skládá ze dvou různých licencí, open source MIT licence pro framework a umbraco freeware licence, která pokrývá UI.
+ Kliknutím na tlačítko následující (nebo modifikováním umbracoConfigurationStatus v souboru web.config) přijímáte licenci tohoto software tak, jak je uvedena v poli níže. Upozorňujeme, že tato distribuce Umbraca se skládá ze dvou různých licencí, open source MIT licence pro framework a Umbraco freeware licence, která pokrývá UI.Není nainstalováno.Dotčené soubory a složky
- Další informace o nastavování oprávnění pro umbraco zde
+ Další informace o nastavování oprávnění pro Umbraco zdeMusíte udělit ASP.NET oprávnění měnit následující soubory/složkyVaše nastavení oprávnění je téměř dokonalé!
- Můžete provozovat umbraco bez potíží, ale nebudete smět instalovat balíčky, které jsou doporučené pro plné využívání všech možností umbraca.]]>
+ Můžete provozovat Umbraco bez potíží, ale nebudete smět instalovat balíčky, které jsou doporučené pro plné využívání všech možností umbraca.]]>
Jak to vyřešitKlikněte zde, chcete-li číst textovou verzivýukové video o nastavovaní oprávnění pro složky umbraca, nebo si přečtěte textovou verzi.]]>Vaše nastavení oprávnění může být problém!
- Můžete provozovat umbraco bez potíží, ale nebudete smět vytvářet složky a instalovat balíčky, které jsou doporučené pro plné využívání všech možností umbraca.]]>
+ Můžete provozovat Umbraco bez potíží, ale nebudete smět vytvářet složky a instalovat balíčky, které jsou doporučené pro plné využívání všech možností umbraca.]]>
Vaše nastavení oprívnění není připraveno pro umbraco!
- Abyste mohli umbraco provozovat, budete muset aktualizovat Vaše nastavení oprávnění.]]>
+ Abyste mohli Umbraco provozovat, budete muset aktualizovat Vaše nastavení oprávnění.]]>
Vaše nastavení oprávnění je dokonalé!
@@ -1055,7 +1055,7 @@
Mějte hezký den!
- Zdraví umbraco robot
+ Zdraví Umbraco robot
]]>
Následující jazyky byly změněny %0%Ahoj %0%
@@ -1083,7 +1083,7 @@
Mějte hezký den!
- Zdraví umbraco robot
+ Zdraví Umbraco robot
]]>Byly změněny následující jazyky:
%0%
@@ -1097,7 +1097,7 @@
Vytvořit balíček
- a výběrem balíčku. Balíčky umbraco mají obvykle přípony ".umb" nebo ".zip".
+ a výběrem balíčku. Balíčky Umbraco mají obvykle přípony ".umb" nebo ".zip".
]]>Tím se balíček odstraníPřetáhněte sem pro nahrání
@@ -1328,7 +1328,6 @@
ZáložkyNadřazený typ obsahu povolenTento typ obsahu používá
- jako nadřazený typ obsahu. Záložky z nadřazených typů obsahu nejsou zobrazeny a mohou byt editovány pouze na nadřazených typech obsahu samotnýchNa této záložce nejsou definovány žádné vlastnosti. Pro vytvoření nové vlastnosti klikněte na odkaz "přidat novou vlastnost" nahoře.Vytvořit odpovídající šablonuPřidat ikonu
@@ -1921,7 +1920,7 @@
diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml
index fd69fc7975..264ef45d5f 100644
--- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml
+++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml
@@ -278,7 +278,7 @@
UndersiderÅben i vindueDette oversætter til den følgende tid på serveren:
- Hvad betyder det?]]>
+ Hvad betyder det?]]>Er du sikker på, at du vil slette dette element?Er du sikker på, at du vil slette alle elementer?Egenskaben %0% anvender editoren %1% som ikke er understøttet af Nested Content.
@@ -307,6 +307,7 @@
Vælg dato og klokkeslæt for at udgive og/eller afpublicere indholdet.Opret nyIndsæt fra udklipsmappen
+ Dette element er i papirkurvenOpret en ny indholdsskabelon fra '%0%'
@@ -335,6 +336,17 @@
Alle medlemmerMedlemgrupper har ingen yderligere egenskaber til redigering.
+
+ Kopiering af indholdstypen fejlede
+ Flytning af indholdstypen fejlede
+
+
+ Kopiering af medietypen fejlede
+ Flytning af medietypen fejlede
+
+
+ Kopiering af medlemstypen fejlede
+
Hvor ønsker du at oprette den nye %0%Opret under
@@ -451,7 +463,7 @@
Elementerne i papirkurven slettes. Luk venligst ikke dette vindue mens sletningen foregårPapirkurven er nu tomNår elementer slettes fra papirkurven, slettes de for altid
- regexlib.com's webservice oplever i øjeblikket problemer, vi ikke har kontrol over. Beklager ulejligheden. ]]>
+ regexlib.com's webservice oplever i øjeblikket problemer, vi ikke har kontrol over. Beklager ulejligheden. ]]>Søg efter et regulært udtryk for at tilføje validering til et formularfelt. Eksempel: 'e-mail', 'postnr.', 'URL'Fjern makroObligatorisk
@@ -623,7 +635,6 @@
Du skal stå til venstre for de 2 celler du ønsker at samle!Du kan ikke opdele en celle, som ikke allerede er delt.Denne egenskab er ugyldig
- Feltet %0% bruger editor %1% som ikke er supporteret for ElementTyper.Om
@@ -825,7 +836,7 @@
]]>
Næste for at fortsætte.]]>Databasen er ikke fundet. Kontrollér venligst at informationen i database forbindelsesstrengen i "web.config" filen er korrekt.
-
For at fortsætte bedes du venligst rette "web.config" filen (ved at bruge Visual Studio eller dit favoritprogram), scroll til bunden, tilføj forbindelsesstrengen til din database i feltet som hedder "umbracoDbDSN" og gem filen.
For at fortsætte bedes du venligst rette "web.config" filen (ved at bruge Visual Studio eller dit favoritprogram), scroll til bunden, tilføj forbindelsesstrengen til din database i feltet som hedder "umbracoDbDSN" og gem filen.
]]>
Kontakt venligst din ISP hvis det er nødvendigt. Hvis du installerer på en lokal maskine eller server kan du muligvis få informationerne fra din systemadministrator.]]>Tryk på Opgradér knappen for at opgradere din database til Umbraco %0%
Bare rolig - intet indhold vil blive slettet og alt vil stadig fungere bagefter!
]]>
[%0%] Notificering om %1% udført på %2%Notificeringer
@@ -1590,7 +1601,7 @@ Mange hilsner fra Umbraco robotten
er ikke blevet låst udeKodeordet er ikke blevet ændretGentag dit nye kodeord
- Du kan ændre dit kodeord, som giver dig adgang til Umbraco Back Office ved at udfylde formularen og klikke på knappen 'Skift dit kodeord'
+ Du kan ændre dit kodeord, som giver dig adgang til Umbraco backoffice ved at udfylde formularen og klikke på knappen 'Skift dit kodeord'IndholdskanalOpret endnu en brugerOpret nye brugere for at give dem adgang til Umbraco. Når en ny bruger oprettes, genereres der en adgangskode, som du kan dele med brugeren.
@@ -1667,7 +1678,7 @@ Mange hilsner fra Umbraco robotten
Send invitationTilbage til brugereUmbraco: Invitation
-
Hej %0%, du er blevet inviteret af %1% til Umbraco backoffice.