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

Web ApplicationsCreative 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.

-

www.creativefounds.co.uk

]]> +

www.creativefounds.co.uk

]]>
Umbraco Development @@ -218,7 +218,7 @@ Google Maps - A map macro that you can use within Rich Text Areas Contact Us -

Contact Us on TwitterWe'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

]]> +

Contact Us on TwitterWe'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.

Creative Founds

-

This package was developed by Chris Koiak & Creative Founds

]]> +

This package was developed by Chris Koiak & Creative Founds

]]> 1 diff --git a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs index 99d1c7d1fd..9838036f72 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs @@ -139,7 +139,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Web.BackOffice.Filters { ILogger logger = Services.GetRequiredService>(); IPropertyValidationService propertyValidationService = Services.GetRequiredService(); - UmbracoMapper umbracoMapper = Services.GetRequiredService(); + IUmbracoMapper umbracoMapper = Services.GetRequiredService(); var validator = new ContentSaveModelValidator(logger, propertyValidationService); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs index e07ef305af..25a54fe4ea 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs @@ -287,7 +287,7 @@ AnotherContentFinder public void GetDataEditors() { IEnumerable types = _typeLoader.GetDataEditors(); - Assert.AreEqual(39, types.Count()); + Assert.AreEqual(40, types.Count()); } /// diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Manifest/ManifestParserTests.cs index 550b0e49cd..f91a53b8c8 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Manifest/ManifestParserTests.cs @@ -217,6 +217,8 @@ javascript: ['~/test.js',/*** some note about stuff asd09823-4**09234*/ '~/test2 IDataEditor editor = manifest.PropertyEditors[1]; Assert.IsTrue((editor.Type & EditorType.MacroParameter) > 0); + Assert.IsNotEmpty(editor.DefaultConfiguration); + Assert.AreEqual("some default val", editor.DefaultConfiguration["key1"]); editor = manifest.PropertyEditors[0]; Assert.AreEqual("Test.Test1", editor.Alias); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Mapping/MappingTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Mapping/MappingTests.cs index 6c883dad44..9ccafbb38a 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Mapping/MappingTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Mapping/MappingTests.cs @@ -3,18 +3,41 @@ using System; using System.Collections.Generic; +using System.Data; using System.Linq; using System.Threading; +using Moq; using NUnit.Framework; +using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Mapping; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Core.Scoping; +using PropertyCollection = Umbraco.Cms.Core.Models.PropertyCollection; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping { [TestFixture] public class MappingTests { + private IScopeProvider _scopeProvider; + + [SetUp] + public void MockScopeProvider() + { + var scopeMock = new Mock(); + scopeMock.Setup(x => x.CreateScope( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(Mock.Of); + + _scopeProvider = scopeMock.Object; + } + [Test] public void SimpleMap() { @@ -22,7 +45,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping { new MapperDefinition1(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing1 = new Thing1 { Value = "value" }; Thing2 thing2 = mapper.Map(thing1); @@ -47,7 +70,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping { new MapperDefinition1(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing1A = new Thing1 { Value = "valueA" }; var thing1B = new Thing1 { Value = "valueB" }; @@ -81,7 +104,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping { new MapperDefinition1(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing3 = new Thing3 { Value = "value" }; Thing2 thing2 = mapper.Map(thing3); @@ -106,7 +129,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping { new MapperDefinition2(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); // can map a PropertyCollection var source = new PropertyCollection(); @@ -122,7 +145,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping new MapperDefinition1(), new MapperDefinition3(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); // the mapper currently has a map from Thing1 to Thing2 // because Thing3 inherits from Thing1, it will map a Thing3 instance, @@ -181,7 +204,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping { new MapperDefinition4(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing5 = new Thing5() { @@ -205,7 +228,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping { new MapperDefinition5(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing7 = new Thing7(); @@ -277,14 +300,14 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping private class MapperDefinition1 : IMapDefinition { - public void DefineMaps(UmbracoMapper mapper) => mapper.Define((source, context) => new Thing2(), Map); + public void DefineMaps(IUmbracoMapper mapper) => mapper.Define((source, context) => new Thing2(), Map); private void Map(Thing1 source, Thing2 target, MapperContext context) => target.Value = source.Value; } private class MapperDefinition2 : IMapDefinition { - public void DefineMaps(UmbracoMapper mapper) => + public void DefineMaps(IUmbracoMapper mapper) => mapper.Define((source, context) => new ContentPropertyDto(), Map); private static void Map(IProperty source, ContentPropertyDto target, MapperContext context) @@ -294,7 +317,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping private class MapperDefinition3 : IMapDefinition { - public void DefineMaps(UmbracoMapper mapper) + public void DefineMaps(IUmbracoMapper mapper) { // just some random things so that the mapper contains things mapper.Define(); @@ -307,7 +330,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping private class MapperDefinition4 : IMapDefinition { - public void DefineMaps(UmbracoMapper mapper) + public void DefineMaps(IUmbracoMapper mapper) { mapper.Define((source, context) => new Thing6(), Map); mapper.Define( @@ -324,7 +347,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping private class MapperDefinition5 : IMapDefinition { - public void DefineMaps(UmbracoMapper mapper) + public void DefineMaps(IUmbracoMapper mapper) { mapper.Define((source, context) => new Thing2(), Map1); mapper.Define((source, context) => new Thing8(), Map2); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberManagerTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberManagerTests.cs index c09222bd6f..d263997aab 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberManagerTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberManagerTests.cs @@ -34,11 +34,12 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security public MemberManager CreateSut() { + var scopeProvider = new Mock().Object; _mockMemberService = new Mock(); _fakeMemberStore = new MemberUserStore( _mockMemberService.Object, - new UmbracoMapper(new MapDefinitionCollection(new List())), - new Mock().Object, + new UmbracoMapper(new MapDefinitionCollection(new List()), scopeProvider), + scopeProvider, new IdentityErrorDescriber()); _mockIdentityOptions = new Mock>(); @@ -94,7 +95,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security { PasswordConfig = "testConfig" }; - + //act IdentityResult identityResult = await sut.CreateAsync(fakeUser); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberUserStoreTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberUserStoreTests.cs index 88c79f4bb1..5da4d18bff 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberUserStoreTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/MemberUserStoreTests.cs @@ -33,7 +33,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security return new MemberUserStore( _mockMemberService.Object, - new UmbracoMapper(new MapDefinitionCollection(new List())), + new UmbracoMapper(new MapDefinitionCollection(new List()), mockScopeProvider.Object), mockScopeProvider.Object, new IdentityErrorDescriber()); } diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.ModelsBuilder.Embedded/BuilderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.ModelsBuilder.Embedded/BuilderTests.cs index 174f099373..0c1266d56e 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.ModelsBuilder.Embedded/BuilderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.ModelsBuilder.Embedded/BuilderTests.cs @@ -97,7 +97,7 @@ namespace Umbraco.Cms.Web.Common.PublishedModels [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")] [ImplementPropertyType(""prop1"")] - public string Prop1 => this.Value(_publishedValueFallback, ""prop1""); + public virtual string Prop1 => this.Value(_publishedValueFallback, ""prop1""); } } "; @@ -203,7 +203,7 @@ namespace Umbraco.Cms.Web.Common.PublishedModels [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")] [ImplementPropertyType(""foo"")] - public global::System.Collections.Generic.IEnumerable Foo => this.Value>(_publishedValueFallback, ""foo""); + public virtual global::System.Collections.Generic.IEnumerable Foo => this.Value>(_publishedValueFallback, ""foo""); } } "; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/MemberControllerUnitTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/MemberControllerUnitTests.cs index 321f34f517..d363697a44 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/MemberControllerUnitTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/MemberControllerUnitTests.cs @@ -46,7 +46,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Controllers [TestFixture] public class MemberControllerUnitTests { - private UmbracoMapper _mapper; + private IUmbracoMapper _mapper; [Test] [AutoMoqData] @@ -503,7 +503,15 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Controllers globalSettings, new Mock().Object) }); - _mapper = new UmbracoMapper(map); + var scopeProvider = Mock.Of(x => x.CreateScope( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()) == Mock.Of()); + + _mapper = new UmbracoMapper(map, scopeProvider); return new MemberController( new DefaultCultureDictionary( @@ -523,13 +531,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Controllers backOfficeSecurityAccessor, new ConfigurationEditorJsonSerializer(), passwordChanger, - Mock.Of(x => x.CreateScope( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny()) == Mock.Of())); + scopeProvider + ); } /// diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index a45d4b290e..3fc1670fad 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -158,7 +158,7 @@ namespace Umbraco.Tests.Testing protected IMapperCollection Mappers => Factory.GetRequiredService(); - protected UmbracoMapper Mapper => Factory.GetRequiredService(); + protected IUmbracoMapper Mapper => Factory.GetRequiredService(); protected IHttpContextAccessor HttpContextAccessor => Factory.GetRequiredService(); protected IContentService ContentService => Factory.GetRequiredService(); protected IRuntimeState RuntimeState => MockRuntimeState(RuntimeLevel.Run); diff --git a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs index 5740c8c1a6..707c486f3e 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs @@ -57,7 +57,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IBackOfficeSignInManager _signInManager; private readonly IUserService _userService; private readonly ILocalizedTextService _textService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly GlobalSettings _globalSettings; private readonly SecuritySettings _securitySettings; private readonly ILogger _logger; @@ -78,7 +78,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IBackOfficeSignInManager signInManager, IUserService userService, ILocalizedTextService textService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IOptions globalSettings, IOptions securitySettings, ILogger logger, diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs index 3aa3239dbc..6ec2abc60e 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs @@ -50,6 +50,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IImageUrlGenerator _imageUrlGenerator; private readonly PreviewRoutes _previewRoutes; private readonly IEmailSender _emailSender; + private readonly MemberPasswordConfigurationSettings _memberPasswordConfigurationSettings; public BackOfficeServerVariables( LinkGenerator linkGenerator, @@ -67,7 +68,8 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IBackOfficeExternalLoginProviders externalLogins, IImageUrlGenerator imageUrlGenerator, PreviewRoutes previewRoutes, - IEmailSender emailSender) + IEmailSender emailSender, + IOptions memberPasswordConfigurationSettings) { _linkGenerator = linkGenerator; _runtimeState = runtimeState; @@ -85,6 +87,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers _imageUrlGenerator = imageUrlGenerator; _previewRoutes = previewRoutes; _emailSender = emailSender; + _memberPasswordConfigurationSettings = memberPasswordConfigurationSettings.Value; } /// @@ -97,7 +100,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers var keepOnlyKeys = new Dictionary { {"umbracoUrls", new[] {"authenticationApiBaseUrl", "serverVarsJs", "externalLoginsUrl", "currentUserApiBaseUrl", "previewHubUrl", "iconApiBaseUrl"}}, - {"umbracoSettings", new[] {"allowPasswordReset", "imageFileTypes", "maxFileSize", "loginBackgroundImage", "loginLogoImage", "canSendRequiredEmail", "usernameIsEmail"}}, + {"umbracoSettings", new[] {"allowPasswordReset", "imageFileTypes", "maxFileSize", "loginBackgroundImage", "loginLogoImage", "canSendRequiredEmail", "usernameIsEmail", "minimumPasswordLength", "minimumPasswordNonAlphaNum"}}, {"application", new[] {"applicationPath", "cacheBuster"}}, {"isDebuggingEnabled", new string[] { }}, {"features", new [] {"disabledFeatures"}} @@ -408,6 +411,8 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers {"showUserInvite", _emailSender.CanSendRequiredEmail()}, {"canSendRequiredEmail", _emailSender.CanSendRequiredEmail()}, {"showAllowSegmentationForDocumentTypes", false}, + {"minimumPasswordLength", _memberPasswordConfigurationSettings.RequiredLength}, + {"minimumPasswordNonAlphaNum", _memberPasswordConfigurationSettings.GetMinNonAlphaNumericChars()}, } }, { diff --git a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs index 7803f9cafb..710fb5aeb8 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs @@ -42,7 +42,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly ILocalizedTextService _localizedTextService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IShortStringHelper _shortStringHelper; private readonly GlobalSettings _globalSettings; @@ -52,7 +52,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IFileService fileService, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, ILocalizedTextService localizedTextService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IShortStringHelper shortStringHelper, IOptions globalSettings) { @@ -668,7 +668,10 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private bool IsDirectory(string path) { var dirInfo = new DirectoryInfo(path); - return dirInfo.Attributes == FileAttributes.Directory; + + // If you turn off indexing in Windows this will have the attribute: + // `FileAttributes.Directory | FileAttributes.NotContentIndexed` + return (dirInfo.Attributes & FileAttributes.Directory) != 0; } // this is an internal class for passing stylesheet data from the client to the controller while editing diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs index 2c8d4bc385..dcc5753524 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs @@ -54,14 +54,14 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IUserService _userService; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; private readonly IContentTypeService _contentTypeService; - private readonly UmbracoMapper _umbracoMapper; - private readonly IPublishedUrlProvider _publishedUrlProvider; + private readonly IUmbracoMapper _umbracoMapper; + private readonly IPublishedUrlProvider _publishedUrlProvider; private readonly IDomainService _domainService; private readonly IDataTypeService _dataTypeService; - private readonly ILocalizationService _localizationService; + private readonly ILocalizationService _localizationService; private readonly IFileService _fileService; private readonly INotificationService _notificationService; - private readonly ActionCollection _actionCollection; + private readonly ActionCollection _actionCollection; private readonly ISqlContext _sqlContext; private readonly IAuthorizationService _authorizationService; private readonly Lazy> _allLangs; @@ -80,7 +80,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IUserService userService, IBackOfficeSecurityAccessor backofficeSecurityAccessor, IContentTypeService contentTypeService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider, IDomainService domainService, IDataTypeService dataTypeService, @@ -2391,8 +2391,8 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers return new ValidationErrorResult(notificationModel); } - - + + } } diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs index 4f90f2759d..79ea6f6329 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs @@ -44,7 +44,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IEntityXmlSerializer _serializer; private readonly PropertyEditorCollection _propertyEditors; private readonly IContentTypeService _contentTypeService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; private readonly IDataTypeService _dataTypeService; private readonly IShortStringHelper _shortStringHelper; @@ -61,7 +61,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, ILocalizedTextService localizedTextService, IEntityXmlSerializer serializer, PropertyEditorCollection propertyEditors, diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeControllerBase.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeControllerBase.cs index b26db7f8fc..46c75e5186 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeControllerBase.cs @@ -38,7 +38,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, ILocalizedTextService localizedTextService) { _editorValidatorCollection = editorValidatorCollection ?? throw new ArgumentNullException(nameof(editorValidatorCollection)); @@ -54,7 +54,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public IContentTypeService ContentTypeService { get; } public IMediaTypeService MediaTypeService { get; } public IMemberTypeService MemberTypeService { get; } - public UmbracoMapper UmbracoMapper { get; } + public IUmbracoMapper UmbracoMapper { get; } public ILocalizedTextService LocalizedTextService { get; } /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs index 54a17bc951..080f84009a 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs @@ -45,7 +45,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IImageUrlGenerator _imageUrlGenerator; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; private readonly IUserService _userService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IBackOfficeUserManager _backOfficeUserManager; private readonly ILoggerFactory _loggerFactory; private readonly ILocalizedTextService _localizedTextService; @@ -60,7 +60,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IImageUrlGenerator imageUrlGenerator, IBackOfficeSecurityAccessor backofficeSecurityAccessor, IUserService userService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IBackOfficeUserManager backOfficeUserManager, ILoggerFactory loggerFactory, ILocalizedTextService localizedTextService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs index 3d532c4d94..9f020125bb 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs @@ -41,7 +41,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly PropertyEditorCollection _propertyEditors; private readonly IDataTypeService _dataTypeService; private readonly ContentSettings _contentSettings; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly PropertyEditorCollection _propertyEditorCollection; private readonly IContentTypeService _contentTypeService; private readonly IMediaTypeService _mediaTypeService; @@ -54,7 +54,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, IOptions contentSettings, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, PropertyEditorCollection propertyEditorCollection, IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs index 2d49c97f2a..980d08c2e2 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs @@ -40,7 +40,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; private readonly GlobalSettings _globalSettings; private readonly ILocalizedTextService _localizedTextService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; public DictionaryController( ILogger logger, @@ -48,7 +48,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IBackOfficeSecurityAccessor backofficeSecurityAccessor, IOptions globalSettings, ILocalizedTextService localizedTextService, - UmbracoMapper umbracoMapper + IUmbracoMapper umbracoMapper ) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); diff --git a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs index 0867a613a5..2aa15e8ae9 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs @@ -58,7 +58,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; private readonly IPublishedUrlProvider _publishedUrlProvider; private readonly IContentService _contentService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IDataTypeService _dataTypeService; private readonly ISqlContext _sqlContext; private readonly ILocalizedTextService _localizedTextService; @@ -80,7 +80,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IBackOfficeSecurityAccessor backofficeSecurityAccessor, IPublishedUrlProvider publishedUrlProvider, IContentService contentService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IDataTypeService dataTypeService, ISqlContext sqlContext, ILocalizedTextService localizedTextService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/ExamineManagementController.cs b/src/Umbraco.Web.BackOffice/Controllers/ExamineManagementController.cs index e9d2795ade..0408faee29 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ExamineManagementController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ExamineManagementController.cs @@ -26,7 +26,6 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IAppPolicyCache _runtimeCache; private readonly IndexRebuilder _indexRebuilder; - public ExamineManagementController(IExamineManager examineManager, ILogger logger, IIOHelper ioHelper, IIndexDiagnosticsFactory indexDiagnosticsFactory, AppCaches appCaches, IndexRebuilder indexRebuilder) @@ -81,14 +80,11 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers { Id = x.Id, Score = x.Score, - //order the values by key - Values = new Dictionary(x.Values.OrderBy(y => y.Key).ToDictionary(y => y.Key, y => y.Value)) + Values = x.AllValues.OrderBy(y => y.Key).ToDictionary(y => y.Key, y => y.Value) }) }; } - - /// /// Check if the index has been rebuilt /// @@ -116,7 +112,6 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers return found != null ? null : CreateModel(index); - } /// @@ -175,11 +170,13 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers var indexDiag = _indexDiagnosticsFactory.Create(index); var isHealth = indexDiag.IsHealthy(); + var properties = new Dictionary { [nameof(IIndexDiagnostics.DocumentCount)] = indexDiag.DocumentCount, [nameof(IIndexDiagnostics.FieldCount)] = indexDiag.FieldCount, }; + foreach (var p in indexDiag.Metadata) properties[p.Key] = p.Value; @@ -191,7 +188,6 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers CanRebuild = _indexRebuilder.CanRebuild(index) }; - return indexerModel; } @@ -204,7 +200,6 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers return new OkResult(); } - //if we didn't find anything try to find it by an explicitly declared searcher if (_examineManager.TryGetSearcher(searcherName, out searcher)) return new OkResult(); diff --git a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs index b1090c9b8e..8465e7a454 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs @@ -27,11 +27,11 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public class LanguageController : UmbracoAuthorizedJsonController { private readonly ILocalizationService _localizationService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly GlobalSettings _globalSettings; public LanguageController(ILocalizationService localizationService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IOptions globalSettings) { _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); diff --git a/src/Umbraco.Web.BackOffice/Controllers/LogController.cs b/src/Umbraco.Web.BackOffice/Controllers/LogController.cs index 5c01f621f9..2d8f2fa82b 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/LogController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/LogController.cs @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IMediaFileSystem _mediaFileSystem; private readonly IImageUrlGenerator _imageUrlGenerator; private readonly IAuditService _auditService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; private readonly IUserService _userService; private readonly AppCaches _appCaches; @@ -37,7 +37,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IMediaFileSystem mediaFileSystem, IImageUrlGenerator imageUrlGenerator, IAuditService auditService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IBackOfficeSecurityAccessor backofficeSecurityAccessor, IUserService userService, AppCaches appCaches, diff --git a/src/Umbraco.Web.BackOffice/Controllers/MacroRenderingController.cs b/src/Umbraco.Web.BackOffice/Controllers/MacroRenderingController.cs index 460bd4a8a8..dc3f21f63d 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MacroRenderingController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MacroRenderingController.cs @@ -30,13 +30,13 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IShortStringHelper _shortStringHelper; private readonly ISiteDomainHelper _siteDomainHelper; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IUmbracoComponentRenderer _componentRenderer; private readonly IVariationContextAccessor _variationContextAccessor; public MacroRenderingController( - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IUmbracoComponentRenderer componentRenderer, IVariationContextAccessor variationContextAccessor, IMacroService macroService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs b/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs index 001b19fb1c..a7ec619ae1 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs @@ -38,7 +38,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; private readonly ILogger _logger; private readonly IHostingEnvironment _hostingEnvironment; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; public MacrosController( ParameterEditorCollection parameterEditorCollection, @@ -47,7 +47,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IBackOfficeSecurityAccessor backofficeSecurityAccessor, ILogger logger, IHostingEnvironment hostingEnvironment, - UmbracoMapper umbracoMapper + IUmbracoMapper umbracoMapper ) { _parameterEditorCollection = parameterEditorCollection ?? throw new ArgumentNullException(nameof(parameterEditorCollection)); diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs index 3bb23e47e9..9d176277ec 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs @@ -60,7 +60,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IMediaService _mediaService; private readonly IEntityService _entityService; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IDataTypeService _dataTypeService; private readonly ILocalizedTextService _localizedTextService; private readonly ISqlContext _sqlContext; @@ -83,7 +83,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IMediaService mediaService, IEntityService entityService, IBackOfficeSecurityAccessor backofficeSecurityAccessor, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IDataTypeService dataTypeService, ISqlContext sqlContext, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs index 36591316d5..5f61d1b1c1 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs @@ -37,7 +37,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IMediaService _mediaService; private readonly IMediaTypeService _mediaTypeService; private readonly IShortStringHelper _shortStringHelper; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; public MediaTypeController(ICultureDictionary cultureDictionary, @@ -45,7 +45,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, IEntityService entityService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs index 567303e150..3d435322b8 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs @@ -49,7 +49,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public class MemberController : ContentControllerBase { private readonly PropertyEditorCollection _propertyEditors; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IMemberService _memberService; private readonly IMemberTypeService _memberTypeService; private readonly IMemberManager _memberManager; @@ -85,7 +85,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IEventMessagesFactory eventMessages, ILocalizedTextService localizedTextService, PropertyEditorCollection propertyEditors, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IMemberService memberService, IMemberTypeService memberTypeService, IMemberManager memberManager, diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs index 88825c0d9a..845e157650 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs @@ -24,12 +24,12 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public class MemberGroupController : UmbracoAuthorizedJsonController { private readonly IMemberGroupService _memberGroupService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly ILocalizedTextService _localizedTextService; public MemberGroupController( IMemberGroupService memberGroupService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, ILocalizedTextService localizedTextService) { _memberGroupService = memberGroupService ?? throw new ArgumentNullException(nameof(memberGroupService)); diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs index 57cb18250c..133581208e 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs @@ -30,7 +30,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IMemberTypeService _memberTypeService; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; private readonly IShortStringHelper _shortStringHelper; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly ILocalizedTextService _localizedTextService; public MemberTypeController( @@ -39,7 +39,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, ILocalizedTextService localizedTextService, IBackOfficeSecurityAccessor backofficeSecurityAccessor, IShortStringHelper shortStringHelper) diff --git a/src/Umbraco.Web.BackOffice/Controllers/PublicAccessController.cs b/src/Umbraco.Web.BackOffice/Controllers/PublicAccessController.cs index 15859660f7..d26736bfdb 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/PublicAccessController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/PublicAccessController.cs @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IPublicAccessService _publicAccessService; private readonly IEntityService _entityService; private readonly IMemberService _memberService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IMemberRoleManager _memberRoleManager; public PublicAccessController( @@ -35,7 +35,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IContentService contentService, IEntityService entityService, IMemberService memberService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IMemberRoleManager memberRoleManager) { _contentService = contentService; diff --git a/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs b/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs index 3131000703..99f5e03174 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs @@ -28,7 +28,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IOptionsMonitor _webRoutingSettings; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; private readonly IRedirectUrlService _redirectUrlService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IConfigManipulator _configManipulator; public RedirectUrlManagementController( @@ -36,7 +36,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IOptionsMonitor webRoutingSettings, IBackOfficeSecurityAccessor backofficeSecurityAccessor, IRedirectUrlService redirectUrlService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IConfigManipulator configManipulator) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); diff --git a/src/Umbraco.Web.BackOffice/Controllers/RelationController.cs b/src/Umbraco.Web.BackOffice/Controllers/RelationController.cs index 882b26e4e4..e9f6d6cb63 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/RelationController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/RelationController.cs @@ -17,10 +17,10 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers [Authorize(Policy = AuthorizationPolicies.SectionAccessContent)] public class RelationController : UmbracoAuthorizedJsonController { - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IRelationService _relationService; - public RelationController(UmbracoMapper umbracoMapper, + public RelationController(IUmbracoMapper umbracoMapper, IRelationService relationService) { _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); diff --git a/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs index e979d02794..187d59b446 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs @@ -28,13 +28,13 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public class RelationTypeController : BackOfficeNotificationsController { private readonly ILogger _logger; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IRelationService _relationService; private readonly IShortStringHelper _shortStringHelper; public RelationTypeController( ILogger logger, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IRelationService relationService, IShortStringHelper shortStringHelper) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs b/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs index 6515c7055c..dfd1c8c973 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs @@ -31,14 +31,14 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly ILocalizedTextService _localizedTextService; private readonly ISectionService _sectionService; private readonly ITreeService _treeService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; public SectionController( IBackOfficeSecurityAccessor backofficeSecurityAccessor, ILocalizedTextService localizedTextService, IDashboardService dashboardService, ISectionService sectionService, ITreeService treeService, - UmbracoMapper umbracoMapper, IControllerFactory controllerFactory, + IUmbracoMapper umbracoMapper, IControllerFactory controllerFactory, IActionDescriptorCollectionProvider actionDescriptorCollectionProvider) { _backofficeSecurityAccessor = backofficeSecurityAccessor; diff --git a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs index 91395431e9..0a800693f8 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs @@ -22,12 +22,12 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public class TemplateController : BackOfficeNotificationsController { private readonly IFileService _fileService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IShortStringHelper _shortStringHelper; public TemplateController( IFileService fileService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IShortStringHelper shortStringHelper) { _fileService = fileService ?? throw new ArgumentNullException(nameof(fileService)); diff --git a/src/Umbraco.Web.BackOffice/Controllers/UserGroupsController.cs b/src/Umbraco.Web.BackOffice/Controllers/UserGroupsController.cs index b663eff6c7..f5cdb94d37 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UserGroupsController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UserGroupsController.cs @@ -29,7 +29,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IEntityService _entityService; private readonly IMediaService _mediaService; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly ILocalizedTextService _localizedTextService; private readonly IShortStringHelper _shortStringHelper; private readonly AppCaches _appCaches; @@ -40,7 +40,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IEntityService entityService, IMediaService mediaService, IBackOfficeSecurityAccessor backofficeSecurityAccessor, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, AppCaches appCaches) diff --git a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs index 5cd20d9f9a..6e7e5f2ed1 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs @@ -64,7 +64,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IShortStringHelper _shortStringHelper; private readonly IUserService _userService; private readonly ILocalizedTextService _localizedTextService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly GlobalSettings _globalSettings; private readonly IBackOfficeUserManager _userManager; private readonly ILoggerFactory _loggerFactory; @@ -87,7 +87,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IShortStringHelper shortStringHelper, IUserService userService, ILocalizedTextService localizedTextService, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IOptions globalSettings, IBackOfficeUserManager backOfficeUserManager, ILoggerFactory loggerFactory, diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs index e8eea703a0..54956184ac 100644 --- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs @@ -101,14 +101,6 @@ namespace Umbraco.Extensions }); builder.Services.AddUnique(); - builder.Services.AddUnique(_ => - { - var sanitizer = new HtmlSanitizer(); - sanitizer.AllowedAttributes.UnionWith(Constants.SvgSanitizer.Attributes); - sanitizer.AllowedCssProperties.UnionWith(Constants.SvgSanitizer.Attributes); - sanitizer.AllowedTags.UnionWith(Constants.SvgSanitizer.Tags); - return sanitizer; - }); builder.Services.AddUnique(); return builder; diff --git a/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs index 36dd11e9e5..39432703a7 100644 --- a/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Web.BackOffice.Filters private class CheckIfUserTicketDataIsStaleFilter : IAsyncActionFilter { private readonly IRequestCache _requestCache; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IUserService _userService; private readonly IEntityService _entityService; private readonly ILocalizedTextService _localizedTextService; @@ -46,7 +46,7 @@ namespace Umbraco.Cms.Web.BackOffice.Filters public CheckIfUserTicketDataIsStaleFilter( IRequestCache requestCache, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IUserService userService, IEntityService entityService, ILocalizedTextService localizedTextService, diff --git a/src/Umbraco.Web.BackOffice/Filters/DataTypeValidateAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/DataTypeValidateAttribute.cs index 24c15e8a7f..b912c982a1 100644 --- a/src/Umbraco.Web.BackOffice/Filters/DataTypeValidateAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/DataTypeValidateAttribute.cs @@ -27,9 +27,9 @@ namespace Umbraco.Cms.Web.BackOffice.Filters { private readonly IDataTypeService _dataTypeService; private readonly PropertyEditorCollection _propertyEditorCollection; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; - public DataTypeValidateFilter(IDataTypeService dataTypeService, PropertyEditorCollection propertyEditorCollection, UmbracoMapper umbracoMapper) + public DataTypeValidateFilter(IDataTypeService dataTypeService, PropertyEditorCollection propertyEditorCollection, IUmbracoMapper umbracoMapper) { _dataTypeService = dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService)); _propertyEditorCollection = propertyEditorCollection ?? throw new ArgumentNullException(nameof(propertyEditorCollection)); diff --git a/src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs b/src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs index c56e277509..8396d77f1c 100644 --- a/src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs +++ b/src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs @@ -96,7 +96,7 @@ namespace Umbraco.Cms.Web.BackOffice.Mapping _contentVariantMapper = new ContentVariantMapper(_localizationService, localizedTextService); } - public void DefineMaps(UmbracoMapper mapper) + public void DefineMaps(IUmbracoMapper mapper) { mapper.Define((source, context) => new ContentPropertyCollectionDto(), Map); mapper.Define((source, context) => new ContentItemDisplay(), Map); diff --git a/src/Umbraco.Web.BackOffice/Mapping/MediaMapDefinition.cs b/src/Umbraco.Web.BackOffice/Mapping/MediaMapDefinition.cs index 2b654fff48..03bca1ee70 100644 --- a/src/Umbraco.Web.BackOffice/Mapping/MediaMapDefinition.cs +++ b/src/Umbraco.Web.BackOffice/Mapping/MediaMapDefinition.cs @@ -41,7 +41,7 @@ namespace Umbraco.Cms.Web.BackOffice.Mapping _tabsAndPropertiesMapper = new TabsAndPropertiesMapper(cultureDictionary, localizedTextService, contentTypeBaseServiceProvider); } - public void DefineMaps(UmbracoMapper mapper) + public void DefineMaps(IUmbracoMapper mapper) { mapper.Define((source, context) => new ContentPropertyCollectionDto(), Map); mapper.Define((source, context) => new MediaItemDisplay(), Map); diff --git a/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs b/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs index 4b2837d9b8..fc1457798a 100644 --- a/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs +++ b/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs @@ -28,7 +28,7 @@ namespace Umbraco.Cms.Web.BackOffice.Mapping _tabsAndPropertiesMapper = tabsAndPropertiesMapper; } - public void DefineMaps(UmbracoMapper mapper) + public void DefineMaps(IUmbracoMapper mapper) { mapper.Define((source, context) => new MemberDisplay(), Map); mapper.Define((source, context) => new MemberBasic(), Map); diff --git a/src/Umbraco.Web.BackOffice/ModelBinders/BlueprintItemBinder.cs b/src/Umbraco.Web.BackOffice/ModelBinders/BlueprintItemBinder.cs index eb88cf3748..124d4acc62 100644 --- a/src/Umbraco.Web.BackOffice/ModelBinders/BlueprintItemBinder.cs +++ b/src/Umbraco.Web.BackOffice/ModelBinders/BlueprintItemBinder.cs @@ -11,7 +11,7 @@ namespace Umbraco.Cms.Web.BackOffice.ModelBinders { private readonly IContentService _contentService; - public BlueprintItemBinder(IJsonSerializer jsonSerializer, UmbracoMapper umbracoMapper, IContentService contentService, IContentTypeService contentTypeService, IHostingEnvironment hostingEnvironment) : base(jsonSerializer, umbracoMapper, contentService, contentTypeService, hostingEnvironment) + public BlueprintItemBinder(IJsonSerializer jsonSerializer, IUmbracoMapper umbracoMapper, IContentService contentService, IContentTypeService contentTypeService, IHostingEnvironment hostingEnvironment) : base(jsonSerializer, umbracoMapper, contentService, contentTypeService, hostingEnvironment) { _contentService = contentService; } diff --git a/src/Umbraco.Web.BackOffice/ModelBinders/ContentItemBinder.cs b/src/Umbraco.Web.BackOffice/ModelBinders/ContentItemBinder.cs index 82b612c98c..81451399b9 100644 --- a/src/Umbraco.Web.BackOffice/ModelBinders/ContentItemBinder.cs +++ b/src/Umbraco.Web.BackOffice/ModelBinders/ContentItemBinder.cs @@ -19,7 +19,7 @@ namespace Umbraco.Cms.Web.BackOffice.ModelBinders internal class ContentItemBinder : IModelBinder { private readonly IJsonSerializer _jsonSerializer; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IContentService _contentService; private readonly IContentTypeService _contentTypeService; private readonly IHostingEnvironment _hostingEnvironment; @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Web.BackOffice.ModelBinders public ContentItemBinder( IJsonSerializer jsonSerializer, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IContentService contentService, IContentTypeService contentTypeService, IHostingEnvironment hostingEnvironment) @@ -79,7 +79,7 @@ namespace Umbraco.Cms.Web.BackOffice.ModelBinders bindingContext.Result = ModelBindingResult.Success(model); } - internal static void BindModel(ContentItemSave model, IContent persistedContent, ContentModelBinderHelper modelBinderHelper, UmbracoMapper umbracoMapper) + internal static void BindModel(ContentItemSave model, IContent persistedContent, ContentModelBinderHelper modelBinderHelper, IUmbracoMapper umbracoMapper) { model.PersistedContent =persistedContent; diff --git a/src/Umbraco.Web.BackOffice/ModelBinders/MediaItemBinder.cs b/src/Umbraco.Web.BackOffice/ModelBinders/MediaItemBinder.cs index 7cd4bceaa8..dc785034d6 100644 --- a/src/Umbraco.Web.BackOffice/ModelBinders/MediaItemBinder.cs +++ b/src/Umbraco.Web.BackOffice/ModelBinders/MediaItemBinder.cs @@ -19,12 +19,12 @@ namespace Umbraco.Cms.Web.BackOffice.ModelBinders private readonly IJsonSerializer _jsonSerializer; private readonly IHostingEnvironment _hostingEnvironment; private readonly IMediaService _mediaService; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IMediaTypeService _mediaTypeService; private readonly ContentModelBinderHelper _modelBinderHelper; - public MediaItemBinder(IJsonSerializer jsonSerializer, IHostingEnvironment hostingEnvironment, IMediaService mediaService, UmbracoMapper umbracoMapper, IMediaTypeService mediaTypeService) + public MediaItemBinder(IJsonSerializer jsonSerializer, IHostingEnvironment hostingEnvironment, IMediaService mediaService, IUmbracoMapper umbracoMapper, IMediaTypeService mediaTypeService) { _jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer)); _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); diff --git a/src/Umbraco.Web.BackOffice/ModelBinders/MemberBinder.cs b/src/Umbraco.Web.BackOffice/ModelBinders/MemberBinder.cs index 2221b907a6..ae3ac6e801 100644 --- a/src/Umbraco.Web.BackOffice/ModelBinders/MemberBinder.cs +++ b/src/Umbraco.Web.BackOffice/ModelBinders/MemberBinder.cs @@ -24,7 +24,7 @@ namespace Umbraco.Cms.Web.BackOffice.ModelBinders private readonly IJsonSerializer _jsonSerializer; private readonly IHostingEnvironment _hostingEnvironment; private readonly IShortStringHelper _shortStringHelper; - private readonly UmbracoMapper _umbracoMapper; + private readonly IUmbracoMapper _umbracoMapper; private readonly IMemberService _memberService; private readonly IMemberTypeService _memberTypeService; @@ -32,7 +32,7 @@ namespace Umbraco.Cms.Web.BackOffice.ModelBinders IJsonSerializer jsonSerializer, IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper, - UmbracoMapper umbracoMapper, + IUmbracoMapper umbracoMapper, IMemberService memberService, IMemberTypeService memberTypeService) { diff --git a/src/Umbraco.Web.BackOffice/Services/IconService.cs b/src/Umbraco.Web.BackOffice/Services/IconService.cs index 96b7391413..a1d634f41b 100644 --- a/src/Umbraco.Web.BackOffice/Services/IconService.cs +++ b/src/Umbraco.Web.BackOffice/Services/IconService.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using Ganss.XSS; using Microsoft.Extensions.Options; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Cache; @@ -18,17 +17,15 @@ namespace Umbraco.Cms.Web.BackOffice.Services { private readonly IOptions _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; - private readonly IHtmlSanitizer _htmlSanitizer; private readonly IAppPolicyCache _cache; public IconService( IOptions globalSettings, IHostingEnvironment hostingEnvironment, - IHtmlSanitizer htmlSanitizer, AppCaches appCaches) + AppCaches appCaches) { _globalSettings = globalSettings; _hostingEnvironment = hostingEnvironment; - _htmlSanitizer = htmlSanitizer; _cache = appCaches.RuntimeCache; } @@ -79,12 +76,11 @@ namespace Umbraco.Cms.Web.BackOffice.Services try { var svgContent = System.IO.File.ReadAllText(iconPath); - var sanitizedString = _htmlSanitizer.Sanitize(svgContent); var svg = new IconModel { Name = iconName, - SvgString = sanitizedString + SvgString = svgContent }; return svg; diff --git a/src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs index 17b1722e8c..a307a67d23 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs @@ -376,7 +376,6 @@ namespace Umbraco.Cms.Web.BackOffice.Trees "icon-trash", RecycleBinSmells, queryStrings.GetRequiredValue("application") + TreeAlias.EnsureStartsWith('/') + "/recyclebin")); - } return nodes; diff --git a/src/Umbraco.Web.Common/Extensions/FormCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/FormCollectionExtensions.cs index d555446a67..6a35f43758 100644 --- a/src/Umbraco.Web.Common/Extensions/FormCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/FormCollectionExtensions.cs @@ -22,8 +22,8 @@ namespace Umbraco.Extensions if (items.Any() == false) return ""; var builder = new StringBuilder(); - foreach (var i in items.Where(i => keysToIgnore.InvariantContains(i.Key) == false)) - builder.Append(string.Format("{0}={1}&", i.Key, i.Value)); + foreach (var (key, value) in items.Where(i => keysToIgnore.InvariantContains(i.Key) == false)) + builder.Append($"{key}={value}&"); return builder.ToString().TrimEnd(Constants.CharArrays.Ampersand); } diff --git a/src/Umbraco.Web.Common/ModelsBuilder/PureLiveModelFactory.cs b/src/Umbraco.Web.Common/ModelsBuilder/PureLiveModelFactory.cs index bd4ccf3d60..ef8f54c1c1 100644 --- a/src/Umbraco.Web.Common/ModelsBuilder/PureLiveModelFactory.cs +++ b/src/Umbraco.Web.Common/ModelsBuilder/PureLiveModelFactory.cs @@ -774,7 +774,7 @@ namespace Umbraco.Cms.Web.Common.ModelsBuilder } public void Stop(bool immediate) - { + { _watcher.EnableRaisingEvents = false; _watcher.Dispose(); _locker.Dispose(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js index 392199738b..9986b9ce8a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js @@ -16,7 +16,7 @@ function UmbLoginController($scope, $location, currentUserResource, formHelper, mediaHelper, umbRequestHelper, Upload, localizationService, userService, externalLoginInfo, externalLoginInfoService, - resetPasswordCodeInfo, $timeout, authResource, $q, $route) { + resetPasswordCodeInfo, authResource, $q) { const vm = this; @@ -72,6 +72,7 @@ vm.loginSubmit = loginSubmit; vm.requestPasswordResetSubmit = requestPasswordResetSubmit; vm.setPasswordSubmit = setPasswordSubmit; + vm.newPasswordKeyUp = newPasswordKeyUp; vm.labels = {}; localizationService.localizeMany([ vm.usernameIsEmail ? "general_email" : "general_username", @@ -362,6 +363,9 @@ }); } + function newPasswordKeyUp(event) { + vm.passwordVal = event.target.value; + } //// diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbpasswordtip.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbpasswordtip.directive.js new file mode 100644 index 0000000000..86e1d3d32f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbpasswordtip.directive.js @@ -0,0 +1,71 @@ +(function () { + 'use strict'; + + angular + .module('umbraco.directives') + .component('umbPasswordTip', { + controller: UmbPasswordTipController, + controllerAs: 'vm', + template: + '{{vm.passwordTip}}', + bindings: { + passwordVal: "<", + minPwdLength: "<", + minPwdNonAlphaNum: "<" + } + }); + + function UmbPasswordTipController(localizationService) { + + let defaultMinPwdLength = Umbraco.Sys.ServerVariables.umbracoSettings.minimumPasswordLength; + let defaultMinPwdNonAlphaNum = Umbraco.Sys.ServerVariables.umbracoSettings.minimumPasswordNonAlphaNum; + + var vm = this; + vm.$onInit = onInit; + vm.$onChanges = onChanges; + + function onInit() { + if (vm.minPwdLength === undefined) { + vm.minPwdLength = defaultMinPwdLength; + } + + if (vm.minPwdNonAlphaNum === undefined) { + vm.minPwdNonAlphaNum = defaultMinPwdNonAlphaNum; + } + + if (vm.minPwdNonAlphaNum > 0) { + localizationService.localize('user_newPasswordFormatNonAlphaTip', [vm.minPwdNonAlphaNum]).then(data => { + vm.passwordNonAlphaTip = data; + updatePasswordTip(0); + }); + } else { + vm.passwordNonAlphaTip = ''; + updatePasswordTip(0); + } + } + + function onChanges(simpleChanges) { + if (simpleChanges.passwordVal) { + if (simpleChanges.passwordVal.currentValue) { + updatePasswordTip(simpleChanges.passwordVal.currentValue.length); + } else { + updatePasswordTip(0); + } + } + } + + const updatePasswordTip = passwordLength => { + const remainingLength = vm.minPwdLength - passwordLength; + if (remainingLength > 0) { + localizationService.localize('user_newPasswordFormatLengthTip', [remainingLength]).then(data => { + vm.passwordTip = data; + if (vm.passwordNonAlphaTip) { + vm.passwordTip += `
${vm.passwordNonAlphaTip}`; + } + }); + } else { + vm.passwordTip = vm.passwordNonAlphaTip; + } + } + } +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js index bbda02806e..fb58b4287d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js @@ -129,6 +129,8 @@ replace: true, templateUrl: 'views/components/buttons/umb-toggle.html', scope: { + // TODO: This should have required ngModel so we can track and validate user input correctly + // https://docs.angularjs.org/api/ng/type/ngModel.NgModelController#custom-control-example checked: "=", disabled: "=", inputId: "@", diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js index 3e227bfcb3..71bf151b89 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js @@ -202,6 +202,9 @@ splitViewChanged(); unbindSplitViewRequest(); } + + // if split view was never closed, the listener is not disposed when changing nodes - this unbinds it + $scope.$on('$destroy', () => unbindSplitViewRequest()); /** * Changes the currently selected variant diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js index 6f272f1ea2..0ac285c094 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js @@ -341,20 +341,19 @@ Use this directive to construct a header inside the main editor window. } } - scope.accessibility.a11yMessageVisible = !isEmptyOrSpaces(scope.accessibility.a11yMessage); - scope.accessibility.a11yNameVisible = !isEmptyOrSpaces(scope.accessibility.a11yName); + + scope.accessibility.a11yMessageVisible = !isNullOrWhitespace(scope.accessibility.a11yMessage); + scope.accessibility.a11yNameVisible = !isNullOrWhitespace(scope.accessibility.a11yName); }); } - - - function isEmptyOrSpaces(str) { - return str === null || str===undefined || str.trim ===''; + function isNullOrWhitespace(str) { + return str === null || str === undefined || str.trim() === ''; } function SetPageTitle(title) { - scope.$emit("$changeTitle", title); + scope.$emit("$changeTitle", title); } var unbindEventHandler = $rootScope.$on('$setAccessibleHeader', function (event, isNew, editorFor, nameLocked, name, contentTypeName, setTitle) { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/prevententersubmit.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/prevententersubmit.directive.js index 355b02216f..62334387cb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/prevententersubmit.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/prevententersubmit.directive.js @@ -17,7 +17,7 @@ angular.module("umbraco.directives") } $(element).on("keypress", function (event) { - if (event.which === 13) { + if (event.which === 13 && enabled === true) { event.preventDefault(); } }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js index efbc384cb4..2e9f15913c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js @@ -24,7 +24,7 @@ @param {boolean} model Set to true or false to set the checkbox to checked or unchecked. @param {string} inputId Set the id of the checkbox. @param {string} text Set the text for the checkbox label. -@param {string} labelKey Set a dictinary/localization string for the checkbox label +@param {string} labelKey Set a dictionary/localization string for the checkbox label @param {callback} onChange Callback when the value of the checkbox change by interaction. @param {boolean} autoFocus Add autofocus to the input field @param {boolean} preventSubmitOnEnter Set the enter prevent directive or not @@ -42,13 +42,15 @@ vm.change = change; function onInit() { - vm.inputId = vm.inputId || "umb-check_" + String.CreateGuid(); + vm.inputId = vm.inputId || "umb-search-filter_" + String.CreateGuid(); + vm.autoFocus = Object.toBoolean(vm.autoFocus) === true; + vm.preventSubmitOnEnter = Object.toBoolean(vm.preventSubmitOnEnter) === true; // If a labelKey is passed let's update the returned text if it's does not contain an opening square bracket [ if (vm.labelKey) { localizationService.localize(vm.labelKey).then(function (data) { - if(data.indexOf('[') === -1){ - vm.text = data; + if (data.indexOf('[') === -1){ + vm.text = data; } }); } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js index 2b2f36dd7d..f4cfacbf70 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js @@ -35,6 +35,12 @@ vm.$onInit = onInit; + vm.setDirty = function () { + // NOTE: We need to use scope because we haven't changd it to vm.propertyForm in the html and that + // might mean a breaking change. + $scope.propertyForm.$setDirty(); + } + vm.setPropertyError = function (errorMsg) { vm.property.propertyErrorMessage = errorMsg; }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js index b1c8608124..7a10ff51b5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js @@ -11,24 +11,27 @@ Use this directive to render a tabs navigation.
     
- - + + - -
-
Content of tab 1
-
-
-
Content of tab 2
-
-
+ + + +
+
Content of tab 1
+
+
+
Content of tab 2
+
+
+
@@ -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.

Click the retry button when done.
More information on editing web.config here.

", + "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.

Click the retry button when done.
More information on editing web.config here.

", "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": "

© 2001 - %0%
Umbraco.org

", + "login_bottomText": "

© 2001 - %0%
Umbraco.org

", "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.

- View Report + View Report

Simply click continue below to be guided through the rest of the upgrade. diff --git a/src/Umbraco.Web.UI.Client/src/less/buttons.less b/src/Umbraco.Web.UI.Client/src/less/buttons.less index c446a02424..d1a426f818 100644 --- a/src/Umbraco.Web.UI.Client/src/less/buttons.less +++ b/src/Umbraco.Web.UI.Client/src/less/buttons.less @@ -65,15 +65,22 @@ // -------------------------------------------------- .btn-reset { - padding: 0; - margin: 0; - border: none; + padding: 0; + margin: 0; + border: none; background: none; - color: currentColor; + color: currentColor; font-family: @baseFontFamily; font-size: @baseFontSize; line-height: @baseLineHeight; - cursor: pointer; + cursor: pointer; + + // Disabled state + &.disabled, + &[disabled], + &:disabled:hover { + cursor: default; + } } // Button Sizes diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less index 19d6a1306e..274f74bbac 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less @@ -34,6 +34,17 @@ &--level0 { transform: none; } + + &--small .umb-property { + .control-header { + float: none; + width: 100%; + } + + .controls { + margin-left: 0; + } + } } // use a loop to build the editor levels diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less index 3b084c9905..281284a5ca 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less @@ -401,6 +401,7 @@ text-align: center; text-align: -moz-center; width: 100%; + box-sizing: border-box; } .umb-grid .umb-editor-placeholder i { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-search-filter.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-search-filter.less index b96d3e8569..b38f5937c7 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-search-filter.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-search-filter.less @@ -21,11 +21,12 @@ html .umb-search-filter { // "icon-search" class it kept for backward compatibility .umb-icon, .icon-search { - color: #d8d7d9; + color: @gray-8; position: absolute; top: 0; bottom: 0; left: 10px; margin: auto 0; + pointer-events: none; } } diff --git a/src/Umbraco.Web.UI.Client/src/less/forms.less b/src/Umbraco.Web.UI.Client/src/less/forms.less index 17c62037cc..3782fca695 100644 --- a/src/Umbraco.Web.UI.Client/src/less/forms.less +++ b/src/Umbraco.Web.UI.Client/src/less/forms.less @@ -589,19 +589,21 @@ table.domains .help-inline { } } .add-on { - display: inline-block; + display: inline-flex; + align-items: center; + justify-content: center; width: auto; height: 22px; min-width: 18px; - padding: 5px 6px 3px 6px; + padding: 4px 6px; font-size: @baseFontSize; font-weight: normal; line-height: @baseLineHeight; text-align: center; - //text-shadow: 0 1px 0 @white; background-color: @white; border: 1px solid @inputBorder; color: @ui-option-type; + &:hover { border-color:@inputBorderFocus; color: @ui-option-type-hover; @@ -807,9 +809,12 @@ legend + .control-group { // adjustments for properties tab .form-horizontal .block-form .control-label { - display: block; - float: none; - width: 100%; + display: block; + float: none; + width: 100%; +} +.form-horizontal .block-form .controls { + margin-left: 0; } //make sure buttons are always on top diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less index 31bb8484c4..66afbfd73f 100644 --- a/src/Umbraco.Web.UI.Client/src/less/main.less +++ b/src/Umbraco.Web.UI.Client/src/less/main.less @@ -402,6 +402,10 @@ table thead button:focus{ /* UI interactions */ +.ui-sortable-handle { + cursor: move; +} + .umb-table tbody.ui-sortable tr { cursor:pointer; diff --git a/src/Umbraco.Web.UI.Client/src/less/panel.less b/src/Umbraco.Web.UI.Client/src/less/panel.less index a036267c85..cc87a0edf5 100644 --- a/src/Umbraco.Web.UI.Client/src/less/panel.less +++ b/src/Umbraco.Web.UI.Client/src/less/panel.less @@ -349,6 +349,7 @@ .umb-panel-header-icon { cursor: pointer; + font-size: 2rem; margin-right: 5px; margin-top: -6px; height: 50px; diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less index 0d8f270f1b..f5e652aa3d 100644 --- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less +++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less @@ -838,22 +838,25 @@ // // Date/time picker // -------------------------------------------------- -.bootstrap-datetimepicker-widget .btn{padding: 0;} -.bootstrap-datetimepicker-widget .picker-switch .btn{ background: none; border: none;} -.umb-datepicker .input-append .add-on{cursor: pointer;} -.umb-datepicker .input-append .on-top { - border: 0 none; +.bootstrap-datetimepicker-widget .btn {padding: 0;} +.bootstrap-datetimepicker-widget .picker-switch .btn { background: none; border: none;} +.umb-datepicker .input-append .btn-clear { + border: none; position: absolute; margin-left: -31px; margin-top: 1px; - display: inline-block; - padding: 5px 6px 3px 6px; + display: inline-flex; + align-items: center; + justify-content: center; + height: 30px; + padding: 4px 6px; font-size: @baseFontSize; font-weight: normal; line-height: @baseLineHeight; text-align: center; background-color: @white; color: @ui-option-type; + &:hover { color: @ui-option-type-hover; } diff --git a/src/Umbraco.Web.UI.Client/src/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/navigation.controller.js index 37f6ff9733..11bea9b275 100644 --- a/src/Umbraco.Web.UI.Client/src/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/navigation.controller.js @@ -325,6 +325,9 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar var queryParams = {}; if ($scope.selectedLanguage && $scope.selectedLanguage.culture) { queryParams["culture"] = $scope.selectedLanguage.culture; + if (!mainCulture) { + $location.search("mculture", $scope.selectedLanguage.culture); + } } var queryString = $.param(queryParams); //create the query string from the params object } diff --git a/src/Umbraco.Web.UI.Client/src/utilities.js b/src/Umbraco.Web.UI.Client/src/utilities.js index 64884b589b..01e18e4e1c 100644 --- a/src/Umbraco.Web.UI.Client/src/utilities.js +++ b/src/Umbraco.Web.UI.Client/src/utilities.js @@ -71,28 +71,29 @@ const isScope = obj => obj && obj.$evalAsync && obj.$watch; const toJsonReplacer = (key, value) => { - var val = value; + var val = value; if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') { - val = undefined; + val = undefined; } else if (isWindow(value)) { - val = '$WINDOW'; - } else if (value && window.document === value) { - val = '$DOCUMENT'; + val = '$WINDOW'; + } else if (value && window.document === value) { + val = '$DOCUMENT'; } else if (isScope(value)) { - val = '$SCOPE'; - } + val = '$SCOPE'; + } return val; - } + }; + /** * Equivalent to angular.toJson */ const toJson = (obj, pretty) => { if (isUndefined(obj)) return undefined; if (!isNumber(pretty)) { - pretty = pretty ? 2 : null; + pretty = pretty ? 2 : null; } return JSON.stringify(obj, toJsonReplacer, pretty); - } + }; /** * Equivalent to angular.fromJson @@ -102,7 +103,7 @@ return val; } return JSON.parse(val); - } + }; /** * Not equivalent to angular.forEach. But like the angularJS method this does not fail on null or undefined. @@ -112,7 +113,7 @@ return obj.forEach(iterator); } return obj; - } + }; let _utilities = { noop: noop, diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js index 88cda027a8..d3a87791f9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js @@ -1,6 +1,7 @@ angular.module("umbraco") .controller("Umbraco.Editors.BlockEditorController", function ($scope, localizationService, formHelper, overlayService) { + var vm = this; vm.model = $scope.model; @@ -52,7 +53,7 @@ angular.module("umbraco") vm.saveButtonState = "error"; } } - } + }; vm.close = function () { if (vm.model && vm.model.close) { @@ -93,7 +94,7 @@ angular.module("umbraco") } } - } + }; } ); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.html index 2367771804..8fe5526c53 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.html @@ -1,4 +1,4 @@ -

+
@@ -14,20 +14,12 @@ hide-description="true"> -
+ - + + -
- - -
- -
+ diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockpicker/blockpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockpicker/blockpicker.controller.js index 2894e0bef4..5e6613c0f4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockpicker/blockpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockpicker/blockpicker.controller.js @@ -1,11 +1,14 @@ angular.module("umbraco") .controller("Umbraco.Editors.BlockPickerController", function ($scope, localizationService) { - var vm = this; + var vm = this; vm.navigation = []; + vm.filter = { + searchTerm: '' + }; localizationService.localizeMany(["blockEditor_tabCreateEmpty", "blockEditor_tabClipboard"]).then( function (data) { @@ -14,7 +17,6 @@ angular.module("umbraco") "alias": "empty", "name": data[0], "icon": "icon-add", - "active": true, "view": "" }, { @@ -25,36 +27,41 @@ angular.module("umbraco") "disabled": vm.model.clipboardItems.length === 0 }]; - vm.activeTab = vm.navigation[0]; + if (vm.model.openClipboard === true) { + vm.activeTab = vm.navigation[1]; + } else { + vm.activeTab = vm.navigation[0]; + } + + vm.activeTab.active = true; } ); - - vm.onNavigationChanged = function(tab) { + vm.onNavigationChanged = function (tab) { vm.activeTab.active = false; vm.activeTab = tab; vm.activeTab.active = true; - } + }; - vm.clickClearClipboard = function() { + vm.clickClearClipboard = function () { vm.onNavigationChanged(vm.navigation[0]); vm.navigation[1].disabled = true;// disabled ws determined when creating the navigation, so we need to update it here. vm.model.clipboardItems = [];// This dialog is not connected via the clipboardService events, so we need to update manually. vm.model.clickClearClipboard(); - } + }; vm.model = $scope.model; - vm.selectItem = function(item, $event) { + vm.selectItem = function (item, $event) { vm.model.selectedItem = item; vm.model.submit($scope.model, $event); - } + }; - vm.close = function() { + vm.close = function () { if ($scope.model && $scope.model.close) { $scope.model.close($scope.model); } - } + }; } ); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockpicker/blockpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockpicker/blockpicker.html index 4b08d4e5fc..b72de0960d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockpicker/blockpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockpicker/blockpicker.html @@ -12,35 +12,35 @@ hide-description="true"> -
+ -
+
- -
+
+
-
+ diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html index 428905020b..77cfc705a3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html @@ -36,13 +36,15 @@
- -
- - - - - + +
+
+ + + + +
+ diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.controller.js index f132c0211b..8b1cffdc4c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.controller.js @@ -18,8 +18,11 @@ preview: "", success: false, info: "", - supportsDimensions: false - }; + a11yInfo: "", + supportsDimensions: false, + originalWidth: 360, + originalHeight: 240 + }; if ($scope.model.modify) { Utilities.extend($scope.model.embed, $scope.model.modify); @@ -32,8 +35,8 @@ vm.changeSize = changeSize; vm.submit = submit; vm.close = close; - - function onInit() { + + function onInit() { if (!$scope.model.title) { localizationService.localize("general_embed").then(function(value){ $scope.model.title = value; @@ -46,8 +49,8 @@ if ($scope.model.embed.url) { $scope.model.embed.show = true; $scope.model.embed.info = ""; + $scope.model.embed.a11yInfo = ""; $scope.model.embed.success = false; - vm.loading = true; $http({ @@ -68,6 +71,7 @@ //not supported $scope.model.embed.preview = ""; $scope.model.embed.info = "Not supported"; + $scope.model.embed.a11yInfo = $scope.model.embed.info; $scope.model.embed.success = false; $scope.model.embed.supportsDimensions = false; vm.trustedPreview = null; @@ -77,6 +81,7 @@ //error $scope.model.embed.preview = ""; $scope.model.embed.info = "Could not embed media - please ensure the URL is valid"; + $scope.model.embed.a11yInfo = $scope.model.embed.info; $scope.model.embed.success = false; $scope.model.embed.supportsDimensions = false; vm.trustedPreview = null; @@ -86,6 +91,8 @@ $scope.model.embed.success = true; $scope.model.embed.supportsDimensions = response.data.SupportsDimensions; $scope.model.embed.preview = response.data.Markup; + $scope.model.embed.info = ""; + $scope.model.embed.a11yInfo = "Retrieved URL"; vm.trustedPreview = $sce.trustAsHtml(response.data.Markup); break; } @@ -97,24 +104,28 @@ $scope.model.embed.supportsDimensions = false; $scope.model.embed.preview = ""; $scope.model.embed.info = "Could not embed media - please ensure the URL is valid"; - + $scope.model.embed.a11yInfo = $scope.model.embed.info; vm.loading = false; }); } else { $scope.model.embed.supportsDimensions = false; $scope.model.embed.preview = ""; $scope.model.embed.info = "Please enter a URL"; + $scope.model.embed.a11yInfo = $scope.model.embed.info; } } function changeSize(type) { - var width, height; + var width = parseInt($scope.model.embed.width, 10); + var height = parseInt($scope.model.embed.height, 10); + var originalWidth = parseInt($scope.model.embed.originalWidth, 10); + var originalHeight = parseInt($scope.model.embed.originalHeight, 10); + var resize = originalWidth !== width || originalHeight !== height; if ($scope.model.embed.constrain) { - width = parseInt($scope.model.embed.width, 10); - height = parseInt($scope.model.embed.height, 10); - if (type == 'width') { + + if (type === 'width') { origHeight = Math.round((width / origWidth) * height); $scope.model.embed.height = origHeight; } else { @@ -122,9 +133,12 @@ $scope.model.embed.width = origWidth; } } - if ($scope.model.embed.url !== "") { + $scope.model.embed.originalWidth = $scope.model.embed.width; + $scope.model.embed.originalHeight = $scope.model.embed.height; + if ($scope.model.embed.url !== "" && resize) { showPreview(); } + } function toggleConstrain() { @@ -141,7 +155,7 @@ if ($scope.model && $scope.model.close) { $scope.model.close(); } - } + } onInit(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.html index 19cf9b2278..fd86f55c07 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/embed/embed.html @@ -15,7 +15,7 @@ - + -

+ +
- - + + - - + + - - + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.controller.js index 59a9aed4bb..51c2c15898 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.controller.js @@ -10,6 +10,10 @@ function IconPickerController($scope, localizationService, iconHelper) { var vm = this; + vm.filter = { + searchTerm: '' + }; + vm.selectIcon = selectIcon; vm.selectColor = selectColor; vm.submit = submit; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.html index 7368d2f39b..19fe679189 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.html @@ -20,7 +20,7 @@
    -
  • +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html index 060217d33c..02429fa164 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html @@ -226,7 +226,8 @@
- + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html index 86e905183c..bb4b025410 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html @@ -23,7 +23,7 @@ class="umb-language-picker__dropdown-item" ng-class="{'umb-language-picker__dropdown-item--current': language.active}" ng-click="selectLanguage(language)" - ng-repeat="language in languages | orderBy:'name'" + ng-repeat="language in languages" > Switch language to diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content.html index 40a88ae6a6..9efc0e80bd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content.html @@ -36,7 +36,8 @@
- + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html index 6978672e99..6e33633512 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html @@ -96,6 +96,7 @@
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-search-filter.html b/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-search-filter.html index d6fde29090..ab21654f91 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-search-filter.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-search-filter.html @@ -2,27 +2,14 @@
- - - +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-search-box.html b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-search-box.html index 77498cd007..054472e4b6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-search-box.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-search-box.html @@ -2,6 +2,7 @@ - - Sorry, we can not find what you are looking for. - - -
    -
  • -
      -
    • -
      - -
      + +

      Sorry, we can not find what you are looking for.

      +
      +

      1 item returned

      +

      {{results.length}} items returned

      +
        +
      • +
          +
        • +
          + +
          +
        • +
      • -
      -
    • -
    +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html b/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html index 3579334996..1e09624f84 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html @@ -33,12 +33,14 @@ required val-server-field="password" ng-minlength="{{vm.config.minPasswordLength}}" - no-dirty-check /> + no-dirty-check + ng-keyup="vm.newPasswordKeyUp($event)"/> Required Minimum {{vm.config.minPasswordLength}} characters {{changePasswordForm.password.errorMsg}} + diff --git a/src/Umbraco.Web.UI.Client/src/views/content/recyclebin.html b/src/Umbraco.Web.UI.Client/src/views/content/recyclebin.html index 2981097656..410ad938f8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/recyclebin.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/recyclebin.html @@ -11,7 +11,8 @@
- + +
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.

diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/media/mediadashboardvideos.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/media/mediadashboardvideos.html index 96d6a3f40a..670fae2f6e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/media/mediadashboardvideos.html +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/media/mediadashboardvideos.html @@ -1,5 +1,5 @@

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

- + {{key}} - {{val}} + {{values | umbCmsJoinArray:', '}} diff --git a/src/Umbraco.Web.UI.Client/src/views/dictionary/list.html b/src/Umbraco.Web.UI.Client/src/views/dictionary/list.html index de7beae0cc..84c138c180 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dictionary/list.html +++ b/src/Umbraco.Web.UI.Client/src/views/dictionary/list.html @@ -32,19 +32,21 @@ - + - + - + diff --git a/src/Umbraco.Web.UI.Client/src/views/documentTypes/copy.html b/src/Umbraco.Web.UI.Client/src/views/documentTypes/copy.html index 8b81462ad5..824527be34 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documentTypes/copy.html +++ b/src/Umbraco.Web.UI.Client/src/views/documentTypes/copy.html @@ -20,7 +20,7 @@
{{source.name}} was copied underneath {{target.name}}
- +
diff --git a/src/Umbraco.Web.UI.Client/src/views/documentTypes/export.html b/src/Umbraco.Web.UI.Client/src/views/documentTypes/export.html index 0b9feb3fb6..b9aa4d9d3a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documentTypes/export.html +++ b/src/Umbraco.Web.UI.Client/src/views/documentTypes/export.html @@ -1,8 +1,8 @@
diff --git a/src/Umbraco.Web.UI.Client/src/views/documentTypes/move.html b/src/Umbraco.Web.UI.Client/src/views/documentTypes/move.html index fe0bde7f1f..b623b6131d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documentTypes/move.html +++ b/src/Umbraco.Web.UI.Client/src/views/documentTypes/move.html @@ -20,7 +20,7 @@
{{source.name}} was moved underneath {{target.name}}
- +
diff --git a/src/Umbraco.Web.UI.Client/src/views/languages/overview.html b/src/Umbraco.Web.UI.Client/src/views/languages/overview.html index 95cb7c535f..9a11691e09 100644 --- a/src/Umbraco.Web.UI.Client/src/views/languages/overview.html +++ b/src/Umbraco.Web.UI.Client/src/views/languages/overview.html @@ -36,7 +36,7 @@ - + {{ language.name }} diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html b/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html index 9825a6f919..c152c33193 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html +++ b/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html @@ -1,62 +1,76 @@ 
- - - - - {{model.macro.id}}
- {{model.macro.key}} -
-
-
- - - - - - +
- +
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
{{model.macro.id}}
+ {{model.macro.key}} +
+
+
+
+ +
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/Umbraco.Web.UI.Client/src/views/media/edit.html b/src/Umbraco.Web.UI.Client/src/views/media/edit.html index d2782a2a21..8f8a62474b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/media/edit.html @@ -23,7 +23,8 @@
- + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.sort.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.sort.controller.js index 95aeb239b9..2cc27be914 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/media.sort.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/media/media.sort.controller.js @@ -11,6 +11,8 @@ vm.saveButtonState = "init"; vm.sortOrder = {}; vm.sortableOptions = { + axis: "y", + containment: "parent", distance: 10, tolerance: "pointer", opacity: 0.7, diff --git a/src/Umbraco.Web.UI.Client/src/views/media/recyclebin.html b/src/Umbraco.Web.UI.Client/src/views/media/recyclebin.html index cd4ad6d07e..fddf63bef3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/recyclebin.html +++ b/src/Umbraco.Web.UI.Client/src/views/media/recyclebin.html @@ -12,7 +12,8 @@
- + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/media/sort.html b/src/Umbraco.Web.UI.Client/src/views/media/sort.html index a483e9c7dc..05a55f435f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/sort.html +++ b/src/Umbraco.Web.UI.Client/src/views/media/sort.html @@ -19,19 +19,17 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/mediaTypes/copy.html b/src/Umbraco.Web.UI.Client/src/views/mediaTypes/copy.html index 9c21f623b5..58968c9dfa 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediaTypes/copy.html +++ b/src/Umbraco.Web.UI.Client/src/views/mediaTypes/copy.html @@ -20,7 +20,7 @@
{{source.name}} was copied underneath {{target.name}}
- +
diff --git a/src/Umbraco.Web.UI.Client/src/views/mediaTypes/move.html b/src/Umbraco.Web.UI.Client/src/views/mediaTypes/move.html index 5225a41a0d..6bb1b6fa10 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediaTypes/move.html +++ b/src/Umbraco.Web.UI.Client/src/views/mediaTypes/move.html @@ -20,7 +20,7 @@
{{source.name}} was moved underneath {{target.name}}
- +
diff --git a/src/Umbraco.Web.UI.Client/src/views/member/edit.html b/src/Umbraco.Web.UI.Client/src/views/member/edit.html index 3fec222350..50c986bd6a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/member/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/member/edit.html @@ -26,7 +26,8 @@
- + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/member/list.html b/src/Umbraco.Web.UI.Client/src/views/member/list.html index a61614e8f5..4f27b54aa9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/member/list.html +++ b/src/Umbraco.Web.UI.Client/src/views/member/list.html @@ -18,7 +18,8 @@
- + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/memberTypes/copy.controller.js b/src/Umbraco.Web.UI.Client/src/views/memberTypes/copy.controller.js new file mode 100644 index 0000000000..aa94b4bd04 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/memberTypes/copy.controller.js @@ -0,0 +1,61 @@ +angular.module("umbraco") + .controller("Umbraco.Editors.MemberTypes.CopyController", + function ($scope, memberTypeResource, treeService, navigationService, notificationsService, appState, eventsService) { + + $scope.dialogTreeApi = {}; + $scope.source = _.clone($scope.currentNode); + + function nodeSelectHandler(args) { + args.event.preventDefault(); + args.event.stopPropagation(); + + if ($scope.target) { + //un-select if there's a current one selected + $scope.target.selected = false; + } + + $scope.target = args.node; + $scope.target.selected = true; + } + + $scope.copy = function () { + + $scope.busy = true; + $scope.error = false; + + memberTypeResource.copy({ parentId: $scope.target.id, id: $scope.source.id }) + .then(function (path) { + $scope.error = false; + $scope.success = true; + $scope.busy = false; + + //get the currently edited node (if any) + var activeNode = appState.getTreeState("selectedNode"); + + //we need to do a double sync here: first sync to the copied content - but don't activate the node, + //then sync to the currenlty edited content (note: this might not be the content that was copied!!) + + navigationService.syncTree({ tree: "memberTypes", path: path, forceReload: true, activate: false }).then(function (args) { + if (activeNode) { + var activeNodePath = treeService.getPath(activeNode).join(); + //sync to this node now - depending on what was copied this might already be synced but might not be + navigationService.syncTree({ tree: "memberTypes", path: activeNodePath, forceReload: false, activate: true }); + } + }); + + }, function (err) { + $scope.success = false; + $scope.error = err; + $scope.busy = false; + }); + }; + + $scope.onTreeInit = function () { + $scope.dialogTreeApi.callbacks.treeNodeSelect(nodeSelectHandler); + }; + + $scope.close = function() { + navigationService.hideDialog(); + }; + + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/memberTypes/copy.html b/src/Umbraco.Web.UI.Client/src/views/memberTypes/copy.html new file mode 100644 index 0000000000..fb7c6b5584 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/memberTypes/copy.html @@ -0,0 +1,53 @@ +
+ +
+
+ +

+ Select the folder to copy {{source.name}} to in the tree structure below +

+ + + +
+
+
{{error.errorMsg}}
+
{{error.data.message}}
+
+
+ +
+
+ {{source.name}} was copied underneath {{target.name}} +
+ +
+ +
+ +
+ + +
+ +
+
+
+ + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.html index 9726daf5e6..87c0026d56 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.html @@ -10,7 +10,7 @@
- + + class="btn-reset umb-block-list__clipboard-button umb-outline" + ng-class="{'--jump': vm.jumpClipboardButton}" + ng-disabled="vm.clipboardItems.length === 0" + ng-click="vm.requestShowClipboard(vm.layout.length, $event)" + localize="title" + title="@blockEditor_tabClipboard"> + + + Clipboard + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less index e290c6e856..019a772fdd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less @@ -236,30 +236,98 @@ ng-form.ng-invalid-val-server-match-settings > .umb-block-list__block > .umb-blo } } } -.umb-block-list__create-button { - position: relative; + +.umb-block-list__actions { display: flex; - width: 100%; - align-items: center; - justify-content: center; + border: 1px dashed @ui-action-discreet-border; - color: @ui-action-discreet-type; - font-weight: bold; - margin: 2px 0; - padding: 5px 15px; - box-sizing: border-box; border-radius: @baseBorderRadius; -} + box-sizing: border-box; -.umb-block-list__create-button:hover { - color: @ui-action-discreet-type-hover; - border-color: @ui-action-discreet-border-hover; - text-decoration: none; -} + &:hover { + border-color: transparent; + > button { -.umb-block-list__create-button.--disabled, -.umb-block-list__create-button.--disabled:hover { - color: @gray-7; - border-color: @gray-7; - cursor: default; + border-color: @ui-action-discreet-border; + + &.umb-block-list__clipboard-button { + opacity: 1; + } + } + + } + + > button { + position: relative; + display: flex; + //width: 100%; + align-items: center; + justify-content: center; + + color: @ui-action-discreet-type; + font-weight: bold; + margin: -1px; + padding: 5px 15px; + + border: 1px dashed transparent; + border-radius: @baseBorderRadius; + box-sizing: border-box; + + &:hover { + color: @ui-action-discreet-type-hover; + border-color: @ui-action-discreet-border-hover; + text-decoration: none; + z-index: 1; + } + + &[disabled], + &[disabled]:hover { + color: @gray-7; + border-color: @gray-7; + cursor: default; + } + + &.umb-block-list__create-button { + flex-grow: 1; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + &.umb-block-list__clipboard-button { + margin-left: 0; + padding: 5px 12px; + font-size: 18px;// Align with block action buttons. + border-top-left-radius: 0; + border-bottom-left-radius: 0; + + opacity: 0; + &:hover, &:focus { + opacity: 1; + } + + &.--jump { + + @keyframes umb-block-list__jump-clipboard-button { + 0% { opacity: 0; } + 10% { opacity: 1; } + 90% { opacity: 1; } + 100% { opacity: 0; } + } + animation: umb-block-list__jump-clipboard-button 2s; + + i{ + @keyframes umb-block-list__jump-clipboard-button-i { + 10% { transform: scale(1); } + 10% { transform: scale(1.33); } + 20% { transform: scale(.82); } + 30% { transform: scale(1.24); } + 40% { transform: scale(.94); } + 50% { transform: scale(1); } + } + animation: umb-block-list__jump-clipboard-button-i 2s; + } + } + + } + } } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js index 56dbc68d90..2d9b13ec7a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js @@ -28,7 +28,7 @@ } }); - function BlockListController($scope, editorService, clipboardService, localizationService, overlayService, blockEditorService, udiService, serverValidationManager, angularHelper) { + function BlockListController($scope, $timeout, editorService, clipboardService, localizationService, overlayService, blockEditorService, udiService, serverValidationManager, angularHelper, eventsService) { var unsubscribe = []; var modelObject; @@ -53,6 +53,8 @@ }; vm.supportCopy = clipboardService.isSupported(); + vm.clipboardItems = []; + unsubscribe.push(eventsService.on("clipboardService.storageUpdate", updateClipboard)); vm.layout = []; // The layout object specific to this Block Editor, will be a direct reference from Property Model. vm.availableBlockTypes = []; // Available block entries of this property editor. @@ -187,6 +189,8 @@ vm.availableContentTypesAliases = modelObject.getAvailableAliasesForBlockContent(); vm.availableBlockTypes = modelObject.getAvailableBlocksForBlockPicker(); + updateClipboard(true); + vm.loading = false; $scope.$evalAsync(); @@ -241,23 +245,24 @@ block.hideContentInOverlay = block.config.forceHideContentEditorInOverlay === true || inlineEditing === true; block.showSettings = block.config.settingsElementTypeKey != null; - block.showCopy = vm.supportCopy && block.config.contentElementTypeKey != null;// if we have content, otherwise it doesn't make sense to copy. + // If we have content, otherwise it doesn't make sense to copy. + block.showCopy = vm.supportCopy && block.config.contentElementTypeKey != null; // Index is set by umbblocklistblock component and kept up to date by it. block.index = 0; block.setParentForm = function (parentForm) { this._parentForm = parentForm; - } + }; block.activate = activateBlock.bind(null, block); block.edit = function () { var blockIndex = vm.layout.indexOf(this.layout); editBlock(this, false, blockIndex, this._parentForm); - } + }; block.editSettings = function () { var blockIndex = vm.layout.indexOf(this.layout); editBlock(this, true, blockIndex, this._parentForm); - } + }; block.requestDelete = requestDeleteBlock.bind(null, block); block.delete = deleteBlock.bind(null, block); block.copy = copyBlock.bind(null, block); @@ -265,7 +270,6 @@ return block; } - function addNewBlock(index, contentElementTypeKey) { // Create layout entry. (not added to property model jet.) @@ -292,7 +296,6 @@ vm.setBlockFocus(blockObject); return true; - } function deleteBlock(block) { @@ -316,7 +319,6 @@ }); modelObject.removeDataAndDestroyModel(block); - } function deleteAllBlocks() { @@ -408,8 +410,34 @@ editorService.open(blockEditorModel); } + vm.requestShowCreate = requestShowCreate; + function requestShowCreate(createIndex, mouseEvent) { + + if (vm.blockTypePicker) { + return; + } + + if (vm.availableBlockTypes.length === 1) { + var wasAdded = false; + var blockType = vm.availableBlockTypes[0]; + + wasAdded = addNewBlock(createIndex, blockType.blockConfigModel.contentElementTypeKey); + + if(wasAdded && !(mouseEvent.ctrlKey || mouseEvent.metaKey)) { + userFlowWhenBlockWasCreated(createIndex); + } + } else { + showCreateDialog(createIndex); + } + + } + vm.requestShowClipboard = requestShowClipboard; + function requestShowClipboard(createIndex, mouseEvent) { + showCreateDialog(createIndex, true); + } + vm.showCreateDialog = showCreateDialog; - function showCreateDialog(createIndex, $event) { + function showCreateDialog(createIndex, openClipboard) { if (vm.blockTypePicker) { return; @@ -425,6 +453,7 @@ $parentForm: vm.propertyForm, // pass in a $parentForm, this maintains the FormController hierarchy with the infinite editing view (if it contains a form) availableItems: vm.availableBlockTypes, title: vm.labels.grid_addElement, + openClipboard: openClipboard, orderBy: "$index", view: "views/common/infiniteeditors/blockpicker/blockpicker.html", size: (amountOfAvailableTypes > 8 ? "medium" : "small"), @@ -445,19 +474,15 @@ } }, submit: function(blockPickerModel, mouseEvent) { - var added = false; + var wasAdded = false; if (blockPickerModel && blockPickerModel.selectedItem) { - added = addNewBlock(createIndex, blockPickerModel.selectedItem.blockConfigModel.contentElementTypeKey); + wasAdded = addNewBlock(createIndex, blockPickerModel.selectedItem.blockConfigModel.contentElementTypeKey); } if(!(mouseEvent.ctrlKey || mouseEvent.metaKey)) { editorService.close(); - if (added && vm.layout.length > createIndex) { - if (inlineEditing === true) { - activateBlock(vm.layout[createIndex].$block); - } else if (inlineEditing === false && vm.layout[createIndex].$block.hideContentInOverlay !== true) { - editBlock(vm.layout[createIndex].$block, false, createIndex, blockPickerModel.$parentForm, {createFlow: true}); - } + if (wasAdded) { + userFlowWhenBlockWasCreated(createIndex); } } }, @@ -476,7 +501,28 @@ clipboardService.clearEntriesOfType(clipboardService.TYPES.BLOCK, vm.availableContentTypesAliases); }; - blockPickerModel.clipboardItems = []; + blockPickerModel.clipboardItems = vm.clipboardItems; + + // open block picker overlay + editorService.open(blockPickerModel); + + }; + function userFlowWhenBlockWasCreated(createIndex) { + if (vm.layout.length > createIndex) { + var blockObject = vm.layout[createIndex].$block; + if (inlineEditing === true) { + blockObject.activate(); + } else if (inlineEditing === false && blockObject.hideContentInOverlay !== true) { + blockObject.edit(); + } + } + } + + function updateClipboard(firstTime) { + + var oldAmount = vm.clipboardItems.length; + + vm.clipboardItems = []; var entriesForPaste = clipboardService.retriveEntriesOfType(clipboardService.TYPES.ELEMENT_TYPE, vm.availableContentTypesAliases); entriesForPaste.forEach(function (entry) { @@ -512,19 +558,33 @@ if(Array.isArray(entry.data) === false) { pasteEntry.blockConfigModel = modelObject.getBlockConfiguration(entry.data.data.contentTypeKey); } - blockPickerModel.clipboardItems.push(pasteEntry); + vm.clipboardItems.push(pasteEntry); }); - blockPickerModel.clipboardItems.sort( (a, b) => { + vm.clipboardItems.sort( (a, b) => { return b.date - a.date }); - // open block picker overlay - editorService.open(blockPickerModel); + if(firstTime !== true && vm.clipboardItems.length > oldAmount) { + jumpClipboard(); + } + } - }; + var jumpClipboardTimeout; + function jumpClipboard() { - var requestCopyAllBlocks = function() { + if(jumpClipboardTimeout) { + return; + } + + vm.jumpClipboardButton = true; + jumpClipboardTimeout = $timeout(() => { + vm.jumpClipboardButton = false; + jumpClipboardTimeout = null; + }, 2000); + } + + function requestCopyAllBlocks() { var aliases = []; @@ -534,7 +594,7 @@ aliases.push(entry.$block.content.contentTypeAlias); // No need to clone the data as its begin handled by the clipboardService. - return {"layout": entry.$block.layout, "data": entry.$block.data, "settingsData":entry.$block.settingsData} + return { "layout": entry.$block.layout, "data": entry.$block.data, "settingsData": entry.$block.settingsData } } ); @@ -543,9 +603,9 @@ var contentNodeName = "?"; var contentNodeIcon = null; - if(vm.umbVariantContent) { + if (vm.umbVariantContent) { contentNodeName = vm.umbVariantContent.editor.content.name; - if(vm.umbVariantContentEditors) { + if (vm.umbVariantContentEditors) { contentNodeIcon = vm.umbVariantContentEditors.content.icon.split(" ")[0]; } else if (vm.umbElementEditorContent) { contentNodeIcon = vm.umbElementEditorContent.model.documentType.icon.split(" ")[0]; @@ -555,13 +615,15 @@ contentNodeIcon = vm.umbElementEditorContent.model.documentType.icon.split(" ")[0]; } - localizationService.localize("clipboard_labelForArrayOfItemsFrom", [vm.model.label, contentNodeName]).then(function(localizedLabel) { + localizationService.localize("clipboard_labelForArrayOfItemsFrom", [vm.model.label, contentNodeName]).then(function (localizedLabel) { clipboardService.copyArray(clipboardService.TYPES.BLOCK, aliases, elementTypesToCopy, localizedLabel, contentNodeIcon || "icon-thumbnail-list", vm.model.id); }); - } + }; + function copyBlock(block) { clipboardService.copy(clipboardService.TYPES.BLOCK, block.content.contentTypeAlias, {"layout": block.layout, "data": block.data, "settingsData":block.settingsData}, block.label, block.content.icon, block.content.udi); } + function requestPasteFromClipboard(index, pasteEntry, pasteType) { if (pasteEntry === undefined) { @@ -599,7 +661,6 @@ vm.currentBlockInFocus = blockObject; return true; - } function requestDeleteBlock(block) { @@ -620,6 +681,7 @@ overlayService.confirmDelete(overlay); }); } + function requestDeleteAllBlocks() { localizationService.localizeMany(["content_nestedContentDeleteAllItems", "general_delete"]).then(function (data) { overlayService.confirmDelete({ @@ -647,7 +709,7 @@ requestDeleteBlock: requestDeleteBlock, deleteBlock: deleteBlock, openSettingsForBlock: openSettingsForBlock - } + }; vm.sortableOptions = { axis: "y", @@ -664,7 +726,6 @@ } }; - function onAmountOfBlocksChanged() { // enable/disable property actions diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.createButton.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.createButton.controller.js index 98d4f4ea3a..365ec809ac 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.createButton.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.createButton.controller.js @@ -9,9 +9,9 @@ var vm = this; vm.plusPosX = 0; - vm.onMouseMove = function($event) { + vm.onMouseMove = function ($event) { vm.plusPosX = $event.offsetX; - } + }; }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js index 41d76475e4..285437b011 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js @@ -78,7 +78,7 @@ model.block.index = index; model.block.updateLabel(); } - } + }; } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js index dab8d2c6f8..018c2b72c1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js @@ -1,4 +1,4 @@ -function booleanEditorController($scope, angularHelper) { +function booleanEditorController($scope) { // Setup the default config // This allow to overwrite the configuration when property editor is re-used @@ -36,6 +36,12 @@ function booleanEditorController($scope, angularHelper) { } } + function setDirty() { + if ($scope.modelValueForm) { + $scope.modelValueForm.modelValue.$setDirty(); + } + } + setupViewModel(); if ($scope.model && !$scope.model.value) { @@ -51,7 +57,7 @@ function booleanEditorController($scope, angularHelper) { // Update the value when the toggle is clicked $scope.toggle = function(){ - angularHelper.getCurrentForm($scope).$setDirty(); + setDirty(); if ($scope.renderModel.value){ $scope.model.value = $scope.model.config.falsevalue; setupViewModel(); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html index 75f3f5452a..aa47e0c667 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html @@ -1,11 +1,17 @@
- - + + + + + + + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js index 7a5954f504..4e0c269fbf 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js @@ -22,6 +22,9 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.ChangePasswordCont if (!$scope.model.config || $scope.model.config.minPasswordLength === undefined) { $scope.model.config.minPasswordLength = 0; } + if (!$scope.model.config || $scope.model.config.minNonAlphaNumericChars === undefined) { + $scope.model.config.minNonAlphaNumericChars = 0; + } //set the model defaults if (!Utilities.isObject($scope.model.value)) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js index c1b432b36e..8166255a26 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js @@ -2,16 +2,16 @@ function ColorPickerController($scope, $timeout) { var vm = this; - //setup the default config + // setup the default config var config = { items: [], multiple: false }; - //map the user config - angular.extend(config, $scope.model.config); + // map the user config + Utilities.extend(config, $scope.model.config); - //map back to the model + // map back to the model $scope.model.config = config; $scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0; @@ -63,7 +63,7 @@ function ColorPickerController($scope, $timeout) { // this is required to re-validate $timeout(function () { var newColor = color ? color.value : null; - $scope.propertyForm.selectedColor.$setViewValue(newColor); + vm.modelValueForm.selectedColor.$setViewValue(newColor); }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html index b7942b7f68..cb5c80a6f1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html @@ -1,17 +1,19 @@ 
-
- You haven't defined any colors -
+ +
+ You haven't defined any colors +
- - + + - + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/multicolorpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/multicolorpicker.controller.js index 967137b930..cb5905e2c9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/multicolorpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/multicolorpicker.controller.js @@ -104,7 +104,7 @@ return x.value === item.value && x.label === item.label; }); - angularHelper.getCurrentForm($scope).$setDirty(); + setDirty(); } function add(evt) { @@ -130,7 +130,7 @@ $scope.newLabel = ""; $scope.hasError = false; $scope.focusOnNew = true; - angularHelper.getCurrentForm($scope).$setDirty(); + setDirty(); return; } @@ -156,6 +156,12 @@ $scope.newLabel = defaultLabel; } + function setDirty() { + if (vm.modelValueForm) { + vm.modelValueForm.selectedColor.$setDirty(); + } + } + $scope.sortableOptions = { axis: 'y', containment: 'parent', @@ -164,7 +170,7 @@ items: '> div.control-group', tolerance: 'pointer', update: function (e, ui) { - angularHelper.getCurrentForm($scope).$setDirty(); + setDirty(); } }; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index 0f012810ba..e818fe9a23 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -15,7 +15,7 @@ * @param {any} editorService * @param {any} userService */ -function contentPickerController($scope, $q, $routeParams, $location, entityResource, editorState, iconHelper, angularHelper, navigationService, localizationService, editorService, userService, overlayService) { +function contentPickerController($scope, $q, $routeParams, $location, entityResource, editorState, iconHelper, navigationService, localizationService, editorService, userService, overlayService) { var vm = { labels: { @@ -112,7 +112,7 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso scroll: true, zIndex: 6000, update: function (e, ui) { - angularHelper.getCurrentForm($scope).$setDirty(); + setDirty(); } }; @@ -180,7 +180,7 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso $scope.clear(); $scope.add(data); } - angularHelper.getCurrentForm($scope).$setDirty(); + setDirty(); }, treeAlias: $scope.model.config.startNode.type, section: $scope.model.config.startNode.type, @@ -257,9 +257,9 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso _.each(model.selection, function (item, i) { $scope.add(item); }); - angularHelper.getCurrentForm($scope).$setDirty(); + setDirty(); } - angularHelper.getCurrentForm($scope).$setDirty(); + setDirty(); editorService.close(); } @@ -288,7 +288,7 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso var currIds = $scope.model.value ? $scope.model.value.split(',') : []; if (currIds.length > 0) { currIds.splice(index, 1); - angularHelper.getCurrentForm($scope).$setDirty(); + setDirty(); $scope.model.value = currIds.join(); } @@ -375,6 +375,12 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso } }); + function setDirty() { + if ($scope.contentPickerForm && $scope.contentPickerForm.modelValue) { + $scope.contentPickerForm.modelValue.$setDirty(); + } + } + /** Syncs the renderModel based on the actual model.value and returns a promise */ function syncRenderModel(doValidation) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html index 1a17ea2698..8ebbaae91f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html @@ -19,14 +19,12 @@
- @@ -64,16 +62,18 @@
+ + -
+
You need to add at least {{model.config.minNumber}} items
-
+
You can only have {{model.config.maxNumber}} items selected
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js index 30b6fc4c8f..af1dea167a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js @@ -161,7 +161,14 @@ function dateTimePickerController($scope, angularHelper, dateHelper, validationM else { $scope.model.value = null; } - angularHelper.getCurrentForm($scope).$setDirty(); + + setDirty(); + } + + function setDirty() { + if ($scope.datePickerForm) { + $scope.datePickerForm.datepicker.$setDirty(); + } } /** Sets the value of the date picker control adn associated viewModel objects based on the model value */ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html index 9501a6631b..f5ac69b9b8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html @@ -19,12 +19,12 @@ ng-required="model.validation.mandatory" val-server="value" class="datepickerinput" /> - -
@@ -32,7 +32,7 @@
-
+

{{mandatoryMessage}}

{{datePickerForm.datepicker.errorMsg}}

Invalid date

diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/decimal/decimal.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/decimal/decimal.html index ac2fdabf3d..fb68a67c60 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/decimal/decimal.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/decimal/decimal.html @@ -9,10 +9,15 @@ aria-required="{{model.validation.mandatory}}" id="{{model.alias}}" val-server="value" - fix-number min="{{model.config.min}}" max="{{model.config.max}}" step="{{model.config.step}}" /> + min="{{model.config.min}}" + max="{{model.config.max}}" + step="{{model.config.step}}" + ng-step="model.config.step" + fix-number /> - + Not a number + Not a valid numeric step size {{decimalFieldForm.decimalField.errorMsg}} diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/email/email.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/email/email.html index 26ec22df8d..3ae03a2d7b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/email/email.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/email/email.html @@ -1,6 +1,7 @@
- -
+

{{mandatoryMessage}}

Invalid email

{{emailFieldForm.textbox.errorMsg}}

diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/eyedropper/eyedropper.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/eyedropper/eyedropper.controller.js new file mode 100644 index 0000000000..82a0d18cab --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/eyedropper/eyedropper.controller.js @@ -0,0 +1,44 @@ +function EyeDropperColorPickerController($scope, angularHelper) { + + var vm = this; + + //setup the default config + var config = { + showAlpha: true, + showPalette: true, + allowEmpty: true + }; + + // map the user config + Utilities.extend(config, $scope.model.config); + + // map back to the model + $scope.model.config = config; + + vm.options = $scope.model.config; + + vm.color = $scope.model.value || null; + + vm.selectColor = function (color) { + angularHelper.safeApply($scope, function () { + vm.color = color ? color.toString() : null; + $scope.model.value = vm.color; + $scope.propertyForm.selectedColor.$setViewValue(vm.color); + }); + }; + + // Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected) + $scope.validateMandatory = function () { + var isValid = !$scope.model.validation.mandatory || ( + $scope.model.value != null + && $scope.model.value != ""); + + return { + isValid: isValid, + errorMsg: $scope.model.validation.mandatoryMessage || "Value cannot be empty", + errorKey: "required" + }; + }; +} + +angular.module("umbraco").controller("Umbraco.PropertyEditors.EyeDropperColorPickerController", EyeDropperColorPickerController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/eyedropper/eyedropper.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/eyedropper/eyedropper.html new file mode 100644 index 0000000000..821f50f92b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/eyedropper/eyedropper.html @@ -0,0 +1,11 @@ +
+ + + + + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js index 50146a4c36..15f5ceaa88 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js @@ -141,9 +141,9 @@ angular.module("umbraco") over: function (event, ui) { var area = event.target.getScope_HackForSortable().area; - var allowedEditors = area.allowed; + var allowedEditors = area.$allowedEditors.map(e => e.alias); - if (($.inArray(ui.item[0].getScope_HackForSortable().control.editor.alias, allowedEditors) < 0 && allowedEditors) || + if (($.inArray(ui.item[0].getScope_HackForSortable().control.editor.alias, allowedEditors) < 0) || (startingArea != area && area.maxItems != '' && area.maxItems > 0 && area.maxItems < area.controls.length + 1)) { $scope.$apply(function () { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js index 70c74d0391..4df8f7e596 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js @@ -31,7 +31,7 @@ angular.module('umbraco') }; //set form to dirty to track changes - $scope.imageCropperForm.$setDirty(); + setDirty(); } /** @@ -67,7 +67,13 @@ angular.module('umbraco') function onFileSelected(value, files) { setModelValueWithSrc(value); //set form to dirty to track changes - $scope.imageCropperForm.$setDirty(); + setDirty(); + } + + function setDirty() { + if ($scope.imageCropperForm) { + $scope.imageCropperForm.modelValue.$setDirty(); + } } function imageLoaded(isCroppable, hasDimensions) { @@ -84,7 +90,7 @@ angular.module('umbraco') if (files && files[0]) { $scope.imageSrc = files[0].fileSrc; //set form to dirty to track changes - $scope.imageCropperForm.$setDirty(); + setDirty(); } } @@ -138,7 +144,7 @@ angular.module('umbraco') $scope.currentPoint = null; //set form to dirty to track changes - $scope.imageCropperForm.$setDirty(); + setDirty(); } else { // we have a crop open already - close the crop (this will discard any changes made) @@ -168,7 +174,7 @@ angular.module('umbraco') $scope.close(); //set form to dirty to track changes - $scope.imageCropperForm.$setDirty(); + setDirty(); }; function reset() { @@ -201,7 +207,7 @@ angular.module('umbraco') } //set form to dirty to track changes - $scope.imageCropperForm.$setDirty(); + setDirty(); }; function isCustomCrop(crop) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html index 91abc3be87..241d61660e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html @@ -2,6 +2,9 @@ ng-controller="Umbraco.PropertyEditors.ImageCropperController"> + + +
- - - + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/integer/integer.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/integer/integer.html index 5c10790400..24a8c33696 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/integer/integer.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/integer/integer.html @@ -9,10 +9,15 @@ aria-required="{{model.validation.mandatory}}" id="{{model.alias}}" val-server="value" - fix-number min="{{model.config.min}}" max="{{model.config.max}}" step="{{model.config.step}}" /> + min="{{model.config.min}}" + max="{{model.config.max}}" + step="{{model.config.step}}" + ng-step="model.config.step" + fix-number /> - + Not a number + Not a valid numeric step size {{integerFieldForm.integerField.errorMsg}} diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html index 42597f0c82..7d863f6730 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html @@ -27,7 +27,7 @@ - +
@@ -54,7 +54,7 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html index 4527458d16..295345a827 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html @@ -6,20 +6,20 @@
- +
- -
- -
-
@@ -32,12 +32,12 @@
-
+
(blank) -
- + + +
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 @@
- +
- + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.controller.js index 6662a86571..2213841ece 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.controller.js @@ -10,6 +10,12 @@ return selected; }; + function setDirty() { + if ($scope.modelValueForm) { + $scope.modelValueForm.modelValue.$setDirty(); + } + } + $scope.pickGroup = function() { editorService.memberGroupPicker({ multiPicker: true, @@ -24,6 +30,7 @@ $scope.model.value[group.name] = true; }); }); + setDirty(); editorService.close(); }, close: function () { @@ -34,6 +41,7 @@ $scope.removeGroup = function (group) { $scope.model.value[group] = false; + setDirty(); } } angular.module('umbraco').controller("Umbraco.PropertyEditors.MemberGroupController", memberGroupController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html index 2715e11b15..abfa628e90 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html @@ -12,4 +12,9 @@ ng-click="pickGroup()"> Add + + + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js index c3137360e2..315eb18ee4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js @@ -1,6 +1,6 @@ //this controller simply tells the dialogs service to open a memberPicker window //with a specified callback, this callback will receive an object with a selection on it -function memberPickerController($scope, entityResource, iconHelper, angularHelper, editorService){ +function memberPickerController($scope, entityResource, iconHelper, editorService){ function trim(str, chr) { var rgxtrim = (!chr) ? new RegExp('^\\s+|\\s+$', 'g') : new RegExp('^' + chr + '+|' + chr + '+$', 'g'); @@ -27,11 +27,16 @@ function memberPickerController($scope, entityResource, iconHelper, angularHelpe } else { $scope.clear(); $scope.add(data); - } - angularHelper.getCurrentForm($scope).$setDirty(); + } } }; + function setDirty() { + if ($scope.modelValueForm) { + $scope.modelValueForm.modelValue.$setDirty(); + } + } + //since most of the pre-value config's are used in the dialog options (i.e. maxNumber, minNumber, etc...) we'll merge the // pre-value config on to the dialog options if ($scope.model.config) { @@ -60,6 +65,7 @@ function memberPickerController($scope, entityResource, iconHelper, angularHelpe $scope.remove = function (index) { $scope.renderModel.splice(index, 1); + setDirty(); }; $scope.add = function (item) { @@ -76,7 +82,8 @@ function memberPickerController($scope, entityResource, iconHelper, angularHelpe if (currIds.indexOf(itemId) < 0) { item.icon = iconHelper.convertFromLegacyIcon(item.icon); - $scope.renderModel.push({ name: item.name, id: item.id, udi: item.udi, icon: item.icon}); + $scope.renderModel.push({ name: item.name, id: item.id, udi: item.udi, icon: item.icon }); + setDirty(); } }; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html index 99f7fffba8..4efa7283da 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html @@ -1,22 +1,23 @@
- +
- + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js index 172f9b2249..cfad66456d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js @@ -1,4 +1,4 @@ -function multiUrlPickerController($scope, angularHelper, localizationService, entityResource, iconHelper, editorService) { +function multiUrlPickerController($scope, localizationService, entityResource, iconHelper, editorService) { var vm = { labels: { @@ -16,8 +16,6 @@ function multiUrlPickerController($scope, angularHelper, localizationService, en $scope.model.value = []; } - var currentForm = angularHelper.getCurrentForm($scope); - $scope.sortableOptions = { axis: "y", containment: "parent", @@ -27,7 +25,7 @@ function multiUrlPickerController($scope, angularHelper, localizationService, en scroll: true, zIndex: 6000, update: function () { - currentForm.$setDirty(); + setDirty(); } }; @@ -66,7 +64,7 @@ function multiUrlPickerController($scope, angularHelper, localizationService, en $scope.remove = function ($index) { $scope.renderModel.splice($index, 1); - currentForm.$setDirty(); + setDirty(); }; $scope.openLinkPicker = function (link, $index) { @@ -122,7 +120,7 @@ function multiUrlPickerController($scope, angularHelper, localizationService, en link.published = true; } - currentForm.$setDirty(); + setDirty(); } editorService.close(); }, @@ -133,6 +131,12 @@ function multiUrlPickerController($scope, angularHelper, localizationService, en editorService.linkPicker(linkPicker); }; + function setDirty() { + if ($scope.multiUrlPickerForm) { + $scope.multiUrlPickerForm.modelValue.$setDirty(); + } + } + function init() { localizationService.localizeMany(["general_recycleBin"]) .then(function (data) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html index 503f4aac9b..12877bff88 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html @@ -18,9 +18,9 @@
+ + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js index f262647a0d..68d375360e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js @@ -8,7 +8,7 @@ angular.module('umbraco').run(['clipboardService', function (clipboardService) { - function clearNestedContentPropertiesForStorage(prop, propClearingMethod) { + function resolveNestedContentPropertiesForPaste(prop, propClearingMethod) { // if prop.editor is "Umbraco.NestedContent" if ((typeof prop === 'object' && prop.editor === "Umbraco.NestedContent")) { @@ -17,8 +17,8 @@ for (var i = 0; i < value.length; i++) { var obj = value[i]; - // remove the key - delete obj.key; + // generate a new key. + obj.key = String.CreateGuid(); // Loop through all inner properties: for (var k in obj) { @@ -28,10 +28,10 @@ } } - clipboardService.registerClearPropertyResolver(clearNestedContentPropertiesForStorage, clipboardService.TYPES.ELEMENT_TYPE) + clipboardService.registerPastePropertyResolver(resolveNestedContentPropertiesForPaste, clipboardService.TYPES.ELEMENT_TYPE) - function clearInnerNestedContentPropertiesForStorage(prop, propClearingMethod) { + function resolveInnerNestedContentPropertiesForPaste(prop, propClearingMethod) { // if we got an array, and it has a entry with ncContentTypeAlias this meants that we are dealing with a NestedContent property data. if ((Array.isArray(prop) && prop.length > 0 && prop[0].ncContentTypeAlias !== undefined)) { @@ -39,8 +39,8 @@ for (var i = 0; i < prop.length; i++) { var obj = prop[i]; - // remove the key - delete obj.key; + // generate a new key. + obj.key = String.CreateGuid(); // Loop through all inner properties: for (var k in obj) { @@ -50,7 +50,7 @@ } } - clipboardService.registerClearPropertyResolver(clearInnerNestedContentPropertiesForStorage, clipboardService.TYPES.RAW) + clipboardService.registerPastePropertyResolver(resolveInnerNestedContentPropertiesForPaste, clipboardService.TYPES.RAW) }]); angular @@ -105,12 +105,13 @@ localizationService.localizeMany(["grid_addElement", "content_createEmpty", "actions_copy"]).then(function (data) { labels.grid_addElement = data[0]; labels.content_createEmpty = data[1]; - labels.copy_icon_title = data[2] + labels.copy_icon_title = data[2]; }); - function setCurrentNode(node) { + function setCurrentNode(node, focusNode) { updateModel(); vm.currentNode = node; + vm.focusOnNode = focusNode; } var copyAllEntries = function () { @@ -168,11 +169,14 @@ method: removeAllEntries, isDisabled: true }; + // helper to force the current form into the dirty state function setDirty() { - if ($scope.$parent.$parent.propertyForm) { - $scope.$parent.$parent.propertyForm.$setDirty(); + + if (vm.umbProperty) { + vm.umbProperty.setDirty(); } + }; function addNode(alias) { @@ -180,7 +184,7 @@ var newNode = createNode(scaffold, null); - setCurrentNode(newNode); + setCurrentNode(newNode, true); setDirty(); validate(); }; @@ -202,7 +206,6 @@ }); const dialog = { - view: "itempicker", orderBy: "$index", view: "itempicker", event: $event, @@ -277,9 +280,9 @@ vm.editNode = function (idx) { if (vm.currentNode && vm.currentNode.key === vm.nodes[idx].key) { - setCurrentNode(null); + setCurrentNode(null, false); } else { - setCurrentNode(vm.nodes[idx]); + setCurrentNode(vm.nodes[idx], true); } }; @@ -500,7 +503,7 @@ setDirty(); //updateModel();// done by setting current node... - setCurrentNode(newNode); + setCurrentNode(newNode, true); } function checkAbilityToPasteContent() { @@ -592,7 +595,7 @@ // If there is only one item, set it as current node if (vm.singleMode || (vm.nodes.length === 1 && vm.maxItems === 1)) { - setCurrentNode(vm.nodes[0]); + setCurrentNode(vm.nodes[0], false); } validate(); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html index f853387612..aaebb5d07e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html @@ -16,7 +16,7 @@
+ umb-auto-focus="{{vm.focusOnNode && vm.currentNode.key === node.key ? 'true' : 'false'}}">
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/notsupported/notsupported.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/notsupported/notsupported.html index a2fbb0e907..f052415a05 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/notsupported/notsupported.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/notsupported/notsupported.html @@ -1,3 +1,3 @@
- +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js index f5f0f7f2a2..b0c3b88bc6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js @@ -1,4 +1,4 @@ -function sliderController($scope, angularHelper) { +function sliderController($scope) { let sliderRef = null; @@ -14,7 +14,13 @@ function setModelValue(values) { $scope.model.value = values ? values.toString() : null; - angularHelper.getCurrentForm($scope).$setDirty(); + setDirty(); + } + + function setDirty() { + if ($scope.modelValueForm) { + $scope.modelValueForm.modelValue.$setDirty(); + } } $scope.setup = function(slider) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html index 27c59194c1..567280b306 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html @@ -1,12 +1,14 @@ 
-
- - -
+ +
+ + +
+ +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.controller.js index 217a9c8421..2b0a5326f6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.controller.js @@ -10,6 +10,12 @@ function userPickerController($scope, iconHelper, editorService, overlayService, var multiPicker = $scope.model.config.multiPicker && $scope.model.config.multiPicker !== '0' ? true : false; + function setDirty() { + if ($scope.modelValueForm) { + $scope.modelValueForm.modelValue.$setDirty(); + } + } + $scope.openUserPicker = function () { var currentSelection = []; @@ -42,7 +48,7 @@ function userPickerController($scope, iconHelper, editorService, overlayService, submit: function () { $scope.renderModel.splice(index, 1); $scope.userName = ''; - + setDirty(); overlayService.close(); }, close: function () { @@ -68,11 +74,13 @@ function userPickerController($scope, iconHelper, editorService, overlayService, if (currIds.indexOf(itemId) < 0) { item.icon = item.icon ? iconHelper.convertFromLegacyIcon(item.icon) : "icon-user"; $scope.renderModel.push({ name: item.name, id: item.id, udi: item.udi, icon: item.icon, avatars: item.avatars }); + setDirty(); } }; $scope.clear = function() { $scope.renderModel = []; + setDirty(); }; var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.html index 8345317eee..331f5e0a94 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.html @@ -1,21 +1,22 @@
-
- +
+ -
+
- + - + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/relationTypes/views/relationType.html b/src/Umbraco.Web.UI.Client/src/views/relationTypes/views/relationType.html index 100d8d9d09..8f910a6c86 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationTypes/views/relationType.html +++ b/src/Umbraco.Web.UI.Client/src/views/relationTypes/views/relationType.html @@ -1,46 +1,63 @@
- - - - -
{{model.relationType.id}}
- {{model.relationType.key}} -
- - -
    -
  • - - -
  • -
  • - - -
  • -
-
+
- - -
{{model.relationType.parentObjectTypeName}}
-
+
- - -
{{model.relationType.childObjectTypeName}}
-
+ + - - -
{{model.relationType.relations.length}}
-
-
-
+ + +
    +
  • + + +
  • +
  • + + +
  • +
+
+ + + +
{{model.relationType.parentObjectTypeName}}
+
+ + + +
{{model.relationType.childObjectTypeName}}
+
+ + + +
{{model.relationType.relations.length}}
+
+ + + +
+ +
+ + + + +
{{model.relationType.id}}
+ {{model.relationType.key}} +
+
+
+
+ +
+
diff --git a/src/Umbraco.Web.UI.NetCore/Views/Partials/grid/bootstrap3-fluid.cshtml b/src/Umbraco.Web.UI.NetCore/Views/Partials/grid/bootstrap3-fluid.cshtml index 8832f1752a..7e349bd7f3 100644 --- a/src/Umbraco.Web.UI.NetCore/Views/Partials/grid/bootstrap3-fluid.cshtml +++ b/src/Umbraco.Web.UI.NetCore/Views/Partials/grid/bootstrap3-fluid.cshtml @@ -7,7 +7,7 @@ Razor helpers located at the bottom of this file *@ -@if (Model != null && Model.sections != null) +@if (Model != null && Model.GetType() == typeof(JObject) && Model.sections != null) { var oneColumn = ((System.Collections.ICollection)Model.sections).Count == 1; diff --git a/src/Umbraco.Web.UI.NetCore/Views/Partials/grid/bootstrap3.cshtml b/src/Umbraco.Web.UI.NetCore/Views/Partials/grid/bootstrap3.cshtml index 65790d31fb..cf35714692 100644 --- a/src/Umbraco.Web.UI.NetCore/Views/Partials/grid/bootstrap3.cshtml +++ b/src/Umbraco.Web.UI.NetCore/Views/Partials/grid/bootstrap3.cshtml @@ -3,7 +3,7 @@ @using Newtonsoft.Json.Linq @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage -@if (Model != null && Model.sections != null) +@if (Model != null && Model.GetType() == typeof(JObject) && Model.sections != null) { var oneColumn = ((System.Collections.ICollection)Model.sections).Count == 1; diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml index 8416bff059..12a3c420fb 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml @@ -46,7 +46,7 @@

Umbraco logo Umbraco

For full functionality of Umbraco CMS it is necessary to enable JavaScript.

-

Here are the instructions how to enable JavaScript in your web browser.

+

Here are the instructions how to enable JavaScript in your web browser.

@@ -114,7 +114,6 @@ @await Html.AngularValueExternalLoginInfoScriptAsync(externalLogins, ViewData.GetExternalSignInProviderErrors()) @Html.AngularValueResetPasswordCodeInfoScript(ViewData[ViewDataExtensions.TokenPasswordResetCode]) @await Html.AngularValueTinyMceAssetsAsync(runtimeMinifier) - //required for the noscript trick document.getElementById("mainwrapper").style.display = "inherit"; } diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoWebsite/NoNodes.cshtml b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoWebsite/NoNodes.cshtml index d790fd4bf7..694d66c056 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoWebsite/NoNodes.cshtml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoWebsite/NoNodes.cshtml @@ -29,14 +29,14 @@

Easy start with Umbraco.tv

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.

- Umbraco.tv → + Umbraco.tv →

Be a part of the community

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.

- our.Umbraco → + our.Umbraco →
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žky Cíl This 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í okna byl otevřený v novém okně Restart Navš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 makro Pole 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 zde Musíte udělit ASP.NET oprávnění měnit následující soubory/složky Vaš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šit Klikněte zde, chcete-li číst textovou verzi vý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é!

- Jste připraveni provozovat umbraco a instalovat balíčky!]]>
+ Jste připraveni provozovat Umbraco a instalovat balíčky!]]> Řešení potíží se složkami Následujte tento odkaz pro další informace o potížích s ASP.NET a vytvářením složek. Nastavování oprávnění pro složky Chci začít od nuly @@ -898,7 +898,7 @@ Abyste získali pomoc od naší oceňované komunity, projděte si dokumentaci, nebo si pusťte některá videa zdarma o tom, jak vytvořit jednoduchý web, jak používat balíčky a rychlý úvod do terminologie umbraca]]> Umbraco %0% je nainstalováno a připraveno k použití soubor /web.config a upravit klíč AppSetting umbracoConfigurationStatus dole na hodnotu '%0%'.]]> - ihned začít kliknutím na tlačítko "Spustit Umbraco" níže.
Jestliže je pro Vás umbraco nové, + ihned začít kliknutím na tlačítko "Spustit Umbraco" níže.
Jestliže je pro Vás Umbraco nové, spoustu zdrojů naleznete na naších stránkách "začínáme".]]>
Spustit Umbraco Chcete-li spravovat Váš web, jednoduše přejděte do administrace umbraca a začněte přidávat obsah, upravovat šablony a stylopisy, nebo přidávat nové funkce]]> @@ -929,7 +929,7 @@ přihlašte se níže Přihlásit se pomocí Relace vypršela - © 2001 - %0%
umbraco.org

]]> + © 2001 - %0%
umbraco.org

]]>
Zapomenuté heslo? Na uvedenou adresu bude zaslán e-mail s odkazem pro obnovení hesla Pokud odpovídá našim záznamům, bude na zadanou adresu zaslán e-mail s pokyny k obnovení hesla @@ -980,14 +980,14 @@ Vyžadováno resetování hesla

- Vaše uživatelské jméno pro přihlášení do back-office Umbraco je: %0% + Vaše uživatelské jméno pro přihlášení do backoffice Umbraco je: %0%

@@ -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žky Nadřazený typ obsahu povolen Tento 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ých Na 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í šablonu Př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.

Klik på Forsøg igen knappen når du er færdig.
Mere information om at redigere web.config her.

]]>
+

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.

Klik på Forsøg igen knappen når du er færdig.
Mere information om at redigere web.config her.

]]>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!

]]>
Tryk på Næste for at fortsætte.]]> @@ -898,7 +909,7 @@ Log ind nedenforLog ind medDin session er udløbet - © 2001 - %0%
umbraco.com

]]>
+ © 2001 - %0%
umbraco.com

]]>
Glemt adgangskode?En e-mail vil blive sendt til den angivne adresse med et link til at nulstille din adgangskodeEn e-mail med instruktioner for nulstilling af adgangskoden vil blive sendt til den angivne adresse, hvis det matcher vores optegnelser @@ -950,7 +961,7 @@ Mange hilsner fra Umbraco robotten

Dette er en automatisk mail for at informere dig om at opgaven '%1%' er blevet udførtpå siden '%2%' af brugeren '%3%'

Opdateringssammendrag:

- + Kliknutím na tento odkaz obnovíte své heslo
- + Kliknutím na tento odkaz přijměte pozvání
%6%

Hav en fortsat god dag!

De bedste hilsner fra umbraco robotten

]]> +      RET       

Opdateringssammendrag:

%6%

Hav en fortsat god dag!

De bedste hilsner fra Umbraco robotten

]]> [%0%] Notificering om %1% udført på %2% Notificeringer @@ -1590,7 +1601,7 @@ Mange hilsner fra Umbraco robotten er ikke blevet låst ude Kodeordet er ikke blevet ændret Gentag 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' Indholdskanal Opret endnu en bruger Opret 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 invitation Tilbage til brugere Umbraco: Invitation -

Hej %0%, du er blevet inviteret af %1% til Umbraco backoffice.

Besked fra %1%: %2%

Klik på dette link for acceptere invitationen

Hvis du ikke kan klikke på linket, så kopier og indsæt denne URL i dit browservindue

%3%

]]>
+

Hej %0%, du er blevet inviteret af %1% til Umbraco backoffice.

Besked fra %1%: %2%

Klik på dette link for acceptere invitationen

Hvis du ikke kan klikke på linket, så kopier og indsæt denne URL i dit browservindue

%3%

]]>
Alle Aktiv Deaktiveret @@ -1692,10 +1703,16 @@ Mange hilsner fra Umbraco robotten Du kan kun have Tilføj op til elementer + URL(er) + URL(er) valgt elementer valgt Ugyldig dato Ikke et tal + Ikke en gyldig numerisk trinstørrelse Ugyldig e-mail + Værdien kan ikke være tom + Værdien kan ikke være tom + Værdien er ugyldig, som ikke matcher det korrekte format %1% mere.]]> %1% for mange.]]> @@ -1853,7 +1870,7 @@ Mange hilsner fra Umbraco robotten Label Speciel visning Vis speciel visning beskrivelsen - Overskrift hvordan denne block præsenteres i BackOffice interfacet. Vælg en .html fil der indeholder din præsensation. + Overskrift hvordan denne block præsenteres i backoffice interfacet. Vælg en .html fil der indeholder din præsensation. Indstillings model Rederings lagets størrelse Tilføj speciel visning @@ -1875,7 +1892,28 @@ Mange hilsner fra Umbraco robotten Error! The ElementType of this block does not exist anymore + Tilføj indhold + Tilføj %0% + Feltet %0% bruger editor %1% som ikke er supporteret for blokke. + + + Hvad er Indholdsskabeloner? + Indholdsskabeloner er foruddefineret indhold der kan vælges når der oprettes nye indholdselementer. + Hvordan opretter jeg en Indholdsskabelon? + + Der er to måder at oprette Indholdsskabeloner på:

+
    +
  • Højreklik på en indholdsnode og vælg "Opret indholdsskabelon" for at oprette en ny Indholdsskabelon.
  • +
  • Højreklik på Indholdsskabeloner i sektionen Indstillinger og vælg den dokumenttype du vil oprette en Indholdsskabelon for.
  • +
+

Når indholdsskabelonen har fået et navn, kan redaktører begynde at bruge indholdsskabelonen som udgangspunkt for deres nye side.

+ ]]> +
+ Hvordan vedligeholder jeg Indholdsskabeloner? + Du kan redigere og slette Indholdsskabeloner fra "Indholdsskabeloner" i sektionen Indstillinger. Fold dokumenttypen som Indholdsskabelonen er baseret på ud og klik på den for at redigere eller slette den. + Afslut Afslut forhåndsvisning diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml index 7d61559280..4b8e790602 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml @@ -284,7 +284,7 @@ Dies führt zur folgenden Zeit auf dem Server: Was bedeutet dies? + Was bedeutet dies? ]]> Wollen Sie dieses Element wirklich entfernen? @@ -445,7 +445,7 @@ Der Papierkorb wird geleert. Bitte warten Sie und schließen Sie das Fenster erst, wenn der Vorgang abgeschlossen ist. Der Papierkorb ist leer Wenn Sie den Papierkorb leeren, werden die enthaltenen Elemente endgültig gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden. - Der Webservice von <a target='_blank' href='http://regexlib.com'>regexlib.com</a> ist zur Zeit nicht erreichbar. Bitte versuchen Sie es später erneut. + Der Webservice von <a target='_blank' rel='noopener' href='http://regexlib.com'>regexlib.com</a> ist zur Zeit nicht erreichbar. Bitte versuchen Sie es später erneut. Finden Sie einen vorbereiteten regulären Ausdruck zur Validierung der Werte, die in dieses Feld eingegeben werden - zum Beispiel 'email, 'plz', 'URL' oder ähnlich. Macro entfernen Pflichtfeld @@ -927,7 +927,7 @@ Hier anmelden: Anmelden mit Sitzung abgelaufen - <p style="text-align:right;">&copy; 2001 - %0% <br /><a href="https://umbraco.com" style="text-decoration: none" target="_blank">umbraco.org</a></p> + <p style="text-align:right;">&copy; 2001 - %0% <br /><a href="https://umbraco.com" style="text-decoration: none" target="_blank" rel="noopener">umbraco.org</a></p> Kennwort vergessen? Es wird eine E-Mail mit einem Kennwort-Zurücksetzen-Link an die angegebene Adresse geschickt. Es wird eine E-Mail mit Anweisungen zum Zurücksetzen des Kennwortes an die angegebene Adresse geschickt sofern diese im Datenbestand gefunden wurde. @@ -986,7 +986,7 @@ - + Klicken Sie hier, um Ihr Kennwort zurück zu setzen @@ -1104,7 +1104,7 @@
- Bearbeiten
+ Bearbeiten @@ -1388,7 +1388,6 @@ Registerkarten Masterdokumenttyp aktiviert Dieser Dokumenttyp verwendet - als Masterdokumenttyp. Register vom Masterdokumenttyp werden nicht angezeigt und können nur im Masterdokumenttyp selbst bearbeitet werden Für dieses Register sind keine Eigenschaften definiert. Klicken Sie oben auf "neue Eigenschaft hinzufügen", um eine neue Eigenschaft hinzuzufügen. Zugehörige Vorlage anlegen Bildsymbol hinzufügen @@ -2006,7 +2005,7 @@ - + Um diese Einladung anzunehmen,
klicken Sie diese Schaltfläche
diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml index bd45345660..8d20b69693 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml @@ -66,7 +66,7 @@ Allow access to assign culture and hostnames Allow access to view a node's history log Allow access to view a node - Allow access to change document type for a node + Allow access to change Document Type for a node Allow access to copy a node Allow access to create nodes Allow access to delete nodes @@ -190,12 +190,12 @@ History (all variants) - To change the document type for the selected content, first select from the list of valid types for this location. + To change the Document Type for the selected content, first select from the list of valid types for this location. Then confirm and/or amend the mapping of properties from the current type to the new, and click Save. The content has been re-published. Current Property Current type - The document type cannot be changed, as there are no alternatives valid for this location. An alternative will be valid if it is allowed under the parent of the selected content item and that all existing child content items are allowed to be created under it. + The Document Type cannot be changed, as there are no alternatives valid for this location. An alternative will be valid if it is allowed under the parent of the selected content item and that all existing child content items are allowed to be created under it. Document Type Changed Map Properties Map to Property @@ -204,7 +204,7 @@ none Content Select New Document Type - The document type of the selected content has been successfully changed to [new type] and the following properties mapped: + The Document Type of the selected content has been successfully changed to [new type] and the following properties mapped: to Could not complete property mapping as one or more properties have more than one mapping defined. Only alternate types valid for the current location are displayed. @@ -283,14 +283,14 @@ Child items Target This 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? Property %0% uses editor %1% which is not supported by Nested Content. Are you sure you want to delete all items? - No content types are configured for this property. - Add element type - Select element type - Select the group whose properties should be displayed. If left blank, the first group on the element type will be used. + No Content Types are configured for this property. + Add Element Type + Select Element Type + Select the group whose properties should be displayed. If left blank, the first group on the Element Type will be used. Enter an angular expression to evaluate against each item for its name. Use to display the item index Add another text box @@ -355,21 +355,32 @@ All Members Member groups have no additional properties for editing. + + Failed to copy content type + Failed to move content type + + + Failed to copy media type + Failed to move media type + + + Failed to copy member type + Where do you want to create the new %0% Create an item under - Select the document type you want to make a content template for + Select the Document Type you want to make a content template for Enter a folder name Choose a type and a title - Document Types within the Settings section, by editing the Allowed child node types under Permissions.]]> - Document Types within the Settings section.]]> + Document Types within the Settings section, by editing the Allowed child node types under Permissions.]]> + Document Types within the Settings section.]]> The selected page in the content tree doesn't allow for any pages to be created below it. - Edit permissions for this document type - Create a new document type - Document Types within the Settings section, by changing the Allow as root option under Permissions.]]> - Media Types Types within the Settings section, by editing the Allowed child node types under Permissions.]]> + Edit permissions for this Document Type + Create a new Document Type + Document Types within the Settings section, by changing the Allow as root option under Permissions.]]> + Media Types within the Settings section, by editing the Allowed child node types under Permissions.]]> The selected media in the tree doesn't allow for any other media to be created below it. - Edit permissions for this media type + Edit permissions for this Media Types Document Type without a template Document Type with Template The data definition for a content page that can be created by editors in the content tree and is directly accessible via a URL. @@ -382,7 +393,7 @@ Folder Used to organise the Document Types, Compositions and Element Types created in this Document Type tree. New folder - New data type + New Data Type New JavaScript file New empty partial view New partial view macro @@ -477,7 +488,7 @@ The items in the recycle bin are now being deleted. Please do not close this window while this operation takes place The recycle bin is now empty When items are deleted from the recycle bin, they will be gone forever - regexlib.com's webservice is currently experiencing some problems, which we have no control over. We are very sorry for this inconvenience.]]> + regexlib.com's webservice is currently experiencing some problems, which we have no control over. We are very sorry for this inconvenience.]]> Search for a regular expression to add validation to a form field. Example: 'email, 'zip-code', 'URL'. Remove Macro Required Field @@ -566,7 +577,7 @@ Tools to manage the index fields The index cannot be read and will need to be rebuilt - The process is taking longer than expected, check the umbraco log to see if there have been any errors during this operation + The process is taking longer than expected, check the Umbraco log to see if there have been any errors during this operation This index cannot be rebuilt because it has no assigned IIndexPopulator @@ -597,7 +608,7 @@ Create custom list view Remove custom list view - A content type, media type or member type with this alias already exists + A Content Type, Media Type or Member Type with this alias already exists Renamed @@ -617,9 +628,9 @@ Show label Width and height All property types & property data - using this data type will be deleted permanently, please confirm you want to delete these as well + using this Data Type will be deleted permanently, please confirm you want to delete these as well Yes, delete - and all property types & property data using this data type + and all property types & property data using this Data Type Select the folder to move to in the tree structure below was moved underneath @@ -636,7 +647,6 @@ %0% is a mandatory field %0% at %1% is not in a correct format %0% is not in a correct format - Property '%0%' uses editor '%1%' which is not supported in Element Types. Received an error from the server @@ -673,6 +683,7 @@ Clear Close Close Window + Close Pane Comment Confirm Constrain @@ -910,7 +921,7 @@ ]]> I want to start from scratch learn how) You can still choose to install Runway later on. Please go to the Developer section and choose Packages. ]]> @@ -924,7 +935,7 @@ I want to start with a simple website - "Runway" is a simple website providing some basic document types and templates. The installer can set up Runway for you automatically, + "Runway" is a simple website providing some basic Document Types and templates. The installer can set up Runway for you automatically, but you can easily edit, extend or remove it. It's not necessary and you can perfectly use Umbraco without it. However, Runway offers an easy foundation based on best practices to get you started faster than ever. If you choose to install Runway, you can optionally select basic building blocks called Runway Modules to enhance your Runway pages. @@ -951,7 +962,7 @@ Get help from our award winning community, browse the documentation or watch som started instantly by clicking the "Launch Umbraco" button below.
If you are new to Umbraco, you can find plenty of resources on our getting started pages.]]>
Launch Umbraco -To manage your website, simply open the Umbraco back office and start adding content, updating the templates and stylesheets or add new functionality]]> +To manage your website, simply open the Umbraco backoffice and start adding content, updating the templates and stylesheets or add new functionality]]>
Connection to database failed. Umbraco Version 3 Umbraco Version 4 @@ -979,7 +990,7 @@ To manage your website, simply open the Umbraco back office and start adding con Log in below Sign in with Session timed out - © 2001 - %0%
Umbraco.com

]]>
+ © 2001 - %0%
Umbraco.com

]]>
Forgotten password? An email will be sent to the address specified with a link to reset your password An email with password reset instructions will be sent to the specified address if it matched our records @@ -1030,14 +1041,14 @@ To manage your website, simply open the Umbraco back office and start adding con Password reset requested

- Your username to login to the Umbraco back-office is: %0% + Your username to login to the Umbraco backoffice is: %0%

@@ -1160,7 +1171,7 @@ To manage your website, simply open the Umbraco back office and start adding con
- + Click this link to reset your password
- EDIT
+ EDIT
@@ -1403,7 +1414,7 @@ To manage your website, simply open the Umbraco back office and start adding con Default template - To import a document type, find the ".udt" file on your computer by clicking the "Browse" button and click "Import" (you'll be asked for confirmation on the next screen) + To import a Document Type, find the ".udt" file on your computer by clicking the "Browse" button and click "Import" (you'll be asked for confirmation on the next screen) New Tab Title Node type Type @@ -1414,7 +1425,6 @@ To manage your website, simply open the Umbraco back office and start adding con Tabs Master Content Type enabled This Content Type uses - as a Master Content Type. Tabs from Master Content Types are not shown and can only be edited on the Master Content Type itself No properties defined on this tab. Click on the "add a new property" link at the top to create a new property. Create matching template Add icon @@ -1500,8 +1510,8 @@ To manage your website, simply open the Umbraco back office and start adding con User %0% was deleted Invite user Invitation has been re-sent to %0% - Document type was exported to file - An error occurred while exporting the document type + Document Type was exported to file + An error occurred while exporting the Document Type Add style @@ -1662,10 +1672,10 @@ To manage your website, simply open the Umbraco back office and start adding con Allowed child node types Allow content of the specified types to be created underneath content of this type. Choose child node - Inherit tabs and properties from an existing document type. New tabs will be added to the current document type or merged if a tab with an identical name exists. - This content type is used in a composition, and therefore cannot be composed itself. - There are no content types available to use as a composition. - Removing a composition will delete all the associated property data. Once you save the document type there's no way back. + Inherit tabs and properties from an existing Document Type. New tabs will be added to the current Document Type or merged if a tab with an identical name exists. + This Content Type is used in a composition, and therefore cannot be composed itself. + There are no Content Types available to use as a composition. + Removing a composition will delete all the associated property data. Once you save the Document Type there's no way back. Create new Use existing Editor settings @@ -1676,12 +1686,12 @@ To manage your website, simply open the Umbraco back office and start adding con Select the folder to move Select the folder to copy to in the tree structure below - All Document types + All Document Types All Documents All media items - using this document type will be deleted permanently, please confirm you want to delete these as well. - using this media type will be deleted permanently, please confirm you want to delete these as well. - using this member type will be deleted permanently, please confirm you want to delete these as well + using this Document Type will be deleted permanently, please confirm you want to delete these as well. + using this Media Type will be deleted permanently, please confirm you want to delete these as well. + using this Member Type will be deleted permanently, please confirm you want to delete these as well and all documents using this type and all media items using this type and all members using this type @@ -1704,11 +1714,11 @@ To manage your website, simply open the Umbraco back office and start adding con Allow editors to create segments of this content. Allow varying by culture Allow segmentation - Element type - Is an Element type - An Element type is meant to be used for instance in Nested Content, and not in the tree. - A document type cannot be changed to an Element type once it has been used to create one or more content items. - This is not applicable for an Element type + Element Type + Is an Element Type + An Element Type is meant to be used for instance in Nested Content, and not in the tree. + A document Type cannot be changed to an Element Type once it has been used to create one or more content items. + This is not applicable for an Element Type You have made changes to this property. Are you sure you want to discard them? Appearance Label above (full-width) @@ -1868,10 +1878,12 @@ To manage your website, simply open the Umbraco back office and start adding con Change your password Change photo New password + Minimum %0% character(s) to go! + There should be at least %0% special character(s) in there. hasn't been locked out The password hasn't been changed Confirm new password - You can change your password for accessing the Umbraco Back Office by filling out the form below and click the 'Change Password' button + You can change your password for accessing the Umbraco backoffice by filling out the form below and click the 'Change Password' button Content Channel Create another user Create new users to give them access to Umbraco. When a new user is created a password will be generated that you can share with the user. @@ -2004,7 +2016,7 @@ To manage your website, simply open the Umbraco back office and start adding con - + Click this link to accept the invite @@ -2077,7 +2089,11 @@ To manage your website, simply open the Umbraco back office and start adding con items selected Invalid date Not a number + Not a valid numeric step size Invalid email + Value cannot be null + Value cannot be empty + Value is invalid, it does not match the correct pattern Custom validation %1% more.]]> %1% too many.]]> @@ -2240,7 +2256,7 @@ To manage your website, simply open the Umbraco back office and start adding con Created Comment Name - No relations for this relation type. + No relations for this Relation Type Relation Type Relations @@ -2284,7 +2300,7 @@ To manage your website, simply open the Umbraco back office and start adding con Partial View Partial View Macro Member - Data type + Data Type Search the redirect dashboard Search the user group section Search the users section @@ -2305,6 +2321,7 @@ To manage your website, simply open the Umbraco back office and start adding con Select one of the options to edit the node. Perform action %0% on the %1% node Add image caption + Search content tree References @@ -2510,7 +2527,7 @@ To manage your website, simply open the Umbraco back office and start adding con Label Custom view Show custom view description - Overwrite how this block appears in the BackOffice UI. Pick a .html file containing your presentation. + Overwrite how this block appears in the backoffice UI. Pick a .html file containing your presentation. Settings model Overlay editor size Add custom view @@ -2532,6 +2549,9 @@ To manage your website, simply open the Umbraco back office and start adding con Error! The ElementType of this block does not exist anymore + Add content + Add %0% + Property '%0%' uses editor '%1%' which is not supported in blocks. What are Content Templates? @@ -2570,4 +2590,8 @@ To manage your website, simply open the Umbraco back office and start adding con File writing Media folder creation + + item returned + items returned + diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml index 7d59dbba63..3885f5e338 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml @@ -67,7 +67,7 @@ Allow access to assign culture and hostnames Allow access to view a node's history log Allow access to view a node - Allow access to change document type for a node + Allow access to change Document Type for a node Allow access to copy a node Allow access to create nodes Allow access to delete nodes @@ -193,12 +193,12 @@ History (all variants) - To change the document type for the selected content, first select from the list of valid types for this location. + To change the Document Type for the selected content, first select from the list of valid types for this location. Then confirm and/or amend the mapping of properties from the current type to the new, and click Save. The content has been re-published. Current Property Current type - The document type cannot be changed, as there are no alternatives valid for this location. An alternative will be valid if it is allowed under the parent of the selected content item and that all existing child content items are allowed to be created under it. + The Document Type cannot be changed, as there are no alternatives valid for this location. An alternative will be valid if it is allowed under the parent of the selected content item and that all existing child content items are allowed to be created under it. Document Type Changed Map Properties Map to Property @@ -207,7 +207,7 @@ none Content Select New Document Type - The document type of the selected content has been successfully changed to [new type] and the following properties mapped: + The Document Type of the selected content has been successfully changed to [new type] and the following properties mapped: to Could not complete property mapping as one or more properties have more than one mapping defined. Only alternate types valid for the current location are displayed. @@ -288,14 +288,14 @@ Child items Target This 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. - No content types are configured for this property. - Add element type - Select element type - Select the group whose properties should be displayed. If left blank, the first group on the element type will be used. + No Content Types are configured for this property. + Add Element Type + Select Element Type + Select the group whose properties should be displayed. If left blank, the first group on the Element Type will be used. Enter an angular expression to evaluate against each item for its name. Use to display the item index Add another text box @@ -362,21 +362,32 @@ All Members Member groups have no additional properties for editing. + + Failed to copy content type + Failed to move content type + + + Failed to copy media type + Failed to move media type + + + Failed to copy member type + Where do you want to create the new %0% Create an item under - Select the document type you want to make a content template for + Select the Document Type you want to make a content template for Enter a folder name Choose a type and a title - Document Types within the Settings section, by editing the Allowed child node types under Permissions.]]> - Document Types within the Settings section.]]> + Document Types within the Settings section, by editing the Allowed child node types under Permissions.]]> + Document Types within the Settings section.]]> The selected page in the content tree doesn't allow for any pages to be created below it. - Edit permissions for this document type - Create a new document type - Document Types within the Settings section, by changing the Allow as root option under Permissions.]]> - Media Types Types within the Settings section, by editing the Allowed child node types under Permissions.]]> + Edit permissions for this Document Type + Create a new Document Type + Document Types within the Settings section, by changing the Allow as root option under Permissions.]]> + Media Types Types within the Settings section, by editing the Allowed child node types under Permissions.]]> The selected media in the tree doesn't allow for any other media to be created below it. - Edit permissions for this media type + Edit permissions for this Media Type Document Type without a template Document Type with Template The data definition for a content page that can be created by editors in the content tree and is directly accessible via a URL. @@ -389,7 +400,7 @@ Folder Used to organise the Document Types, Compositions and Element Types created in this Document Type tree. New folder - New data type + New Data Type New JavaScript file New empty partial view New partial view macro @@ -482,7 +493,7 @@ The items in the recycle bin are now being deleted. Please do not close this window while this operation takes place The recycle bin is now empty When items are deleted from the recycle bin, they will be gone forever - regexlib.com's webservice is currently experiencing some problems, which we have no control over. We are very sorry for this inconvenience.]]> + regexlib.com's webservice is currently experiencing some problems, which we have no control over. We are very sorry for this inconvenience.]]> Search for a regular expression to add validation to a form field. Example: 'email, 'zip-code', 'URL'. Remove Macro Required Field @@ -572,7 +583,7 @@ Tools to manage the index fields The index cannot be read and will need to be rebuilt - The process is taking longer than expected, check the umbraco log to see if there have been any errors during this operation + The process is taking longer than expected, check the Umbraco log to see if there have been any errors during this operation This index cannot be rebuilt because it has no assigned IIndexPopulator @@ -602,7 +613,7 @@ Create custom list view Remove custom list view - A content type, media type or member type with this alias already exists + A Content Type, Media Type or Member Type with this alias already exists Renamed @@ -622,9 +633,9 @@ Show label Width and height All property types & property data - using this data type will be deleted permanently, please confirm you want to delete these as well + using this Data Type will be deleted permanently, please confirm you want to delete these as well Yes, delete - and all property types & property data using this data type + and all property types & property data using this Data Type Select the folder to move to in the tree structure below was moved underneath @@ -660,7 +671,6 @@ Please place cursor at the left of the two cells you wish to merge You cannot split a cell that hasn't been merged. This property is invalid - Property '%0%' uses editor '%1%' which is not supported in Element Types. Options @@ -681,6 +691,7 @@ Clear Close Close Window + Close Pane Comment Confirm Constrain @@ -917,7 +928,7 @@ ]]> I want to start from scratch learn how) You can still choose to install Runway later on. Please go to the Developer section and choose Packages. ]]> @@ -931,7 +942,7 @@ I want to start with a simple website - "Runway" is a simple website providing some basic document types and templates. The installer can set up Runway for you automatically, + "Runway" is a simple website providing some basic Document Types and templates. The installer can set up Runway for you automatically, but you can easily edit, extend or remove it. It's not necessary and you can perfectly use Umbraco without it. However, Runway offers an easy foundation based on best practices to get you started faster than ever. If you choose to install Runway, you can optionally select basic building blocks called Runway Modules to enhance your Runway pages. @@ -958,7 +969,7 @@ Get help from our award winning community, browse the documentation or watch som started instantly by clicking the "Launch Umbraco" button below.
If you are new to Umbraco, you can find plenty of resources on our getting started pages.]]>
Launch Umbraco -To manage your website, simply open the Umbraco back office and start adding content, updating the templates and stylesheets or add new functionality]]> +To manage your website, simply open the Umbraco backoffice and start adding content, updating the templates and stylesheets or add new functionality]]>
Connection to database failed. Umbraco Version 3 Umbraco Version 4 @@ -986,7 +997,7 @@ To manage your website, simply open the Umbraco back office and start adding con Log in below Sign in with Session timed out - © 2001 - %0%
Umbraco.com

]]> + © 2001 - %0%
Umbraco.com

]]>
Forgotten password? An email will be sent to the address specified with a link to reset your password An email with password reset instructions will be sent to the specified address if it matched our records @@ -1037,14 +1048,14 @@ To manage your website, simply open the Umbraco back office and start adding con Password reset requested

- Your username to login to the Umbraco back-office is: %0% + Your username to login to the Umbraco backoffice is: %0%

@@ -1165,7 +1176,7 @@ To manage your website, simply open the Umbraco back office and start adding con
- + Click this link to reset your password
- EDIT
+ EDIT
@@ -1405,7 +1416,7 @@ To manage your website, simply open the Umbraco back office and start adding con Default template - To import a document type, find the ".udt" file on your computer by clicking the "Browse" button and click "Import" (you'll be asked for confirmation on the next screen) + To import a Document Type, find the ".udt" file on your computer by clicking the "Browse" button and click "Import" (you'll be asked for confirmation on the next screen) New Tab Title Node type Type @@ -1416,7 +1427,6 @@ To manage your website, simply open the Umbraco back office and start adding con Tabs Master Content Type enabled This Content Type uses - as a Master Content Type. Tabs from Master Content Types are not shown and can only be edited on the Master Content Type itself No properties defined on this tab. Click on the "add a new property" link at the top to create a new property. Create matching template Add icon @@ -1512,8 +1522,8 @@ To manage your website, simply open the Umbraco back office and start adding con Invitation has been re-sent to %0% Cannot publish the document since the required '%0%' is not published Validation failed for language '%0%' - Document type was exported to file - An error occurred while exporting the document type + Document Type was exported to file + An error occurred while exporting the Document Type The release date cannot be in the past Cannot schedule the document for publishing since the required '%0%' is not published Cannot schedule the document for publishing since the required '%0%' has a publish date later than a non mandatory language @@ -1679,10 +1689,10 @@ To manage your website, simply open the Umbraco back office and start adding con Allowed child node types Allow content of the specified types to be created underneath content of this type. Choose child node - Inherit tabs and properties from an existing document type. New tabs will be added to the current document type or merged if a tab with an identical name exists. - This content type is used in a composition, and therefore cannot be composed itself. - There are no content types available to use as a composition. - Removing a composition will delete all the associated property data. Once you save the document type there's no way back. + Inherit tabs and properties from an existing Document Type. New tabs will be added to the current Document Type or merged if a tab with an identical name exists. + This Content Type is used in a composition, and therefore cannot be composed itself. + There are no Content Types available to use as a composition. + Removing a composition will delete all the associated property data. Once you save the Document Type there's no way back. Create new Use existing Editor settings @@ -1695,12 +1705,12 @@ To manage your website, simply open the Umbraco back office and start adding con Select the folder to move Select the folder to copy to in the tree structure below - All Document types + All Document Types All Documents All media items - using this document type will be deleted permanently, please confirm you want to delete these as well. - using this media type will be deleted permanently, please confirm you want to delete these as well. - using this member type will be deleted permanently, please confirm you want to delete these as well + using this Document Type will be deleted permanently, please confirm you want to delete these as well. + using this Media Type will be deleted permanently, please confirm you want to delete these as well. + using this Member Type will be deleted permanently, please confirm you want to delete these as well and all documents using this type and all media items using this type and all members using this type @@ -1712,7 +1722,7 @@ To manage your website, simply open the Umbraco back office and start adding con Allow this property value to be displayed on the member profile page tab has no sort order Where is this composition used? - This composition is currently used in the composition of the following content types: + This composition is currently used in the composition of the following Content Types: Allow variations Allow vary by culture Allow segmentation @@ -1723,11 +1733,11 @@ To manage your website, simply open the Umbraco back office and start adding con Allow editors to create segments of this content. Allow varying by culture Allow segmentation - Element type - Is an element type - An element type is meant to be used for instance in Nested Content, and not in the tree. - A document type cannot be changed to an element type once it has been used to create one or more content items. - This is not applicable for an element type + Element Type + Is an Element Type + An Element Type is meant to be used for instance in Nested Content, and not in the tree. + A Document Type cannot be changed to an Element Type once it has been used to create one or more content items. + This is not applicable for an Element Type You have made changes to this property. Are you sure you want to discard them? Appearance Label above (full-width) @@ -1886,10 +1896,12 @@ To manage your website, simply open the Umbraco back office and start adding con Change your password Change photo New password + Minimum %0% character(s) to go! + There should be at least %0% special character(s) in there. hasn't been locked out The password hasn't been changed Confirm new password - You can change your password for accessing the Umbraco Back Office by filling out the form below and click the 'Change Password' button + You can change your password for accessing the Umbraco backoffice by filling out the form below and click the 'Change Password' button Content Channel Create another user Create new users to give them access to Umbraco. When a new user is created a password will be generated that you can share with the user. @@ -2022,7 +2034,7 @@ To manage your website, simply open the Umbraco back office and start adding con - + Click this link to accept the invite @@ -2094,6 +2106,7 @@ To manage your website, simply open the Umbraco back office and start adding con items selected Invalid date Not a number + Not a valid numeric step size Invalid email Value cannot be null Value cannot be empty @@ -2261,7 +2274,7 @@ To manage your website, simply open the Umbraco back office and start adding con Created Comment Name - No relations for this relation type. + No relations for this Relation Type Relation Type Relations @@ -2305,7 +2318,7 @@ To manage your website, simply open the Umbraco back office and start adding con Partial View Partial View Macro Member - Data type + Data Type Search the redirect dashboard Search the user group section Search the users section @@ -2326,6 +2339,7 @@ To manage your website, simply open the Umbraco back office and start adding con Select one of the options to edit the node. Perform action %0% on the %1% node Add image caption + Search content tree References @@ -2531,7 +2545,7 @@ To manage your website, simply open the Umbraco back office and start adding con Label Custom view Show custom view description - Overwrite how this block appears in the BackOffice UI. Pick a .html file containing your presentation. + Overwrite how this block appears in the backoffice UI. Pick a .html file containing your presentation. Settings model Overlay editor size Add custom view @@ -2553,6 +2567,9 @@ To manage your website, simply open the Umbraco back office and start adding con Error! The ElementType of this block does not exist anymore + Add content + Add %0% + Property '%0%' uses editor '%1%' which is not supported in blocks. What are Content Templates? @@ -2591,4 +2608,8 @@ To manage your website, simply open the Umbraco back office and start adding con File writing Media folder creation + + item returned + items returned + diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/es.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/es.xml index 2f4fac3450..b1cb25ea0e 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/es.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/es.xml @@ -208,7 +208,7 @@ Nodos hijo Destino Esto se traduce en la siguiente hora en el servidor: - ¿Esto qué significa?]]> + ¿Esto qué significa?]]> ¿Estás seguro que quieres eliminar este elemento? Propiedad %0% utiliza editor %1% que no está soportado por Nested Content. Añadir otra caja de texto @@ -320,7 +320,7 @@ Se está vaciando la papelera. No cierres esta ventana mientras se ejecuta este proceso La papelera está vacía No podrás recuperar los elementos una vez sean borrados de la papelera - regexlib.com está experimentando algunos problemas en estos momentos, de los cuales no somos responsables. Pedimos disculpas por las molestias.]]> + regexlib.com está experimentando algunos problemas en estos momentos, de los cuales no somos responsables. Pedimos disculpas por las molestias.]]> Buscar una expresión regular para agregar validación a un campo de formulario. Ejemplo: 'correo electrónico', 'código postal', 'URL'. Eliminar macro Campo obligatorio @@ -671,7 +671,7 @@ Umbraco %0% ha sido instalado y está listo para ser usado archivo /web.config y actualizar la clave del AppSetting UmbracoConfigurationStatus del final al valor '%0%'.]]> empezar inmediatamente pulsando el botón "Lanzar Umbraco" de debajo.
Si eres nuevo con Umbraco, puedes encontrar cantidad de recursos en nuestras páginas de cómo empezar.]]>
- Lanzar Umbraco Para administrar tu sitio web, simplemente abre el back office de Umbraco y empieza a añadir contenido, a actualizar plantillas y hojas de estilo o a añadir nueva funcionalidad]]> + Lanzar Umbraco Para administrar tu sitio web, simplemente abre el backoffice de Umbraco y empieza a añadir contenido, a actualizar plantillas y hojas de estilo o a añadir nueva funcionalidad]]> No se ha podido establecer la conexión con la base de datos Umbraco versión 3 Umbraco versión 4 @@ -696,7 +696,7 @@ Resplandeciente sábado Iniciar sesión La sesión ha caducado - © 2001 - %0%
umbraco.com

]]> + © 2001 - %0%
umbraco.com

]]>
¿Olvidaste tu contraseña? Enviaremos un email a la dirección especificada con un enlace para restaurar tu contraseña Un email con instrucciones para restaurar tu contraseña será enviado a la dirección especificada si ésta está registrada. @@ -752,7 +752,7 @@ - + Pulsa este enlace para restaurar tu contraseña @@ -989,7 +989,6 @@ Pestañas Tipo de Contenido Maestro activado Este Tipo de Contenido usa - como Tipo de Contenido Maestro. Las pestañas para los Tipos de Contenido Maestros no se muestran y solo se pueden modificar desde el Tipo de Contenido Maestro No existen propiedades para esta pestaña. Haz clic en el enlace "añadir nueva propiedad" para crear una nueva propiedad. Añadir icono @@ -1284,7 +1283,7 @@ Este mail se ha generado automáticamente para informale que %2% has solicitado que el documento '%1%' sea traducido en '%5%'. - Para editarlo, vaya a la dirección http://%3%/translation/details.aspx?id=%4% o inicia sesión en umbraco y ve a http://%3% para ver las tareas pendientes de traducir. + Para editarlo, vaya a la dirección http://%3%/translation/details.aspx?id=%4% o inicia sesión en Umbraco y ve a http://%3% para ver las tareas pendientes de traducir. Espero que tenga un buen dia. @@ -1485,7 +1484,7 @@ - + Pulsa este enlace para aceptar la invitación diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml index 65b3d69000..1c3ab3361c 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml @@ -277,7 +277,7 @@ Eléments enfants Cible Ceci se traduit par l'heure suivante sur le serveur : - Qu'est-ce que cela signifie?]]> + Qu'est-ce que cela signifie?]]> Etes-vous certain(e) de vouloir supprimer cet élément? Etes-vous certain(e) de vouloir supprimer tous les éléments? La propriété %0% utilise l'éditeur %1% qui n'est pas supporté par Nested Content. @@ -336,6 +336,17 @@ Tous les membres Les groupes de membres n'ont pas de propriétés supplémentaires modifiables. + + Echec de la copie du type de contenu + Echec du déplacement du type de contenu + + + Echec de la copie du type de media + Echec du déplacement du type de media + + + Echec de la copie du type de membre + Où voulez-vous créer le nouveau %0% Créer un élément sous @@ -443,7 +454,7 @@ Les éléments dans la corbeille sont en cours de suppression. Veuillez ne pas fermer cette fenêtre avant que cette opération ne soit terminée. La corbeille est maintenant vide Les éléments supprimés de la corbeille seront supprimés définitivement - regexlib.com rencontre actuellement des problèmes sur lesquels nous n'avons aucun contrôle. Nous sommes sincèrement désolés pour le désagrément.]]> + regexlib.com rencontre actuellement des problèmes sur lesquels nous n'avons aucun contrôle. Nous sommes sincèrement désolés pour le désagrément.]]> Rechercher une expression régulière à ajouter pour la validation d'un champ de formulaire. Exemple: 'email, 'zip-code', 'URL'. Supprimer la macro Champ obligatoire @@ -636,6 +647,7 @@ Choisir Fermer Fermer la fenêtre + Fermer le panel Commenter Confirmer Conserver @@ -930,7 +942,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Connectez-vous ci-dessous Identifiez-vous avec La session a expiré - © 2001 - %0%
Umbraco.com

]]>
+ © 2001 - %0%
Umbraco.com

]]>
Mot de passe oublié? Un email contenant un lien pour ré-initialiser votre mot de passe sera envoyé à l'adresse spécifiée Un email contenant les instructions de ré-initialisation de votre mot de passe sera envoyée à l'adresse spécifiée si elle correspond à nos informations. @@ -981,14 +993,14 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Une réinitialisation de votre mot de passe a été demandée

- Votre nom d'utilisateur pour vous connecter au back-office Umbraco est : %0% + Votre nom d'utilisateur pour vous connecter au backoffice Umbraco est : %0%

@@ -1107,7 +1119,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
- + Cliquez sur ce lien pour réinitialiser votre mot de passe
- MODIFIER
+ MODIFIER
@@ -1354,7 +1366,6 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Onglets Type de contenu de base activé Ce type de contenu utilise - en tant que type de contenu de base. Les onglets du type de contenu de base ne sont pas affichés et peuvent seulement être modifiés à partir du type de contenu de base lui-même. Aucune propriété définie dans cet onglet. Cliquez sur le lien "Ajouter une nouvelle propriété" en-haut pour créer une nouvelle propriété. Créer le template correspondant Ajouter une icône @@ -1802,10 +1813,12 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Changer le mot de passe Changer la photo Nouveau mot de passe + Plus que %0% caractère(s) minimum! + Il devrait y avoir au moins %0% caractère(s) spéciaux. n'a pas été bloqué Le mot de passe n'a pas été modifié Confirmez votre nouveau mot de passe - Vous pouvez changer votre mot de passe d'accès au Back Office Umbraco en remplissant le formulaire ci-dessous puis en cliquant sur le bouton "Changer le mot de passe" + Vous pouvez changer votre mot de passe d'accès au backoffice Umbraco en remplissant le formulaire ci-dessous puis en cliquant sur le bouton "Changer le mot de passe" Canal de contenu Créer un autre utilisateur Créer de nouveaux utilisateurs pour leur donner accès à Umbraco. Lors de la création d'un nouvel utilisateur, un mot de passe est généré que vous pouvez partager avec ce dernier. @@ -1937,7 +1950,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à - + Cliquez sur ce lien pour accepter l'invitation @@ -2202,6 +2215,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Partial View Macro de Partial View Membre + Chercher dans l'arborescence de contenu Références @@ -2361,4 +2375,8 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à ]]> + + élément retrouvé + éléments retrouvés + diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/he.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/he.xml index fcc9cfb8ad..d69db216c1 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/he.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/he.xml @@ -181,7 +181,7 @@ הפריטים הנמצאים בסל המיחזור נמחקים כעת, השאר חלון זה פתוח עד לגמר פעולת המחיקה. סל המיחזור ריק כעת מחיקת פריטים מסל המיחזור תמחוק את הפריטים לצמיתות - regexlib.com's webservice is currently experiencing some problems, which we have no control over. We are very sorry for this inconvenience.]]> + regexlib.com's webservice is currently experiencing some problems, which we have no control over. We are very sorry for this inconvenience.]]> חיפוש ביטויים להוספת אימות עבור שדות טופס. לדוגמא: 'כתובת אימייל', 'מיקוד', 'כתובת אתר' ועוד הסר מאקרו שדה חובה @@ -449,7 +449,7 @@ Get help from our award winning community, browse the documentation or watch som started instantly by clicking the "Launch Umbraco" button below.
If you are new to Umbraco, you can find plenty of resources on our getting started pages.]]>
Launch Umbraco -To manage your website, simply open the Umbraco back office and start adding content, updating the templates and stylesheets or add new functionality]]> +To manage your website, simply open the Umbraco backoffice and start adding content, updating the templates and stylesheets or add new functionality]]> ההתחברות לבסיס הנתונים נכשלה. Umbraco גירסה 3 Umbraco גירסה 4 @@ -467,7 +467,7 @@ To manage your website, simply open the Umbraco back office and start adding con יש לבצע חידוש פעילות על מנת לשמור על התוכן - © 2001 - %0%
umbraco.com

]]> + © 2001 - %0%
umbraco.com

]]>
לוח הבקרה diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/it.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/it.xml index 812da01703..2f89060ac6 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/it.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/it.xml @@ -186,7 +186,7 @@ - regexlib.com ha attualmente qualche problema, di cui non abbiamo il controllo. Siamo spiacevoli dell'inconveniente.]]> + regexlib.com ha attualmente qualche problema, di cui non abbiamo il controllo. Siamo spiacevoli dell'inconveniente.]]> Elimina Macro Campo obbligatorio @@ -422,7 +422,7 @@ Fatti aiutare dalla nostra community, consulta la documentazione o guarda alcuni /web.config e aggiornare la chiave AppSetting UmbracoConfigurationStatus impostando il valore '%0%'.]]> iniziare immediatamente cliccando sul bottone "Avvia Umbraco".
Se sei nuovo a Umbraco, si possono trovare un sacco di risorse sulle nostre pagine Getting Started.]]>
Avvia Umbraco -Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e iniziare ad aggiungere i contenuti, aggiornando i modelli e i fogli di stile o aggiungere nuove funzionalità]]> +Per gestire il tuo sito web, è sufficiente aprire il backoffice di Umbraco e iniziare ad aggiungere i contenuti, aggiornando i modelli e i fogli di stile o aggiungere nuove funzionalità]]> Connessione al database non riuscita. Umbraco Versione 3 Umbraco Versione 4 @@ -440,7 +440,7 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i Riconnetti adesso per salvare il tuo lavoro - © 2001 - %0%
umbraco.com

]]>
+ © 2001 - %0%
umbraco.com

]]>
Dashboard @@ -603,7 +603,6 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i Utenti - Tipo di contenuto master abilitato Questo tipo di contenuto usa @@ -820,7 +819,7 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i Amministratore Campo Categoria Cambia la tua password - + Conferma la nuova password Contenuto del canale Campo Descrizione diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ja.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ja.xml index 80aad2c301..ac56649083 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ja.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ja.xml @@ -246,7 +246,7 @@ ごみ箱を空にしています。実行中はウィンドウを閉じないでください。 ごみ箱は空です ごみ箱から削除すると復活させることはできません - regexlib.comのウェブサービスに現在問題が起きているかもしれず、操作できませんでした。大変申し訳ありませんがこの機能は使用できません。]]> + regexlib.comのウェブサービスに現在問題が起きているかもしれず、操作できませんでした。大変申し訳ありませんがこの機能は使用できません。]]> フォームのフィールドを正規表現で検証できます。例: 'email, 'zip-code' 'URL' マクロを削除 必須フィールド @@ -608,7 +608,7 @@ Runwayをインストールして作られた新しいウェブサイトがど ハッピー土曜日 ウェブサイトにログインします。 セッションタイムアウトしました。 - © 2001 - %0%
umbraco.org

]]>
+ © 2001 - %0%
umbraco.org

]]>
ダッシュボード @@ -804,7 +804,6 @@ Runwayをインストールして作られた新しいウェブサイトがど タブ マスターコンテンツタイプが有効 このコンテンツタイプの使用 - マスターコンテンツタイプについては、マスターコンテンツタイプからのタブは表示されず、マスターコンテンツタイプでのみ編集することができます。 このタブにはプロパティが定義されていません、上部のリンクから新しいプロパティを作成してください アイコンの追加 diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ko.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ko.xml index 02f50e73b2..0e29856926 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ko.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ko.xml @@ -180,7 +180,7 @@ 휴지통안에 이 항목들이 완전히 삭제중 입니다. 작업이 완료되기전까지 창을 닫지마세요. 휴지통이 비었습니다. 휴지통에서 삭제하시면 완전히 삭제됩니다. - regexlib.com의 웹서비스는 현재 제어할 수 없는 몇가지 문제점이 보고되었습니다. 불편을 드려 대단히 죄송합니다.]]> + regexlib.com의 웹서비스는 현재 제어할 수 없는 몇가지 문제점이 보고되었습니다. 불편을 드려 대단히 죄송합니다.]]> 필드 유효성검사를 위해 정규표현식을 검색합니다. 예: 'email, 'zip-code' 'URL' 매크로 삭제 필수 필드 @@ -452,7 +452,7 @@ TRANSLATE ME: 'Renew now to save your work' - © 2001 - %0%
umbraco.com

]]>
+ © 2001 - %0%
umbraco.com

]]>
대시보드 @@ -815,7 +815,7 @@ 관리자 카테고리 필드 Change Your Password - You can change your password for accessing the Umbraco Back Office by filling out the form below and click the 'Change Password' button + You can change your password for accessing the Umbraco backoffice by filling out the form below and click the 'Change Password' button 컨텐츠 채널 설명 필드 사용자 비활성화 diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/nb.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/nb.xml index cc0b46f200..bd70a6d0f4 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/nb.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/nb.xml @@ -240,7 +240,7 @@ Innholdet i papirkurven blir nå slettet. Vennligst ikke lukk dette vinduet mens denne operasjonen foregår Papirkurven er nå tom Når elementer blir slettet fra papirkurven vil de være slettet for alltid - regexlib.com tjenesten opplever for tiden problemer som vi ikke har kontroll over. Vi beklager denne ubeleiligheten.]]> + regexlib.com tjenesten opplever for tiden problemer som vi ikke har kontroll over. Vi beklager denne ubeleiligheten.]]> Søk etter et regulært uttrykk for å legge inn validering til et felt. Eksempel: 'email, 'zip-code', 'URL'. Fjern makro Obligatorisk @@ -509,7 +509,7 @@ Logg på nedenfor Logg på med Din sesjon er utløpt - © 2001 - %0%
umbraco.com

]]>
+ © 2001 - %0%
umbraco.com

]]>
Skrivebord @@ -689,7 +689,6 @@ Vennlig hilsen Umbraco roboten Arkfaner Hovedinnholdstype aktivert Denne dokumenttypen bruker - som hoveddokumenttype. Arkfaner fra hoveddokumenttyper vises ikke og kan kun endres på hoveddokumenttypen selv. Ingen egenskaper definert i denne arkfanen. Klikk på "legg til ny egenskap" lenken i toppen for å opprette en ny egenskap. diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/nl.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/nl.xml index aa6ef7dd36..5613f830b6 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/nl.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/nl.xml @@ -650,7 +650,6 @@ Plaats de cursor links van de twee cellen die je wilt samenvoegen Je kunt een cel die is samengevoegd niet delen Deze eigenschap is ongeldig - Eigenschap '%0%' gebruikt editor '%1%' die niet ondersteund wordt in Element Types. Opties @@ -903,7 +902,7 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je Umbraco %0% is geïnstalleerd en klaar voor gebruik. /web.config bestand aanpassen, en de Appsetting key UmbracoConfigurationStatus onder in het bestand veranderen naar '%0%'.]]> meteen beginnen door de "Launch Umbraco" knop hieronder te klikken.
Als je een beginnende Umbraco gebruiker bent, dan kun je you can find veel informatie op onze "getting started" pagina's vinden.]]>
- Launch Umbraco Om je website te beheren open je simpelweg de Umbraco back office en begin je inhoud toe te voegen, templates en stylesheets aan te passen of nieuwe functionaliteit toe te voegen]]> + Launch Umbraco Om je website te beheren open je simpelweg de Umbraco backoffice en begin je inhoud toe te voegen, templates en stylesheets aan te passen of nieuwe functionaliteit toe te voegen]]> Verbinding met de database mislukt. Umbraco versie 3 Umbraco versie 4 @@ -1230,7 +1229,6 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je Tabs Basis inhoudstype ingeschakeld Dit inhoudstype gebruikt - als basis inhoudstype. Tabs van basis inhoudstypes worden niet getoond en kunnen alleen worden aangepast op het basis inhoudstype zelf Geen eigenschappen gedefinieerd op dit tabblad. Klik op de link "voeg een nieuwe eigenschap" aan de bovenkant om een ​​nieuwe eigenschap te creëren. Maak een bijpassende sjabloon Icoon toevoegen @@ -2365,6 +2363,7 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je Fout! Het Elementtype van dit blok bestaat niet meer + Eigenschap '%0%' gebruikt editor '%1%' die niet ondersteund wordt in blokken. Wat zijn Inhoudssjablonen? diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/pl.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/pl.xml index a40f7e666b..970364fa21 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/pl.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/pl.xml @@ -205,7 +205,7 @@ Elementy dzieci Cel Oznacza to następującą godzinę na serwerze: - Co to oznacza?]]> + Co to oznacza?]]> Czy na pewno chcesz usunąć ten element? Właściwość %0% używa edytora %1%, który nie jest wspierany przez Nested Content. Dodaj kolejne pole tekstowe @@ -321,7 +321,7 @@ Zawartość kosza jest teraz usuwana. Proszę nie zamykać tego okna do momentu zakończenia procesu. Zawartość kosza została usunięta Usunięcie elementów z kosza powoduje ich trwałe i nieodwracalne skasowanie - regexlib.com aktualnie nie jest dostępny, na co nie mamy wpływu. Bardzo przepraszamy za te utrudnienia.]]> + regexlib.com aktualnie nie jest dostępny, na co nie mamy wpływu. Bardzo przepraszamy za te utrudnienia.]]> Przeszukaj dla wyrażeń regularnych, aby dodać regułę sprawdzającą do formularza. Np. 'email' 'URL' Usuń Makro Pole wymagane @@ -728,7 +728,7 @@ Naciśnij przycisk instaluj, aby zainstalować bazę danych Umb Zaloguj się poniżej Zaloguj się z Sesja wygasła - © 2001 - %0%
umbraco.com

]]>
+ © 2001 - %0%
umbraco.com

]]>
Zapomniałeś hasła? E-mail z linkiem do zresetowania hasła zostanie wysłany na podany adres E-mail z instrukcjami do zresetowania hasła zostanie wysłany, jeśli zgadza się z naszą bazą danych @@ -737,7 +737,7 @@ Naciśnij przycisk instaluj, aby zainstalować bazę danych Umb Twoje hasło zostało zmienione Link, na który kliknąłeś jest niewłaściwy lub wygasł Umbraco: Resetowanie hasła - Twoja nazwa użytkownika do zalogowania się w Umbraco back-office to: %0%

Kliknij tutaj, aby zresetować Twoje hasło lub kopiuj/wklej ten URL w przeglądarce:

%1%

]]>
+ Twoja nazwa użytkownika do zalogowania się w Umbraco backoffice to: %0%

Kliknij tutaj, aby zresetować Twoje hasło lub kopiuj/wklej ten URL w przeglądarce:

%1%

]]>
Panel zarządzania @@ -981,7 +981,6 @@ Naciśnij przycisk instaluj, aby zainstalować bazę danych Umb Zakładki Włączono Główny Typ Treści Ten Typ Treści używa - jako Główny Typ Treści. Zakładki Głównego Typu Treści nie są wyświetlone i mogą być edytowane jedynie w samym Głównym Typie Treści Żadne właściwości nie zostały zdefiniowane dla tej zakładki. Kliknij w link "dodaj nową właściwość", który znajduje się na górze strony, aby stworzyć nową właściwość. Dodaj ikonę @@ -1321,7 +1320,7 @@ Naciśnij przycisk instaluj, aby zainstalować bazę danych Umb Zmień hasło! Nowe hasło Potwierdź nowe hasło - Możesz zmienić swoje hasło w Umbraco Back Office przez wypełnienie formularza poniżej i kliknięcie przycisku "Zmień hasło" + Możesz zmienić swoje hasło w Umbraco backoffice przez wypełnienie formularza poniżej i kliknięcie przycisku "Zmień hasło" Kanał zawartości Opis Wyłącz użytkownika diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/pt.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/pt.xml index 0091cde73c..5f11605c31 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/pt.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/pt.xml @@ -180,7 +180,7 @@ Os itens na lixeira agora estão sendo removidos. Favor não fechar esta janela enquanto este processo é concluído A lixeira agora está vazia Quando itens são removidos da lixeira estes somem para sempre - regexlib.com está no momento sofrendo dificuldades dos quais não temos controle. Pedimos desculpas pela inconveniência.]]> + regexlib.com está no momento sofrendo dificuldades dos quais não temos controle. Pedimos desculpas pela inconveniência.]]> Busque por uma expressão regular para adicionar validação à um campo de formulário. Exemplo: 'email', 'zip-code' (código postal), 'URL' Remover Macro Campo obrigatório @@ -445,7 +445,7 @@ Pressione "próximo" para iniciar o assistente.]]> Renovar agora para salvar seu trabalho - © 2001 - %0%
umbraco.com

]]>
+ © 2001 - %0%
umbraco.com

]]>
Painel diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ru.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ru.xml index df3c0361b9..0501698c9f 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ru.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/ru.xml @@ -241,7 +241,7 @@ Очистить дату ВНИМАНИЕ: этот документ опубликован, но его URL вступает в противоречие с документом %0% Это время будет соответствовать следующему времени на сервере: - Что это означает?]]> + Что это означает?]]> Задать дату Порядок сортировки обновлен Для сортировки узлов просто перетаскивайте узлы или нажмите на заголовке столбца. Вы можете выбрать несколько узлов, удерживая клавиши "shift" или "ctrl" при пометке @@ -371,7 +371,7 @@ Все элементы в корзине сейчас удаляются. Пожалуйста, не закрывайте это окно до окончания процесса удаления Корзина пуста Вы больше не сможете восстановить элементы, удаленные из корзины - regexlib.com испытывает в настоящее время некоторые трудности, не зависящие от нас. Просим извинить за причиненные неудобства.]]> + regexlib.com испытывает в настоящее время некоторые трудности, не зависящие от нас. Просим извинить за причиненные неудобства.]]> Используйте поиск регулярных выражений для добавления сервиса проверки к полю Вашей формы. Например: 'email, 'zip-code', 'URL' Удалить макрос Обязательное поле @@ -890,7 +890,7 @@ Обновите сейчас, чтобы сохранить сделанные изменения - © 2001 - %0%
umbraco.com

]]>
+ © 2001 - %0%
umbraco.com

]]>
Сегодня же выходной! Понедельник — день тяжелый... Вот уже вторник... @@ -956,7 +956,7 @@ - + Нажмите на эту ссылку для того, чтобы сбросить пароль @@ -1095,7 +1095,7 @@
- ВНЕСТИ ИЗМЕНЕНИЯ
+ ВНЕСТИ ИЗМЕНЕНИЯ @@ -1330,7 +1330,6 @@ Добавить значок - в качестве родительского типа. Вкладки родительского типа не показаны и могут быть изменены непосредственно в родительском типе Родительский тип контента разрешен Данный тип контента использует Шаблон по-умолчанию @@ -1671,7 +1670,7 @@ Добавьте пользователя в группу(ы) для задания прав доступа Пригласить Приглашение в панель администрирования Umbraco -

Здравствуйте, %0%,

Вы были приглашены пользователем %1%, и Вам предоставлен доступ в панель администрирования Umbraco.

Сообщение от %1%: %2%

Перейдите по этой ссылке, чтобы принять приглашение.

Если Вы не имеете возможности перейти по ссылке, скопируйте нижеследующий текст ссылки и вставьте в адресную строку Вашего браузера.

%3%

]]>

Здравствуйте, %0%,

Вы были приглашены пользователем %1%, и Вам предоставлен доступ в панель администрирования Umbraco.

Сообщение от %1%: %2%

Перейдите по этой ссылке, чтобы принять приглашение.

Если Вы не имеете возможности перейти по ссылке, скопируйте нижеследующий текст ссылки и вставьте в адресную строку Вашего браузера.

%3%

]]> @@ -1726,7 +1725,7 @@ - + Нажмите на эту ссылку, чтобы принять приглашение diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/sv.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/sv.xml index 511765e604..d9fc485007 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/sv.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/sv.xml @@ -136,7 +136,7 @@ Välj Förhandsgranska Förhandsgranskning är avstängt på grund av att det inte finns någon mall tilldelad - Ångra + Gör något annat Välj stil Visa stil Infoga tabell @@ -243,10 +243,10 @@ Installera Umbraco Forms - Stanna - Ignorera ändringar - Du har ändringar som inte är sparade - Vill du verkligen lämna sidan? Du har ändringar som inte är sparade + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes Klar @@ -272,6 +272,8 @@ Kopierade %0% av %1% objekt + Länktitel + Länk Namn Hantera domännamn Stäng fönstret @@ -300,7 +302,7 @@ Allt som ligger i papperskorgen tas nu bort. Stäng inte detta fönster förrän detta är klart Papperskorgen är nu tom Om du tömmer papperskorgen kommer allt som ligger i den att tas bort permanent - regexlib.com's webbtjänst har för närvarande driftsstörningar. Tyvärr kan vi inte göra något åt detta.]]> + regexlib.com's webbtjänst har för närvarande driftsstörningar. Tyvärr kan vi inte göra något åt detta.]]> Sök efter en regular expression som kan validera ett formulärsfält. t.ex. 'email' eller 'URL' Ta bort makro Obligatoriskt formulärsfält @@ -308,7 +310,9 @@ Cache för webbplatsen har uppdaterats. Allt publicerat innehåll är nu uppdaterat. Innehåll som inte har publicerats är fortfarande opublicerat. Webbplatsens cache kommer att uppdateras. Allt innehåll som är publicerat kommer att uppdateras. Innehåll som inte är publicerat kommer att förbli opublicerat. Välj startnod för innehåll + Välj media Välj ikon + Välj länk Välj startnod för media Välj användargrupper Välj sektioner @@ -318,6 +322,9 @@ Klicka på förhandsgranskningsbilden för att se bilden i full storlek Välj ett objekt Se cachat objekt + Länk till sida + Öppnar länken i ett nytt fönster eller flik + Länk till media Redigera de olika översättningarna för ordboksinlägget %0% nedan. Du kan lägga till ytterligare språk under 'språk' i menyn till vänster. @@ -551,7 +558,7 @@ Umbraco %0% är installerat och klart för användning /web.config filen och ändra AppSettingsnyckeln UmbracoConfigurationStatus på slutet till %0%]]> börja omedelbart genom att klicka på "Starta Umbraco"-knappen nedan.
Om du är en ny Umbraco användarekan du hitta massor av resurser på våra kom igång sidor.]]>
- Starta Umbraco För att administrera din webbplats öppnar du bara Umbraco back office och börjar lägga till innehåll, uppdatera mallar och stilmallar eller lägga till nya funktioner.]]> + Starta Umbraco För att administrera din webbplats öppnar du bara Umbraco backoffice och börjar lägga till innehåll, uppdatera mallar och stilmallar eller lägga till nya funktioner.]]> Anslutningen till databasen misslyckades. Se Umbraco %0% antingen för en ny installation eller en uppgradering från version 3.0.

Tryck på "next" för att börja.]]>
@@ -567,7 +574,7 @@ Förnya nu för att spara ditt arbete - © 2001 - %0%
umbraco.com

]]>
+ © 2001 - %0%
umbraco.com

]]>
Happy super Sunday Happy manic Monday Happy tremendous Tuesday @@ -725,7 +732,6 @@ Användare - som huvudinnehållstyp. Tabbar från huvudinnehållstyper visas inte och kan endast redigeras på själva huvudinnehållstypen. Huvudinnehållstyp påslagen Denna huvudinnehållstyp använder Defaultmall @@ -741,8 +747,8 @@ Flikar - Sortera ordningen - Skapandedatum + Sort order + Creation date Sortering klar Välj i vilken ordning du vill ha sidorna genom att dra dem upp eller ner i listan. Du kan också klicka på kolumnrubrikerna för att sortera grupper av sidor @@ -815,12 +821,12 @@ Bild - Makro + Macro Lägg till - Välj utformning + Choose layout Lägg till rad - Lägg till innehåll - Släpp innehåll + Add content + Drop content Indholdet er ikke tilladt her Indholdet er tilladt her Klicka för att lägga in @@ -847,7 +853,7 @@ Alternativt fält Alternativ text - Hölje + Casing Välj fält Konvertera radbrytningar Byter radbrytningar mot html-taggen &lt;br&gt; @@ -940,7 +946,7 @@ Ändra lösenord Ändra bild Bekräfta det nya lösenordet - Du kan byta ditt lösenord för Umbraco Back Office genom att fylla i nedanstående formulär och klicka på knappen "Ändra lösenord". + Du kan byta ditt lösenord för Umbraco backoffice genom att fylla i nedanstående formulär och klicka på knappen "Ändra lösenord". Innehållskanal Skapa en till användare Skapa nya användare för att ge dom åtkomst till Umbraco. När en ny användare skapas kommer ett lösenord genereras som du kan dela med användaren. @@ -963,7 +969,7 @@ Senast utlåst Senast inloggad Lösenordet ändrades - Logga in + Login Startnod i mediabiblioteket Begränsa media sectionen till en specifik startnod Media startnoder diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/tr.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/tr.xml index fa0f909bfb..bb73d43a3e 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/tr.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/tr.xml @@ -561,7 +561,7 @@ Dizini yönetmek için araçlar alanlar Dizin okunamıyor ve yeniden oluşturulması gerekecek - İşlem beklenenden uzun sürüyor, bu işlem sırasında herhangi bir hata olup olmadığını görmek için umbraco günlüğünü kontrol edin + İşlem beklenenden uzun sürüyor, bu işlem sırasında herhangi bir hata olup olmadığını görmek için Umbraco günlüğünü kontrol edin Bu dizin, atanmış olmadığı için yeniden oluşturulamaz IIndexPopulator @@ -631,7 +631,6 @@ %0% zorunlu bir alandır %1% konumunda %0% doğru biçimde değil %0% doğru biçimde değil - '%0%' özelliği, Öğe Türlerinde desteklenmeyen '%1%' düzenleyicisini kullanıyor. Sunucudan bir hata aldı @@ -858,7 +857,7 @@

Devam etmek için lütfen "web.config" dosyasını düzenleyin (Visual Studio veya favori metin düzenleyicinizi kullanarak), en alta kaydırın, veritabanınız için "UmbracoDbDSN" adlı anahtara bağlantı dizesini ekleyin ve dosyayı kaydedin.

Yeniden dene düğmesini tıklayın. - bitti.
+ bitti.
Web.config'i düzenleme hakkında daha fazla bilgi burada.

]]>
@@ -1009,7 +1008,7 @@ Web sitenizi yönetmek için, Umbraco'nun arka ofisini açın ve içerik eklemey Aşağıda oturum açın ile oturum açın Oturum zaman aşımına uğradı - © 2015 - %0%
Umbraco.com

]]>
+ © 2015 - %0%
Umbraco.com

]]>
Şifrenizi mi unuttunuz? Parolanızı sıfırlamak için bir bağlantıyla belirtilen adrese bir e-posta gönderilecektir Kayıtlarımızla eşleşirse, şifre sıfırlama talimatlarını içeren bir e-posta, belirtilen adrese gönderilecektir @@ -1068,7 +1067,7 @@ Web sitenizi yönetmek için, Umbraco'nun arka ofisini açın ve içerik eklemey - + Şifrenizi sıfırlamak için bu bağlantıyı tıklayın @@ -1193,7 +1192,7 @@ Web sitenizi yönetmek için, Umbraco'nun arka ofisini açın ve içerik eklemey
- DÜZENLE
+ DÜZENLE @@ -1469,7 +1468,6 @@ Web sitenizi yönetmek için, Umbraco'nun arka ofisini açın ve içerik eklemey Sekmeler Ana İçerik Türü etkinleştirildi Bu İçerik Türü kullanır - Ana İçerik Türü olarak . Ana İçerik Türlerinden sekmeler gösterilmez ve yalnızca Ana İçerik Türünün kendisinde düzenlenebilir Bu sekmede tanımlanmış özellik yok. Yeni bir mülk oluşturmak için üstteki "yeni mülk ekle" bağlantısını tıklayın. Eşleşen şablon oluştur Simge ekle @@ -2065,7 +2063,7 @@ Web sitenizi yönetmek için, Umbraco'nun arka ofisini açın ve içerik eklemey - + Daveti Kabul Etmek İçin Bu Bağlantıyı Tıklayın @@ -2256,7 +2254,7 @@ Web sitenizi yönetmek için, Umbraco'nun arka ofisini açın ve içerik eklemey Durum denetleyicisi, sitenizin çeşitli alanlarını en iyi uygulama ayarları, yapılandırma, olası sorunlar vb. için değerlendirir. Sorunları bir düğmeye basarak kolayca düzeltebilirsiniz. - Kendi sağlık kontrollerinizi ekleyebilir, özel durum kontrolleri hakkında daha fazla bilgi için belgeler .

+ Kendi sağlık kontrollerinizi ekleyebilir, özel durum kontrolleri hakkında daha fazla bilgi için belgeler .

]]>
@@ -2494,7 +2492,7 @@ Web sitenizi yönetmek için, Umbraco'nun arka ofisini açın ve içerik eklemey Umbraco eğitim videolarının saatleri yalnızca bir tıklama uzaklıkta Umbraco'da ustalaşmak mı istiyorsunuz? Umbraco'nun kullanımıyla ilgili bu videolardan birini izleyerek en iyi uygulamaları öğrenmek için birkaç dakikanızı ayırın. Daha da fazla Umbraco videosu için umbraco.tv adresini ziyaret edin

+

Umbraco'da ustalaşmak mı istiyorsunuz? Umbraco'nun kullanımıyla ilgili bu videolardan birini izleyerek en iyi uygulamaları öğrenmek için birkaç dakikanızı ayırın. Daha da fazla Umbraco videosu için umbraco.tv adresini ziyaret edin

]]>
Başlamak için @@ -2505,27 +2503,27 @@ Web sitenizi yönetmek için, Umbraco'nun arka ofisini açın ve içerik eklemey Daha fazla bilgi edinin öğelerle çalışma hakkında daha fazla bilgi edinin Our Umbraco'nun Dokümantasyon bölümünde + Ayarlar öğelerle çalışma hakkında daha fazla bilgi edinin Our Umbraco'nun Dokümantasyon bölümünde ]]> Topluluk Forumu'nda bir soru sorun + Topluluk Forumu'nda bir soru sorun ]]> Eğitici videolarımızı izleyin (bazıları ücretsiz, bazıları abonelik gerektirir) + Eğitici videolarımızı izleyin (bazıları ücretsiz, bazıları abonelik gerektirir) ]]> Üretkenliği artıran araçlarımız ve ticari desteğimiz hakkında bilgi edinin + Üretkenliği artıran araçlarımız ve ticari desteğimiz hakkında bilgi edinin ]]> eğitim ve sertifika fırsatları hakkında bilgi edinin + Gerçek hayattaki eğitim ve sertifika fırsatları hakkında bilgi edinin ]]> @@ -2575,6 +2573,7 @@ Web sitenizi yönetmek için, Umbraco'nun arka ofisini açın ve içerik eklemey Hata! Bu bloğun ElementType'ı artık mevcut değil + '%0%' özelliği, bloklarda desteklenmeyen '%1%' düzenleyicisini kullanıyor. İçerik Şablonları Nedir? diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/zh.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/zh.xml index 286ab88881..595f4ac7d1 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/zh.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/zh.xml @@ -169,7 +169,7 @@ 子项 目标 这将转换到服务器上的以下时间: - 这是什么意思?]]> + 这是什么意思?]]> 点击上传 @@ -257,7 +257,7 @@ 正在清空回收站,请不要关闭窗口。 回收站已清空 从回收站删除的项目将不可恢复 - regexlib.com的服务暂时出现问题。]]> + regexlib.com的服务暂时出现问题。]]> 查找正则表达式来验证输入,如: 'email、'zip-code'、'URL'。 移除宏 必填项 @@ -630,7 +630,7 @@ 在下方登录 登录 会话超时 - © 2001 - %0%
Umbraco.com

]]>
+ © 2001 - %0%
Umbraco.com

]]>
忘记密码? 电子邮件将发送到地址指定的链接, 以重置您的密码 如果电子邮件与我们的记录相符, 则将发送带有密码重置指令的邮件 @@ -847,7 +847,6 @@ 选项卡 主控文档类型激活 该文档类型使用 - 作为主控文档类型. 主控文档类型的标签只能在主控文档类型里修改。 没有字段设置在该标签页 添加图标 diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/zh_tw.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/zh_tw.xml index 0bdc79f052..5230485766 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/zh_tw.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/zh_tw.xml @@ -166,7 +166,7 @@ 子項目 目標 預計發表的時間(伺服器端) - 這是什麼意思?]]> + 這是什麼意思?]]> 點選以便上傳 @@ -254,7 +254,7 @@ 正在清空回收站,請不要關閉窗口。 回收站已清空 從回收站刪除的項目將不可恢復 - regexlib.com的網站服務目前出現些狀況,而我們無能為力。我們對此不便感到十分抱歉。]]> + regexlib.com的網站服務目前出現些狀況,而我們無能為力。我們對此不便感到十分抱歉。]]> 查找規則運算式來驗證輸入,如: 'email、'zip-code'、'URL'。 移除巨集 必填項目 @@ -619,7 +619,7 @@ 下方登入 登入使用 連線時間過了 - © 2001 - %0%
Umbraco.com

]]>
+ © 2001 - %0%
Umbraco.com

]]>
忘記密碼? 一封內有重設密碼連結的電子郵件已經寄出給您 一封內有重設密碼連結的電子郵件已經寄到此信箱 @@ -834,7 +834,6 @@ 選項卡 主控文件類型啟動 該文檔類型使用 - 作為主控文件類型. 主控文件類型的標籤只能在主控文件類型裡修改。 沒有欄位設置在該標籤頁 增加圖示 diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 0bec939262..7c58185131 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -105,6 +105,7 @@ all + @@ -231,6 +232,9 @@ 8121 / http://localhost:8121 + 8130 + / + http://localhost:8130 False False diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/cy.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/cy.xml index eacfcde1bf..274b7ef5b0 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/cy.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/cy.xml @@ -292,7 +292,7 @@ Eitemau blentyn Targed Mae hyn yn trawsnewid at yr amser ganlynol ar y gweinydd: - Beth mae hyn yn golygu?]]> + Beth mae hyn yn golygu?]]> Ydych chi'n sicr eich bod eisiau dileu'r eitem yma? Mae'r priodwedd %0% yn defnyddio'r golygydd %1% sydd ddim yn cyd-fynd â Chynnwys Amnyth. Wyt ti'n siŵr fod ti eisiau dileu pob eitem? @@ -483,7 +483,7 @@ Mae'r eitemau yn y bin ailgylchu yn cael eu dileu. Peidiwch â chau'r ffenestr yma wrth i'r gweithrediad gymryd lle Mae'r bin ailgylchu yn awr yn wag Pan gaiff eitemau eu dileu o'r bin ailgylchu, byddent yn diflannu am byth - regexlib.com ar hyn o bryd, nid oes gennym reolaeth dros hyn. Mae'n ddrwg iawn gennym ni am yr anghyfleustra.]]> + regexlib.com ar hyn o bryd, nid oes gennym reolaeth dros hyn. Mae'n ddrwg iawn gennym ni am yr anghyfleustra.]]> Chwiliwch am fynegiad cyson er mwyn ychwanegu dilysiad i faes ffurflen. Enghraifft: 'email, 'zip-code' 'url' Dileu Macro Maes Gofynnol @@ -589,7 +589,7 @@ Offer i reoli'r mynegai meysydd Ni ellir darllen yr mynegai a bydd angen ei ailadeiladu - Mae'r broses yn cymryd mwy o amser na'r disgwyl, gwiriwch y log umbraco i weld os mae wedi bod unrhyw wall yn ystod y gweithrediad hwn + Mae'r broses yn cymryd mwy o amser na'r disgwyl, gwiriwch y log Umbraco i weld os mae wedi bod unrhyw wall yn ystod y gweithrediad hwn Ni ellir ailadeiladu'r mynegai hwn oherwydd nad yw wedi'i aseinio IIndexPopulator @@ -676,7 +676,6 @@ %0% yn faes ofynnol %0% yn %1% mewn fformat annilys %0% mewn fformat annilys - Briodwedd '%0%' yn defnyddio'r golygydd '%1%' sydd ddim wedi ei chynnal yn y teipiau elfen. Derbynwyd gwall o'r gweinydd @@ -701,7 +700,6 @@ Symudwch y cyrchwr ar ochr chwith y ddwy gell yr ydych eisiau cyfuno Ni allwch hollti cell sydd heb ei gyfuno. Mae gan briodwedd hon gwallau - Priodwedd '%0%' yn defnyddio'r golygydd '%1%' sydd ddim yn cael ei gefnogi mewn Mathau o Elfen. Gwall yn y ffynhonnell XSLT Nid yw'r XSLTwedi'i achub gan ei fod yn cynnwys gwall(au) Mae gwall ffurfwedd gyda'r math o ddata sy'n cael ei ddefnyddio ar gyfer y priodwedd yma, gwiriwch y fath o ddata @@ -1089,7 +1087,7 @@ Er mwyn gweinyddu eich gwefan, agorwch swyddfa gefn Umbraco a dechreuwch ychwang Mewngofnodwch isod Mewngofnodwch gyda Sesiwn wedi cyrraedd terfyn amser - © 2001 - %0%
Umbraco.com

]]>
+ © 2001 - %0%
Umbraco.com

]]>
Wedi anghofio eich cyfrinair? Bydd ebost yn cael ei anfon i'r cyfeiriad darparwyd gyda dolen i ailosod eich cyfrinair Bydd ebost gyda chyfarwyddiadau ailosod cyfrinair yn cael ei anfon at y cyfeiriad darparwyd os yw'n cyfateb â'n cofnodion @@ -1148,7 +1146,7 @@ Er mwyn gweinyddu eich gwefan, agorwch swyddfa gefn Umbraco a dechreuwch ychwang - + Cliciwch y ddolen yma er mwyn ailosod eich cyfrinair @@ -1271,7 +1269,7 @@ Er mwyn gweinyddu eich gwefan, agorwch swyddfa gefn Umbraco a dechreuwch ychwang
- GOLYGU
+ GOLYGU @@ -1566,7 +1564,6 @@ Er mwyn gweinyddu eich gwefan, agorwch swyddfa gefn Umbraco a dechreuwch ychwang Tabiau Math o Gynnwys Meistr wedi'i alluogi Mae'r Math o Gynnwys yma yn defnyddio - fel Math o Gynnwys Meistr. Nid yw tabiau o Fath o Gynnwys Meistr yn cael eu dangos a gall dim ond eu golygu ar y Math o Gynnwys Meistr ei hunan Dim priodweddau wedi'u diffinio ar y tab yma. Cliciwch ar y ddolen "ychwanegu priodwedd newydd" ar y topi greu priodwedd newydd. Math o Ddogfen Feistr Creu templedi cydweddol @@ -2245,7 +2242,7 @@ Er mwyn gweinyddu eich gwefan, agorwch swyddfa gefn Umbraco a dechreuwch ychwang - + Cliciwch y ddolen yma i dderbyn y gwahoddiad @@ -2763,6 +2760,7 @@ Er mwyn gweinyddu eich gwefan, agorwch swyddfa gefn Umbraco a dechreuwch ychwang Rydych chi wedi gwneud newidiadau i'r cynnwys hwn. Wyt ti'n siŵr eich bod chi am eu taflu ei fwrdd? Gwaredu cread? + Priodwedd '%0%' yn defnyddio'r golygydd '%1%' sydd ddim yn cael ei gefnogi mewn blociau. Beth yw Templedi Gynnwys diff --git a/src/Umbraco.Web/ModelStateExtensions.cs b/src/Umbraco.Web/ModelStateExtensions.cs index d9bc40c12e..ca2974ac4a 100644 --- a/src/Umbraco.Web/ModelStateExtensions.cs +++ b/src/Umbraco.Web/ModelStateExtensions.cs @@ -21,11 +21,11 @@ namespace Umbraco.Web { if (dictionary == null) return; - foreach (var keyValuePair in dictionary + foreach (var (key, value) in dictionary //It can either equal the prefix exactly (model level errors) or start with the prefix. (property level errors) .Where(keyValuePair => keyValuePair.Key == prefix || keyValuePair.Key.StartsWith(prefix + "."))) { - state[keyValuePair.Key] = keyValuePair.Value; + state[key] = value; } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 60299a9b34..378903f947 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -71,6 +71,8 @@ 5.0.376 + + 2.9.1 @@ -250,4 +252,4 @@ - \ No newline at end of file +