Compare commits

...

44 Commits

Author SHA1 Message Date
Sebastiaan Janssen 7e7f9902f6 Bumps version to 7.7.4 2017-10-23 14:18:00 +02:00
Sebastiaan Janssen dcd2630d6b Merge branch 'dev-v7.6' into dev-v7 2017-10-23 14:10:04 +02:00
Sebastiaan Janssen b70f543790 Reverts wrongly committed files 2017-10-23 14:02:00 +02:00
Sebastiaan Janssen 24c1c15b66 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-10-23 13:59:30 +02:00
Sebastiaan Janssen 4a0cd7228b Revert "U4-10554 - warn if closing page with changes"
This reverts commit 24b147e2a6.
2017-10-23 13:59:06 +02:00
Stephan edfe212227 Fix login issue 2017-10-20 15:35:30 +02:00
Sebastiaan Janssen e3bc98a155 Merge pull request #2257 from umbraco/temp-U4-10566
U4-10566 The legacy API Member.PopulateGroups throws an exception
2017-10-19 06:59:18 -07:00
Shannon f85532f15e U4-10566 The legacy API Member.PopulateGroups throws an exception 2017-10-20 00:56:34 +11:00
Sebastiaan Janssen b04d71ca5f Merge pull request #2256 from richarth/patch-1
Removed duplicate translations
2017-10-19 00:41:33 -07:00
Sebastiaan Janssen ab4de382f3 Merge pull request #2252 from umbraco/temp-u4-7317
U4-7317 - select default template
2017-10-18 12:38:53 -07:00
Sebastiaan Janssen a293c633fc Merge pull request #2249 from umbraco/temp-u4-8652
U4-8652 - accept exceptions when loading some assemblies
2017-10-18 11:00:45 -07:00
Richard Thompson 507e3ece98 Removed duplicate translations
Removed duplicate definition of English translations
2017-10-18 15:36:17 +01:00
Stephan b77826fd3d Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-10-18 12:18:59 +02:00
Stephan 4c7358d63b U4-8960 - minor fixes 2017-10-18 12:17:58 +02:00
Stephan 4814612102 Merge branch 'U4-8960' of https://github.com/lars-erik/Umbraco-CMS into temp-u4-8960 2017-10-18 11:56:00 +02:00
Robert 6dae4396bb Merge pull request #2250 from umbraco/temp-u4-10554
U4-10554 - warn if closing page with changes
2017-10-18 11:53:54 +02:00
Stephan dd5560f00b U4-8616 - minor cleanup 2017-10-18 10:11:23 +02:00
Stephan b56575fc50 Merge branch 'dev-v7' of https://github.com/jhauge/Umbraco-CMS into temp-u4-8616 2017-10-18 09:49:05 +02:00
Stephan b06d30c0f9 U4-10554 - cross-browser 2017-10-18 09:29:50 +02:00
Claus 9c50e1c48d fixing bug in U4-10524 Show warning in UI for the media/content picker that is referencing a trashed or deleted item 2017-10-17 23:52:34 +02:00
Claus 0688835ac0 fixing bug in U4-10524 Show warning in UI for the media/content picker that is referencing a trashed or deleted item 2017-10-17 23:44:03 +02:00
Stephan 353b8f21cd U4-7317 - select default template 2017-10-17 16:04:31 +02:00
Stephan 30a0d553d5 Merge pull request #1230 from bjarnef/dev-v7-U4-8319
U4-8319 - Sort data types array by name A-Z
2017-10-17 15:06:54 +02:00
Stephan d0fbc362b2 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2017-10-17 15:00:13 +02:00
Stephan 39c534ef54 Merge branch 'temp-u4-7115' into dev-v7 2017-10-17 14:59:56 +02:00
Stephan 7f86166abf Merge branch 'dev-v7' of https://github.com/hfloyd/Umbraco-CMS into temp-u4-7115 2017-10-17 14:59:07 +02:00
Robert 838e86469a Merge pull request #2245 from umbraco/temp-u4-5322
U4-5322 - add labels to color picker
2017-10-17 14:47:36 +02:00
Stephan 24b147e2a6 U4-10554 - warn if closing page with changes 2017-10-17 14:39:47 +02:00
Stephan 11342ff1df U4-8652 - accept exceptions when loading some assemblies 2017-10-17 14:04:24 +02:00
Robert bf20af9345 Merge pull request #2247 from umbraco/temp-u4-5722b
Temp u4 5722b
2017-10-17 13:19:34 +02:00
Robert c69774e3f2 Merge pull request #2246 from umbraco/temp-u4-7360
U4-7360 - toggle password visibility
2017-10-17 12:30:37 +02:00
Robert 7de8f5a59a Added missing width and height to the "show password" icon
Not having the height and width on the icon, caused IE 11 to shrink the icon which looked a bit off.
2017-10-17 12:09:55 +02:00
Stephan 909e3788ea Merge branch 'U4-5722' of https://github.com/NikRimington/Umbraco-CMS into temp-u4-5722b 2017-10-16 17:20:19 +02:00
Stephan 09a92ef6ce U4-7360 - toggle password visibility 2017-10-16 16:58:15 +02:00
Stephan 7d9c2bcce9 Merge branch 'dev-v7' into temp-u4-5322 2017-10-16 16:32:43 +02:00
Stephan 529ae961ff U4-5322 - add labels to color picker 2017-10-16 16:16:43 +02:00
Nik 7367c8ef67 Re-do min max number of items in the grid after rebasing 2017-07-30 02:09:38 +01:00
Lars-Erik Aabech 361ef2a475 Opening up GetHttpContextFactory for extending (actually in prev commit, but messed up) 2016-09-13 23:57:31 +02:00
Lars-Erik Aabech d382fcc919 Issue with isHosted in TypeFinder when unit testing. 2016-09-13 23:56:15 +02:00
Lars-Erik Aabech aac8451627 Removing HttpContext dependency from GridValueConverter. Adding configuration for IOHelper when testing to remove usage of HttpContext. 2016-09-11 21:36:10 +02:00
Jesper Hauge c96c09f42f Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-06-20 21:55:25 +02:00
Jesper Hauge 50f8f18503 Fixes U4-8616 2016-06-20 21:53:40 +02:00
bjarnef 9001cd8a6f Sort data types array by name A-Z 2016-04-14 23:50:43 +02:00
Heather Floyd 1279fd234f Checking for possible Null Ref Exception in Textstring.cshtml grid renderer 2015-09-11 19:43:41 -04:00
34 changed files with 780 additions and 307 deletions
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.7.3")]
[assembly: AssemblyInformationalVersion("7.7.3")]
[assembly: AssemblyFileVersion("7.7.4")]
[assembly: AssemblyInformationalVersion("7.7.4")]
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.7.3");
private static readonly Version Version = new Version("7.7.4");
/// <summary>
/// Gets the current version of Umbraco.
+24 -6
View File
@@ -13,11 +13,28 @@ using Umbraco.Core.Configuration;
namespace Umbraco.Core.IO
{
public static class IOHelper
{
{
/// <summary>
/// Gets or sets a value forcing Umbraco to consider it is non-hosted.
/// </summary>
/// <remarks>This should always be false, unless unit testing.</remarks>
public static bool ForceNotHosted { get; set; }
private static string _rootDir = "";
// static compiled regex for faster performance
private readonly static Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
/// <summary>
/// Gets a value indicating whether Umbraco is hosted.
/// </summary>
public static bool IsHosted
{
get
{
return ForceNotHosted == false && (HttpContext.Current != null || HostingEnvironment.IsHosted);
}
}
public static char DirSepChar
{
@@ -72,14 +89,14 @@ namespace Umbraco.Core.IO
internal static string ResolveUrlsFromTextString(string text)
{
if (UmbracoConfig.For.UmbracoSettings().Content.ResolveUrlsFromTextString)
{
{
using (DisposableTimer.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete"))
{
// find all relative urls (ie. urls that contain ~)
var tags = ResolveUrlPattern.Matches(text);
foreach (Match tag in tags)
{
{
string url = "";
if (tag.Groups[1].Success)
url = tag.Groups[1].Value;
@@ -97,7 +114,8 @@ namespace Umbraco.Core.IO
public static string MapPath(string path, bool useHttpContext)
{
if (path == null) throw new ArgumentNullException("path");
if (path == null) throw new ArgumentNullException("path");
useHttpContext = useHttpContext && IsHosted;
// Check if the path is already mapped
if ((path.Length >= 2 && path[1] == Path.VolumeSeparatorChar)
@@ -303,7 +321,7 @@ namespace Umbraco.Core.IO
var debugFolder = Path.Combine(binFolder, "debug");
if (Directory.Exists(debugFolder))
return debugFolder;
#endif
#endif
var releaseFolder = Path.Combine(binFolder, "release");
if (Directory.Exists(releaseFolder))
return releaseFolder;
@@ -178,29 +178,25 @@ namespace Umbraco.Core.PropertyEditors
return result;
}
private void ConvertItemsToJsonIfDetected(IDictionary<string, object> result)
protected void ConvertItemsToJsonIfDetected(IDictionary<string, object> result)
{
//now we're going to try to see if any of the values are JSON, if they are we'll convert them to real JSON objects
// so they can be consumed as real json in angular!
// convert values that are Json to true Json objects that can be consumed by Angular
var keys = result.Keys.ToArray();
for (var i = 0; i < keys.Length; i++)
{
if (result[keys[i]] is string)
if ((result[keys[i]] is string) == false) continue;
var asString = result[keys[i]].ToString();
if (asString.DetectIsJson() == false) continue;
try
{
var asString = result[keys[i]].ToString();
if (asString.DetectIsJson())
{
try
{
var json = JsonConvert.DeserializeObject(asString);
result[keys[i]] = json;
}
catch
{
//swallow this exception, we thought it was json but it really isn't so continue returning a string
}
}
result[keys[i]] = JsonConvert.DeserializeObject(asString);
}
catch
{
// swallow this exception, we thought it was Json but it really isn't so continue returning a string
}
}
}
@@ -1,13 +1,14 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.PropertyEditors.ValueConverters
{
[DefaultPropertyValueConverter]
[PropertyValueType(typeof(string))]
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
public class ColorPickerValueConverter : PropertyValueConverterBase
public class ColorPickerValueConverter : PropertyValueConverterBase, IPropertyValueConverterMeta
{
public override bool IsConverter(PublishedPropertyType propertyType)
{
@@ -18,11 +19,60 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
return false;
}
public Type GetPropertyValueType(PublishedPropertyType propertyType)
{
return UseLabel(propertyType) ? typeof(PickedColor) : typeof(string);
}
public PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType, PropertyCacheValue cacheValue)
{
return PropertyCacheLevel.Content;
}
private bool UseLabel(PublishedPropertyType propertyType)
{
var preValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(propertyType.DataTypeId);
PreValue preValue;
return preValues.PreValuesAsDictionary.TryGetValue("useLabel", out preValue) && preValue.Value == "1";
}
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
// make sure it's a string
return source == null ? string.Empty : source.ToString();
var useLabel = UseLabel(propertyType);
if (source == null) return useLabel ? null : string.Empty;
var ssource = source.ToString();
if (ssource.DetectIsJson())
{
try
{
var jo = JsonConvert.DeserializeObject<JObject>(ssource);
if (useLabel) return new PickedColor(jo["value"].ToString(), jo["label"].ToString());
return jo["value"].ToString();
}
catch { /* not json finally */ }
}
if (useLabel) return new PickedColor(ssource, ssource);
return ssource;
}
public class PickedColor
{
public PickedColor(string color, string label)
{
Color = color;
Label = label;
}
public string Color { get; private set; }
public string Label { get; private set; }
public override string ToString()
{
return Color;
}
}
}
}
@@ -43,8 +43,8 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
var gridConfig = UmbracoConfig.For.GridConfig(
ApplicationContext.Current.ProfilingLogger.Logger,
ApplicationContext.Current.ApplicationCache.RuntimeCache,
new DirectoryInfo(HttpContext.Current.Server.MapPath(SystemDirectories.AppPlugins)),
new DirectoryInfo(HttpContext.Current.Server.MapPath(SystemDirectories.Config)),
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)),
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config)),
HttpContext.Current.IsDebuggingEnabled);
var sections = GetArray(obj, "sections");
+49 -5
View File
@@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security;
using System.Text;
using System.Web;
using System.Web.Compilation;
using System.Web.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
@@ -21,6 +20,38 @@ namespace Umbraco.Core
{
private static volatile HashSet<Assembly> _localFilteredAssemblyCache;
private static readonly object LocalFilteredAssemblyCacheLocker = new object();
private static readonly List<string> NotifiedLoadExceptionAssemblies = new List<string>();
private static string[] _assembliesAcceptingLoadExceptions;
private static string[] AssembliesAcceptingLoadExceptions
{
get
{
if (_assembliesAcceptingLoadExceptions != null)
return _assembliesAcceptingLoadExceptions;
var s = ConfigurationManager.AppSettings["Umbraco.AssembliesAcceptingLoadExceptions"];
return _assembliesAcceptingLoadExceptions = string.IsNullOrWhiteSpace(s)
? new string[0]
: s.Split(',').Select(x => x.Trim()).ToArray();
}
}
private static bool AcceptsLoadExceptions(Assembly a)
{
if (AssembliesAcceptingLoadExceptions.Length == 0)
return false;
if (AssembliesAcceptingLoadExceptions.Length == 1 && AssembliesAcceptingLoadExceptions[0] == "*")
return true;
var name = a.GetName().Name; // simple name of the assembly
return AssembliesAcceptingLoadExceptions.Any(pattern =>
{
if (pattern.Length > name.Length) return false; // pattern longer than name
if (pattern.Length == name.Length) return pattern.InvariantEquals(name); // same length, must be identical
if (pattern[pattern.Length] != '.') return false; // pattern is shorter than name, must end with dot
return name.StartsWith(pattern); // and name must start with pattern
});
}
/// <summary>
/// lazily load a reference to all assemblies and only local assemblies.
@@ -45,7 +76,7 @@ namespace Umbraco.Core
HashSet<Assembly> assemblies = null;
try
{
var isHosted = HttpContext.Current != null || HostingEnvironment.IsHosted;
var isHosted = IOHelper.IsHosted;
try
{
@@ -528,9 +559,22 @@ namespace Umbraco.Core
AppendCouldNotLoad(sb, a, getAll);
foreach (var loaderException in rex.LoaderExceptions.WhereNotNull())
AppendLoaderException(sb, loaderException);
var ex = new ReflectionTypeLoadException(rex.Types, rex.LoaderExceptions, sb.ToString());
// rethrow with new message
throw new ReflectionTypeLoadException(rex.Types, rex.LoaderExceptions, sb.ToString());
// rethrow with new message, unless accepted
if (AcceptsLoadExceptions(a) == false) throw ex;
// log a warning, and return what we can
lock (NotifiedLoadExceptionAssemblies)
{
if (NotifiedLoadExceptionAssemblies.Contains(a.FullName) == false)
{
NotifiedLoadExceptionAssemblies.Add(a.FullName);
LogHelper.WarnWithException(typeof(TypeFinder), "Could not load all types from " + a.GetName().Name + ".", ex);
}
}
return rex.Types.WhereNotNull().ToArray();
}
}
@@ -388,13 +388,12 @@ namespace Umbraco.Tests.TestHelpers
return ctx;
}
protected FakeHttpContextFactory GetHttpContextFactory(string url, RouteData routeData = null)
protected virtual FakeHttpContextFactory GetHttpContextFactory(string url, RouteData routeData = null)
{
var factory = routeData != null
? new FakeHttpContextFactory(url, routeData)
: new FakeHttpContextFactory(url);
//set the state helper
StateHelper.HttpContext = factory.HttpContext;
@@ -0,0 +1,26 @@
(function () {
'use strict';
// comes from https://codepen.io/jakob-e/pen/eNBQaP
// works fine with Angular 1.6.5 - alas not with 1.1.5 - binding issue
function PasswordToggleDirective($compile) {
var directive = {
restrict: 'A',
scope: {},
link: function(scope, elem, attrs) {
scope.tgl = function () { elem.attr("type", (elem.attr("type") === "text" ? "password" : "text")); }
var lnk = angular.element("<a data-ng-click=\"tgl()\">Toggle</a>");
$compile(lnk)(scope);
elem.wrap("<div class=\"password-toggle\"/>").after(lnk);
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbPasswordToggle', PasswordToggleDirective);
})();
@@ -2,12 +2,12 @@
* @ngdoc service
* @name umbraco.services.assetsService
*
* @requires $q
* @requires $q
* @requires angularHelper
*
*
* @description
* Promise-based utillity service to lazy-load client-side dependencies inside angular controllers.
*
*
* ##usage
* To use, simply inject the assetsService into any controller that needs it, and make
* sure the umbraco.services module is accesible - which it should be by default.
@@ -18,7 +18,7 @@
* //this code executes when the dependencies are done loading
* });
* });
* </pre>
* </pre>
*
* You can also load individual files, which gives you greater control over what attibutes are passed to the file, as well as timeout
*
@@ -38,13 +38,14 @@
* //loadcss cannot determine when the css is done loading, so this will trigger instantly
* });
* });
* </pre>
* </pre>
*/
angular.module('umbraco.services')
.factory('assetsService', function ($q, $log, angularHelper, umbRequestHelper, $rootScope, $http) {
var initAssetsLoaded = false;
var appendRnd = function (url) {
function appendRnd (url) {
//if we don't have a global umbraco obj yet, the app is bootstrapping
if (!Umbraco.Sys.ServerVariables.application) {
return url;
@@ -77,7 +78,8 @@ angular.module('umbraco.services')
return this.loadedAssets[path];
}
},
/**
/**
Internal method. This is called when the application is loading and the user is already authenticated, or once the user is authenticated.
There's a few assets the need to be loaded for the application to function but these assets require authentication to load.
*/
@@ -108,10 +110,10 @@ angular.module('umbraco.services')
*
* @description
* Injects a file as a stylesheet into the document head
*
*
* @param {String} path path to the css file to load
* @param {Scope} scope optional scope to pass into the loader
* @param {Object} keyvalue collection of attributes to pass to the stylesheet element
* @param {Object} keyvalue collection of attributes to pass to the stylesheet element
* @param {Number} timeout in milliseconds
* @returns {Promise} Promise object which resolves when the file has loaded
*/
@@ -149,10 +151,10 @@ angular.module('umbraco.services')
*
* @description
* Injects a file as a javascript into the document
*
*
* @param {String} path path to the js file to load
* @param {Scope} scope optional scope to pass into the loader
* @param {Object} keyvalue collection of attributes to pass to the script element
* @param {Object} keyvalue collection of attributes to pass to the script element
* @param {Number} timeout in milliseconds
* @returns {Promise} Promise object which resolves when the file has loaded
*/
@@ -192,8 +194,8 @@ angular.module('umbraco.services')
* @methodOf umbraco.services.assetsService
*
* @description
* Injects a collection of files, this can be ONLY js files
*
* Injects a collection of css and js files
*
*
* @param {Array} pathArray string array of paths to the files to load
* @param {Scope} scope optional scope to pass into the loader
@@ -206,61 +208,72 @@ angular.module('umbraco.services')
throw "pathArray must be an array";
}
// Check to see if there's anything to load, resolve promise if not
var nonEmpty = _.reject(pathArray, function (item) {
return item === undefined || item === "";
});
});
//don't load anything if there's nothing to load
if (nonEmpty.length > 0) {
var promises = [];
var assets = [];
//compile a list of promises
//blocking
_.each(nonEmpty, function (path) {
path = convertVirtualPath(path);
var asset = service._getAssetPromise(path);
//if not previously loaded, add to list of promises
if (asset.state !== "loaded") {
if (asset.state === "new") {
asset.state = "loading";
assets.push(asset);
}
//we need to always push to the promises collection to monitor correct
//execution
promises.push(asset.deferred.promise);
}
});
//gives a central monitoring of all assets to load
promise = $q.all(promises);
_.each(assets, function (asset) {
LazyLoad.js(appendRnd(asset.path), function () {
asset.state = "loaded";
if (!scope) {
asset.deferred.resolve(true);
}
else {
angularHelper.safeApply(scope, function () {
asset.deferred.resolve(true);
});
}
});
});
}
else {
//return and resolve
if (nonEmpty.length === 0) {
var deferred = $q.defer();
promise = deferred.promise;
deferred.resolve(true);
return promise;
}
//compile a list of promises
//blocking
var promises = [];
var assets = [];
_.each(nonEmpty, function (path) {
path = convertVirtualPath(path);
var asset = service._getAssetPromise(path);
//if not previously loaded, add to list of promises
if (asset.state !== "loaded") {
if (asset.state === "new") {
asset.state = "loading";
assets.push(asset);
}
//we need to always push to the promises collection to monitor correct
//execution
promises.push(asset.deferred.promise);
}
});
//gives a central monitoring of all assets to load
promise = $q.all(promises);
// Split into css and js asset arrays, and use LazyLoad on each array
var cssAssets = _.filter(assets,
function (asset) {
return asset.path.match(/(\.css$|\.css\?)/ig);
});
var jsAssets = _.filter(assets,
function (asset) {
return asset.path.match(/(\.js$|\.js\?)/ig);
});
function assetLoaded(asset) {
asset.state = "loaded";
if (!scope) {
asset.deferred.resolve(true);
return;
}
angularHelper.safeApply(scope,
function () {
asset.deferred.resolve(true);
});
}
if (cssAssets.length > 0) {
var cssPaths = _.map(cssAssets, function (asset) { return appendRnd(asset.path) });
LazyLoad.css(cssPaths, function() { _.each(cssAssets, assetLoaded); });
}
if (jsAssets.length > 0) {
var jsPaths = _.map(jsAssets, function (asset) { return appendRnd(asset.path) });
LazyLoad.js(jsPaths, function () { _.each(jsAssets, assetLoaded); });
}
return promise;
}
@@ -66,7 +66,7 @@
margin-bottom: auto;
}
.login-overlay .form input[type="text"],
.login-overlay .form input[type="text"],
.login-overlay .form input[type="password"],
.login-overlay .form input[type="email"] {
height: 36px;
@@ -114,8 +114,44 @@
line-height: 36px;
}
.login-overlay .text-error,
.login-overlay .text-info
.login-overlay .text-error,
.login-overlay .text-info
{
font-weight:bold;
}
}
.password-toggle {
position: relative;
display: block;
user-select: none;
input::-ms-clear, input::-ms-reveal {
display: none;
}
a {
opacity: .5;
cursor: pointer;
display: inline-block;
position: absolute;
height: 1px;
width: 45px;
height: 75%;
font-size: 0;
background-repeat: no-repeat;
background-size: 50%;
background-position: center;
top: 0;
margin-left: -45px;
z-index: 1;
-webkit-tap-highlight-color: transparent;
}
[type="text"] + a {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath fill='%23444' d='M29.6.4C29 0 28 0 27.4.4L21 6.8c-1.4-.5-3-.8-5-.8C9 6 3 10 0 16c1.3 2.6 3 4.8 5.4 6.5l-5 5c-.5.5-.5 1.5 0 2 .3.4.7.5 1 .5s1 0 1.2-.4l27-27C30 2 30 1 29.6.4zM13 10c1.3 0 2.4 1 2.8 2L12 15.8c-1-.4-2-1.5-2-2.8 0-1.7 1.3-3 3-3zm-9.6 6c1.2-2 2.8-3.5 4.7-4.7l.7-.2c-.4 1-.6 2-.6 3 0 1.8.6 3.4 1.6 4.7l-2 2c-1.6-1.2-3-2.7-4-4.4zM24 13.8c0-.8 0-1.7-.4-2.4l-10 10c.7.3 1.6.4 2.4.4 4.4 0 8-3.6 8-8z'/%3E%3Cpath fill='%23444' d='M26 9l-2.2 2.2c2 1.3 3.6 3 4.8 4.8-1.2 2-2.8 3.5-4.7 4.7-2.7 1.5-5.4 2.3-8 2.3-1.4 0-2.6 0-3.8-.4L10 25c2 .6 4 1 6 1 7 0 13-4 16-10-1.4-2.8-3.5-5.2-6-7z'/%3E%3C/svg%3E");
}
[type="password"] + a {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath fill='%23444' d='M16 6C9 6 3 10 0 16c3 6 9 10 16 10s13-4 16-10c-3-6-9-10-16-10zm8 5.3c1.8 1.2 3.4 2.8 4.6 4.7-1.2 2-2.8 3.5-4.7 4.7-3 1.5-6 2.3-8 2.3s-6-.8-8-2.3C6 19.5 4 18 3 16c1.5-2 3-3.5 5-4.7l.6-.2C8 12 8 13 8 14c0 4.5 3.5 8 8 8s8-3.5 8-8c0-1-.3-2-.6-2.6l.4.3zM16 13c0 1.7-1.3 3-3 3s-3-1.3-3-3 1.3-3 3-3 3 1.3 3 3z'/%3E%3C/svg%3E");
}
}
@@ -109,16 +109,48 @@ ul.color-picker li a {
}
/* pre-value editor */
/*.control-group.color-picker-preval:before {
content: "";
display: inline-block;
vertical-align: middle;
height: 100%;
}*/
/*.control-group.color-picker-preval div.thumbnail {
display: inline-block;
vertical-align: middle;
}*/
.control-group.color-picker-preval div.color-picker-prediv {
display: inline-block;
width: 60%;
}
.control-group.color-picker-preval pre {
display: inline;
margin-right: 20px;
margin-left: 10px;
width: 50%;
white-space: nowrap;
overflow: hidden;
margin-bottom: 0;
vertical-align: middle;
}
.control-group.color-picker-preval btn {
//vertical-align: middle;
}
.control-group.color-picker-preval input[type="text"] {
min-width: 40%;
width: 40%;
display: inline-block;
margin-right: 20px;
margin-top: 1px;
}
.control-group.color-picker-preval label {
border:solid @white 1px;
padding:6px;
border: solid @white 1px;
padding: 6px;
}
@@ -16,7 +16,11 @@
maxFileSize: Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB",
acceptedFileTypes: mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes),
uploaded: false
}
}
$scope.togglePassword = function () {
var elem = $("form[name='loginForm'] input[name='password']");
elem.attr("type", (elem.attr("type") === "text" ? "password" : "text"));
}
function init() {
// Check if it is a new user
@@ -48,7 +52,7 @@
]).then(function () {
$scope.inviteStep = Number(inviteVal);
});
}
}
@@ -82,7 +86,7 @@
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10);
// set percentage property on file
$scope.avatarFile.uploadProgress = progressPercentage;
$scope.avatarFile.uploadProgress = progressPercentage;
}
}).success(function (data, status, headers, config) {
@@ -149,11 +153,11 @@
//error
formHelper.handleError(err);
$scope.invitedUserPasswordModel.buttonState = "error";
});
}
}
};
var setFieldFocus = function (form, field) {
@@ -180,7 +184,7 @@
}
function resetInputValidation() {
$scope.confirmPassword = "";
$scope.confirmPassword = "";
$scope.password = "";
$scope.login = "";
if ($scope.loginForm) {
@@ -255,7 +259,7 @@
//TODO: Do validation properly like in the invite password update
//if the login and password are not empty we need to automatically
//if the login and password are not empty we need to automatically
// validate them - this is because if there are validation errors on the server
// then the user has to change both username & password to resubmit which isn't ideal,
// so if they're not empty, we'll just make sure to set them to valid.
@@ -289,7 +293,7 @@
});
//setup a watch for both of the model values changing, if they change
// while the form is invalid, then revalidate them so that the form can
// while the form is invalid, then revalidate them so that the form can
// be submitted again.
$scope.loginForm.username.$viewChangeListeners.push(function () {
if ($scope.loginForm.username.$invalid) {
@@ -24,8 +24,8 @@
</label>
<input type="password" ng-model="invitedUserPasswordModel.password" name="password" class="-full-width-input" umb-auto-focus required val-server-field="value" autocomplete="off" ng-minlength="{{invitedUserPasswordModel.passwordPolicies.minPasswordLength}}" />
<span class="help-inline" val-msg-for="password" val-toggle-msg="required"><localize key="user_passwordIsBlank">Your new password cannot be blank!</localize></span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="minlength">Minimum {{invitedUserPasswordModel.passwordPolicies.minPasswordLength}} characters</span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="valServerField"></span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="minlength">Minimum {{invitedUserPasswordModel.passwordPolicies.minPasswordLength}} characters</span>
<span class="help-inline" val-msg-for="password" val-toggle-msg="valServerField"></span>
</div>
<div class="control-group" ng-class="{error: setPasswordForm.confirmPassword.$invalid}">
@@ -49,15 +49,15 @@
<div class="form" ng-if="inviteStep === 2">
<div class="flex justify-center items-center">
<ng-form name="avatarForm">
<umb-progress-bar style="max-width: 100px; margin-bottom: 5px;"
ng-show="avatarFile.uploadStatus === 'uploading'"
progress="{{ avatarFile.uploadProgress }}"
size="s">
</umb-progress-bar>
<div class="umb-info-local-item text-error mt3" ng-if="avatarFile.uploadStatus === 'error'">
{{ avatarFile.serverErrorMessage }}
</div>
@@ -69,7 +69,7 @@
ngf-multiple="false"
ngf-pattern="{{avatarFile.acceptedFileTypes}}"
ngf-max-size="{{ avatarFile.maxFileSize }}">
<umb-avatar color="gray"
size="xl"
unknown-char="+"
@@ -77,7 +77,7 @@
img-srcset="{{invitedUser.avatars[4]}} 2x, {{invitedUser.avatars[4]}} 3x">
</umb-avatar>
</a>
</ng-form>
</div>
@@ -149,8 +149,9 @@
<div class="control-group" ng-class="{error: loginForm.password.$invalid}">
<label><localize key="general_password">Password</localize></label>
<input type="password" ng-model="password" name="password" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" autocomplete="off" />
</div>
<div class="password-toggle">
<input type="password" ng-model="password" name="password" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" autocomplete="off" /><a ng-click="togglePassword()">Toggle</a>
</div>
<div class="flex justify-between items-center">
<button type="submit" class="btn btn-success" val-trigger-change="#login .form input"><localize key="general_login">Login</localize></button>
@@ -1,25 +1,131 @@
function ColorPickerController($scope) {
$scope.toggleItem = function (color) {
if ($scope.model.value == color) {
$scope.model.value = "";
//this is required to re-validate
$scope.propertyForm.modelValue.$setViewValue($scope.model.value);
}
else {
$scope.model.value = color;
//this is required to re-validate
$scope.propertyForm.modelValue.$setViewValue($scope.model.value);
}
};
function ColorPickerController($scope) {
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
if ($scope.isConfigured) {
for (var key in $scope.model.config.items) {
if (!$scope.model.config.items[key].hasOwnProperty("value"))
$scope.model.config.items[key] = { value: $scope.model.config.items[key], label: $scope.model.config.items[key] };
}
$scope.model.useLabel = isTrue($scope.model.config.useLabel);
initActiveColor();
}
$scope.toggleItem = function (color) {
var currentColor = $scope.model.value.hasOwnProperty("value")
? $scope.model.value.value
: $scope.model.value;
var newColor;
if (currentColor === color.value) {
// deselect
$scope.model.value = $scope.model.useLabel ? { value: "", label: "" } : "";
newColor = "";
}
else {
// select
$scope.model.value = $scope.model.useLabel ? { value: color.value, label: color.label } : color.value;
newColor = color.value;
}
// this is required to re-validate
$scope.propertyForm.modelValue.$setViewValue(newColor);
};
// Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected)
$scope.validateMandatory = function () {
$scope.validateMandatory = function () {
var isValid = !$scope.model.validation.mandatory || (
$scope.model.value != null
&& $scope.model.value != ""
&& (!$scope.model.value.hasOwnProperty("value") || $scope.model.value.value !== "")
);
return {
isValid: !$scope.model.validation.mandatory || ($scope.model.value != null && $scope.model.value != ""),
isValid: isValid,
errorMsg: "Value cannot be empty",
errorKey: "required"
};
}
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
// A color is active if it matches the value and label of the model.
// If the model doesn't store the label, ignore the label during the comparison.
$scope.isActiveColor = function (color) {
// no value
if (!$scope.model.value)
return false;
// Complex color (value and label)?
if (!$scope.model.value.hasOwnProperty("value"))
return $scope.model.value === color.value;
return $scope.model.value.value === color.value && $scope.model.value.label === color.label;
};
// Finds the color best matching the model's color,
// and sets the model color to that one. This is useful when
// either the value or label was changed on the data type.
function initActiveColor() {
// no value
if (!$scope.model.value)
return;
// Complex color (value and label)?
if (!$scope.model.value.hasOwnProperty("value"))
return;
var modelColor = $scope.model.value.value;
var modelLabel = $scope.model.value.label;
// Check for a full match or partial match.
var foundItem = null;
// Look for a fully matching color.
for (var key in $scope.model.config.items) {
var item = $scope.model.config.items[key];
if (item.value == modelColor && item.label == modelLabel) {
foundItem = item;
break;
}
}
// Look for a color with a matching value.
if (!foundItem) {
for (var key in $scope.model.config.items) {
var item = $scope.model.config.items[key];
if (item.value == modelColor) {
foundItem = item;
break;
}
}
}
// Look for a color with a matching label.
if (!foundItem) {
for (var key in $scope.model.config.items) {
var item = $scope.model.config.items[key];
if (item.label == modelLabel) {
foundItem = item;
break;
}
}
}
// If a match was found, set it as the active color.
if (foundItem) {
$scope.model.value.value = foundItem.value;
$scope.model.value.label = foundItem.label;
}
}
// figures out if a value is trueish enough
function isTrue(bool) {
return !!bool && bool !== "0" && angular.lowercase(bool) !== "false";
}
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.ColorPickerController", ColorPickerController);
@@ -5,10 +5,10 @@
</div>
<ul class="thumbnails color-picker">
<li ng-repeat="(key, val) in model.config.items" ng-class="{active: model.value === val}">
<a ng-click="toggleItem(val)" class="thumbnail" hex-bg-color="{{val}}">
</a>
<li ng-repeat="(key, val) in model.config.items" ng-class="{active: isActiveColor(val)}">
<a ng-click="toggleItem(val)" class="thumbnail" hex-bg-color="{{val.value}}">
</a>
<span class="color-label" ng-if="model.useLabel" ng-bind="val.label"></span>
</li>
</ul>
@@ -1,12 +1,13 @@
<div ng-controller="Umbraco.PrevalueEditors.MultiColorPickerController">
<div class="control-group color-picker-preval">
<input name="newColor" type="hidden" />
<label for="newColor" val-highlight="hasError">#{{newColor}}</label>
<input name="newLabel" type="text" ng-model="newLabel" class="umb-editor color-label" placeholder="Label" />
<button class="btn add" ng-click="add($event)"><localize key="general_add">Add</localize></button>
<label for="newColor" val-highlight="hasError">{{newColor}}</label>
</div>
<div class="control-group color-picker-preval" ng-repeat="item in model.value">
<div class="thumbnail span1" hex-bg-color="{{item.value}}" bg-orig="transparent"></div>
<pre>{{item.value}}</pre>
<div class="color-picker-prediv"><pre>#{{item.value}} - {{item.label}}</pre></div>
<button class="btn btn-danger" ng-click="remove(item, $event)"><localize key="general_remove">Remove</localize></button>
</div>
</div>
@@ -2,15 +2,17 @@
function ($scope, $timeout, assetsService, angularHelper, $element) {
//NOTE: We need to make each color an object, not just a string because you cannot 2-way bind to a primitive.
var defaultColor = "000000";
var defaultLabel = null;
$scope.newColor = defaultColor;
$scope.newLavel = defaultLabel;
$scope.hasError = false;
assetsService.load([
//"lib/spectrum/tinycolor.js",
"lib/spectrum/spectrum.js"
"lib/spectrum/spectrum.js"
], $scope).then(function () {
var elem = $element.find("input");
var elem = $element.find("input[name='newColor']");
elem.spectrum({
color: null,
showInitial: false,
@@ -21,7 +23,7 @@
clickoutFiresChange: true,
hide: function (color) {
//show the add butotn
$element.find(".btn.add").show();
$element.find(".btn.add").show();
},
change: function (color) {
angularHelper.safeApply($scope, function () {
@@ -39,21 +41,41 @@
//make an array from the dictionary
var items = [];
for (var i in $scope.model.value) {
items.push({
value: $scope.model.value[i],
id: i
});
var oldValue = $scope.model.value[i];
if (oldValue.hasOwnProperty("value")) {
items.push({
value: oldValue.value,
label: oldValue.label,
id: i
});
} else {
items.push({
value: oldValue,
label: oldValue,
id: i
});
}
}
//now make the editor model the array
$scope.model.value = items;
}
// ensure labels
for (var i = 0; i < $scope.model.value.length; i++) {
var item = $scope.model.value[i];
item.label = item.hasOwnProperty("label") ? item.label : item.value;
}
function validLabel(label) {
return label !== null && typeof label !== "undefined" && label !== "" && label.length && label.length > 0;
}
$scope.remove = function (item, evt) {
evt.preventDefault();
$scope.model.value = _.reject($scope.model.value, function (x) {
return x.value === item.value;
return x.value === item.value && x.label === item.label;
});
};
@@ -63,15 +85,15 @@
evt.preventDefault();
if ($scope.newColor) {
var newLabel = validLabel($scope.newLabel) ? $scope.newLabel : $scope.newColor;
var exists = _.find($scope.model.value, function(item) {
return item.value.toUpperCase() == $scope.newColor.toUpperCase();
return item.value.toUpperCase() === $scope.newColor.toUpperCase() || item.label.toUpperCase() === newLabel.toUpperCase();
});
if (!exists) {
$scope.model.value.push({ value: $scope.newColor });
//$scope.newColor = defaultColor;
// set colorpicker to default color
//var elem = $element.find("input");
//elem.spectrum("set", $scope.newColor);
$scope.model.value.push({
value: $scope.newColor,
label: newLabel
});
$scope.hasError = false;
return;
}
@@ -48,14 +48,18 @@
<a href ng-click="scaleDown(currentCell)">
<i class="icon icon-remove"></i>
</a>
{{currentCell.grid}}
{{currentCell.grid}}
<a href ng-click="scaleUp(currentCell, availableRowSpace, true)">
<i class="icon icon-add"></i>
</a>
</div>
</umb-control-group>
<umb-control-group label="@grid_maxItems" description="@grid_maxItemsDescription">
<input type="number" ng-model="currentCell.maxItems" class="umb-editor-tiny" placeholder="Max" min="0" />
</umb-control-group>
<umb-control-group hide-label="true">
<umb-control-group hide-label="true">
<i class="icon-delete red"></i>
<a class="btn btn-small btn-link" href="" ng-click="deleteArea(currentCell, currentRow)">
<localize key="general_delete" class="ng-isolate-scope ng-scope">Delete</localize>
@@ -81,6 +81,7 @@ angular.module("umbraco")
var notIncludedRte = [];
var cancelMove = false;
var startingArea;
$scope.sortableOptionsCell = {
distance: 10,
@@ -112,9 +113,11 @@ angular.module("umbraco")
},
over: function (event, ui) {
var allowedEditors = $(event.target).scope().area.allowed;
var area = $(event.target).scope().area;
var allowedEditors = area.allowed;
if ($.inArray(ui.item.scope().control.editor.alias, allowedEditors) < 0 && allowedEditors) {
if (($.inArray(ui.item.scope().control.editor.alias, allowedEditors) < 0 && allowedEditors) ||
(startingArea != area && area.maxItems != '' && area.maxItems > 0 && area.maxItems < area.controls.length + 1)) {
$scope.$apply(function () {
$(event.target).scope().area.dropNotAllowed = true;
@@ -168,6 +171,10 @@ angular.module("umbraco")
start: function (e, ui) {
//Get the starting area for reference
var area = $(e.target).scope().area;
startingArea = area;
// fade out control when sorting
ui.item.context.style.display = "block";
ui.item.context.style.opacity = "0.5";
@@ -224,7 +224,7 @@
<!-- Controls repeat end -->
<!-- if area is empty tools -->
<div class="umb-grid-add-more-content" ng-if="area.controls.length > 0 && !sortMode">
<div class="umb-grid-add-more-content" ng-if="area.controls.length > 0 && !sortMode && (area.maxItems == undefined || area.maxItems == '' || area.maxItems == 0 || area.maxItems > area.controls.length)">
<div class="cell-tools-add -bar newbtn" ng-click="openEditorOverlay($event, area, 0, area.$uniqueId);"><localize key="grid_addElement" /></div>
</div>
@@ -65,7 +65,9 @@
ng-repeat="area in layout.areas | filter:zeroWidthFilter"
ng-style="{width: percentage(area.grid) + '%', 'max-width': '100%'}">
<div class="preview-cell"></div>
<div class="preview-cell">
<p style="font-size: 6px; line-height: 8px; text-align: center" ng-show="area.maxItems > 0">{{area.maxItems}}</p>
</div>
</div>
</div>
</div>
@@ -44,7 +44,10 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
function(id) {
var found = _.find(medias,
function(m) {
return m.udi === id || m.id === id;
// We could use coercion (two ='s) here .. but not sure if this works equally well in all browsers and
// it's prone to someone "fixing" it at some point without knowing the effects. Rather use toString()
// compares and be completely sure it works.
return m.udi.toString() === id.toString() || m.id.toString() === id.toString();
});
if (found) {
return found;
+2 -2
View File
@@ -1027,9 +1027,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>7730</DevelopmentServerPort>
<DevelopmentServerPort>7740</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7730</IISUrl>
<IISUrl>http://localhost:7740</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
@@ -6,7 +6,11 @@
string markup = Model.editor.config.markup.ToString();
var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
markup = markup.Replace("#value#", umbracoHelper.ReplaceLineBreaksForHtml(HttpUtility.HtmlEncode(Model.value.ToString())));
markup = markup.Replace("#style#", Model.editor.config.style.ToString());
if (Model.editor.config.style != null)
{
markup = markup.Replace("#style#", Model.editor.config.style.ToString());
}
<text>
@Html.Raw(markup)
@@ -1260,6 +1260,9 @@ Mange hilsner fra Umbraco robotten
<key alias="chooseDefault">Vælg standard</key>
<key alias="areAdded">er tilføjet</key>
<key alias="maxItems">Maksimalt emner</key>
<key alias="maxItemsDescription">Efterlad blank eller sat til 0 ubegrænset for</key>
</area>
<area alias="contentTypeEditor">
+118 -125
View File
@@ -87,14 +87,14 @@
<key alias="domainUpdated">Domain '%0%' has been updated</key>
<key alias="orEdit">Edit Current Domains</key>
<key alias="domainHelp">
<![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
"https://www.example.com/". One-level paths in domains are supported, eg. "example.com/en". However, they
<![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
"https://www.example.com/". One-level paths in domains are supported, eg. "example.com/en". However, they
should be avoided. Better use the culture setting above.]]>
</key>
<key alias="inherit">Inherit</key>
<key alias="setLanguage">Culture</key>
<key alias="setLanguageHelp">
<![CDATA[Set the culture for nodes below the current node,<br /> or inherit culture from parent nodes. Will also apply<br />
<![CDATA[Set the culture for nodes below the current node,<br /> or inherit culture from parent nodes. Will also apply<br />
to the current node, unless a domain below applies too.]]>
</key>
<key alias="setDomains">Domains</key>
@@ -351,11 +351,11 @@
<key alias="tableColumns">Number of columns</key>
<key alias="tableRows">Number of rows</key>
<key alias="templateContentAreaHelp">
<![CDATA[<strong>Set a placeholder id</strong> by setting an ID on your placeholder you can inject content into this template from child templates,
<![CDATA[<strong>Set a placeholder id</strong> by setting an ID on your placeholder you can inject content into this template from child templates,
by referring this ID using a <code>&lt;asp:content /&gt;</code> element.]]>
</key>
<key alias="templateContentPlaceHolderHelp">
<![CDATA[<strong>Select a placeholder id</strong> from the list below. You can only
<![CDATA[<strong>Select a placeholder id</strong> from the list below. You can only
choose Id's from the current template's master.]]>
</key>
<key alias="thumbnailimageclickfororiginal">Click on the image to see full size</key>
@@ -397,15 +397,15 @@
</area>
<area alias="dictionaryItem">
<key alias="description">
<![CDATA[
Edit the different language versions for the dictionary item '<em>%0%</em>' below<br/>You can add additional languages under the 'languages' in the menu on the left
<![CDATA[
Edit the different language versions for the dictionary item '<em>%0%</em>' below<br/>You can add additional languages under the 'languages' in the menu on the left
]]>
</key>
<key alias="displayName">Culture Name</key>
<key alias="changeKey">Edit the key of the dictionary item.</key>
<key alias="changeKeyError">
<![CDATA[
The key '%0%' already exists.
<![CDATA[
The key '%0%' already exists.
]]>
</key>
</area>
@@ -693,35 +693,35 @@
<key alias="databaseFound">Your database has been found and is identified as</key>
<key alias="databaseHeader">Database configuration</key>
<key alias="databaseInstall">
<![CDATA[
Press the <strong>install</strong> button to install the Umbraco %0% database
<![CDATA[
Press the <strong>install</strong> button to install the Umbraco %0% database
]]>
</key>
<key alias="databaseInstallDone"><![CDATA[Umbraco %0% has now been copied to your database. Press <strong>Next</strong> to proceed.]]></key>
<key alias="databaseNotFound">
<![CDATA[<p>Database not found! Please check that the information in the "connection string" of the "web.config" file is correct.</p>
<p>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. </p>
<p>
Click the <strong>retry</strong> button when
done.<br /><a href="http://our.umbraco.org/documentation/Using-Umbraco/Config-files/webconfig7" target="_blank">
<![CDATA[<p>Database not found! Please check that the information in the "connection string" of the "web.config" file is correct.</p>
<p>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. </p>
<p>
Click the <strong>retry</strong> button when
done.<br /><a href="http://our.umbraco.org/documentation/Using-Umbraco/Config-files/webconfig7" target="_blank">
More information on editing web.config here.</a></p>]]>
</key>
<key alias="databaseText">
<![CDATA[To complete this step, you must know some information regarding your database server ("connection string").<br />
Please contact your ISP if necessary.
<![CDATA[To complete this step, you must know some information regarding your database server ("connection string").<br />
Please contact your ISP if necessary.
If you're installing on a local machine or server you might need information from your system administrator.]]>
</key>
<key alias="databaseUpgrade">
<![CDATA[
<p>
Press the <strong>upgrade</strong> button to upgrade your database to Umbraco %0%</p>
<p>
Don't worry - no content will be deleted and everything will continue working afterwards!
</p>
<![CDATA[
<p>
Press the <strong>upgrade</strong> button to upgrade your database to Umbraco %0%</p>
<p>
Don't worry - no content will be deleted and everything will continue working afterwards!
</p>
]]>
</key>
<key alias="databaseUpgradeDone">
<![CDATA[Your database has been upgraded to the final version %0%.<br />Press <strong>Next</strong> to
<![CDATA[Your database has been upgraded to the final version %0%.<br />Press <strong>Next</strong> to
proceed. ]]>
</key>
<key alias="databaseUpToDate"><![CDATA[Your current database is up-to-date!. Click <strong>next</strong> to continue the configuration wizard]]></key>
@@ -736,65 +736,65 @@
<key alias="permissionsAffectedFoldersMoreInfo">More information on setting up permissions for Umbraco here</key>
<key alias="permissionsAffectedFoldersText">You need to grant ASP.NET modify permissions to the following files/folders</key>
<key alias="permissionsAlmostPerfect">
<![CDATA[<strong>Your permission settings are almost perfect!</strong><br /><br />
<![CDATA[<strong>Your permission settings are almost perfect!</strong><br /><br />
You can run Umbraco without problems, but you will not be able to install packages which are recommended to take full advantage of Umbraco.]]>
</key>
<key alias="permissionsHowtoResolve">How to Resolve</key>
<key alias="permissionsHowtoResolveLink">Click here to read the text version</key>
<key alias="permissionsHowtoResolveText"><![CDATA[Watch our <strong>video tutorial</strong> on setting up folder permissions for Umbraco or read the text version.]]></key>
<key alias="permissionsMaybeAnIssue">
<![CDATA[<strong>Your permission settings might be an issue!</strong>
<br/><br />
<![CDATA[<strong>Your permission settings might be an issue!</strong>
<br/><br />
You can run Umbraco without problems, but you will not be able to create folders or install packages which are recommended to take full advantage of Umbraco.]]>
</key>
<key alias="permissionsNotReady">
<![CDATA[<strong>Your permission settings are not ready for Umbraco!</strong>
<br /><br />
<![CDATA[<strong>Your permission settings are not ready for Umbraco!</strong>
<br /><br />
In order to run Umbraco, you'll need to update your permission settings.]]>
</key>
<key alias="permissionsPerfect">
<![CDATA[<strong>Your permission settings are perfect!</strong><br /><br />
<![CDATA[<strong>Your permission settings are perfect!</strong><br /><br />
You are ready to run Umbraco and install packages!]]>
</key>
<key alias="permissionsResolveFolderIssues">Resolving folder issue</key>
<key alias="permissionsResolveFolderIssuesLink">Follow this link for more information on problems with ASP.NET and creating folders</key>
<key alias="permissionsSettingUpPermissions">Setting up folder permissions</key>
<key alias="permissionsText">
<![CDATA[
Umbraco needs write/modify access to certain directories in order to store files like pictures and PDF's.
It also stores temporary data (aka: cache) for enhancing the performance of your website.
<![CDATA[
Umbraco needs write/modify access to certain directories in order to store files like pictures and PDF's.
It also stores temporary data (aka: cache) for enhancing the performance of your website.
]]>
</key>
<key alias="runwayFromScratch">I want to start from scratch</key>
<key alias="runwayFromScratchText">
<![CDATA[
Your website is completely empty at the moment, so that's perfect if you want to start from scratch and create your own document types and templates.
(<a href="http://Umbraco.tv/documentation/videos/for-site-builders/foundation/document-types">learn how</a>)
You can still choose to install Runway later on. Please go to the Developer section and choose Packages.
<![CDATA[
Your website is completely empty at the moment, so that's perfect if you want to start from scratch and create your own document types and templates.
(<a href="http://Umbraco.tv/documentation/videos/for-site-builders/foundation/document-types">learn how</a>)
You can still choose to install Runway later on. Please go to the Developer section and choose Packages.
]]>
</key>
<key alias="runwayHeader">You've just set up a clean Umbraco platform. What do you want to do next?</key>
<key alias="runwayInstalled">Runway is installed</key>
<key alias="runwayInstalledText">
<![CDATA[
You have the foundation in place. Select what modules you wish to install on top of it.<br />
This is our list of recommended modules, check off the ones you would like to install, or view the <a href="#" onclick="toggleModules(); return false;" id="toggleModuleList">full list of modules</a>
<![CDATA[
You have the foundation in place. Select what modules you wish to install on top of it.<br />
This is our list of recommended modules, check off the ones you would like to install, or view the <a href="#" onclick="toggleModules(); return false;" id="toggleModuleList">full list of modules</a>
]]>
</key>
<key alias="runwayOnlyProUsers">Only recommended for experienced users</key>
<key alias="runwaySimpleSite">I want to start with a simple website</key>
<key alias="runwaySimpleSiteText">
<![CDATA[
<p>
"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.
</p>
<small>
<em>Included with Runway:</em> Home page, Getting Started page, Installing Modules page.<br />
<em>Optional Modules:</em> Top Navigation, Sitemap, Contact, Gallery.
</small>
<![CDATA[
<p>
"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.
</p>
<small>
<em>Included with Runway:</em> Home page, Getting Started page, Installing Modules page.<br />
<em>Optional Modules:</em> Top Navigation, Sitemap, Contact, Gallery.
</small>
]]>
</key>
<key alias="runwayWhatIsRunway">What is Runway</key>
@@ -805,24 +805,24 @@
<key alias="step5">Step 5/5: Umbraco is ready to get you started</key>
<key alias="thankYou">Thank you for choosing Umbraco</key>
<key alias="theEndBrowseSite">
<![CDATA[<h3>Browse your new site</h3>
<![CDATA[<h3>Browse your new site</h3>
You installed Runway, so why not see how your new website looks.]]>
</key>
<key alias="theEndFurtherHelp">
<![CDATA[<h3>Further help and information</h3>
<![CDATA[<h3>Further help and information</h3>
Get help from our award winning community, browse the documentation or watch some free videos on how to build a simple site, how to use packages and a quick guide to the Umbraco terminology]]>
</key>
<key alias="theEndHeader">Umbraco %0% is installed and ready for use</key>
<key alias="theEndInstallFailed">
<![CDATA[To finish the installation, you'll need to
<![CDATA[To finish the installation, you'll need to
manually edit the <strong>/web.config file</strong> and update the AppSetting key <strong>UmbracoConfigurationStatus</strong> in the bottom to the value of <strong>'%0%'</strong>.]]>
</key>
<key alias="theEndInstallSuccess">
<![CDATA[You can get <strong>started instantly</strong> by clicking the "Launch Umbraco" button below. <br />If you are <strong>new to Umbraco</strong>,
<![CDATA[You can get <strong>started instantly</strong> by clicking the "Launch Umbraco" button below. <br />If you are <strong>new to Umbraco</strong>,
you can find plenty of resources on our getting started pages.]]>
</key>
<key alias="theEndOpenUmbraco">
<![CDATA[<h3>Launch Umbraco</h3>
<![CDATA[<h3>Launch Umbraco</h3>
To manage your website, simply open the Umbraco back office and start adding content, updating the templates and stylesheets or add new functionality]]>
</key>
<key alias="Unavailable">Connection to database failed.</key>
@@ -830,8 +830,8 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="Version4">Umbraco Version 4</key>
<key alias="watch">Watch</key>
<key alias="welcomeIntro">
<![CDATA[This wizard will guide you through the process of configuring <strong>Umbraco %0%</strong> for a fresh install or upgrading from version 3.0.
<br /><br />
<![CDATA[This wizard will guide you through the process of configuring <strong>Umbraco %0%</strong> for a fresh install or upgrading from version 3.0.
<br /><br />
Press <strong>"next"</strong> to start the wizard.]]>
</key>
</area>
@@ -889,47 +889,47 @@ To manage your website, simply open the Umbraco back office and start adding con
<area alias="notifications">
<key alias="editNotifications">Edit your notification for %0%</key>
<key alias="mailBody">
<![CDATA[
Hi %0%
This is an automated mail to inform you that the task '%1%'
has been performed on the page '%2%'
by the user '%3%'
Go to http://%4%/#/content/content/edit/%5% to edit.
Have a nice day!
Cheers from the Umbraco robot
<![CDATA[
Hi %0%
This is an automated mail to inform you that the task '%1%'
has been performed on the page '%2%'
by the user '%3%'
Go to http://%4%/#/content/content/edit/%5% to edit.
Have a nice day!
Cheers from the Umbraco robot
]]>
</key>
<key alias="mailBodyHtml">
<![CDATA[<p>Hi %0%</p>
<p>This is an automated mail to inform you that the task <strong>'%1%'</strong>
has been performed on the page <a href="http://%4%/#/content/content/edit/%5%"><strong>'%2%'</strong></a>
by the user <strong>'%3%'</strong>
</p>
<div style="margin: 8px 0; padding: 8px; display: block;">
<br />
<a style="color: white; font-weight: bold; background-color: #5372c3; text-decoration : none; margin-right: 20px; border: 8px solid #5372c3; width: 150px;" href="http://%4%/#/content/content/edit/%5%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EDIT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a> &nbsp;
<br />
</div>
<p>
<h3>Update summary:</h3>
<table style="width: 100%;">
%6%
</table>
</p>
<div style="margin: 8px 0; padding: 8px; display: block;">
<br />
<a style="color: white; font-weight: bold; background-color: #5372c3; text-decoration : none; margin-right: 20px; border: 8px solid #5372c3; width: 150px;" href="http://%4%/#/content/content/edit/%5%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EDIT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a> &nbsp;
<br />
</div>
<p>Have a nice day!<br /><br />
Cheers from the Umbraco robot
<![CDATA[<p>Hi %0%</p>
<p>This is an automated mail to inform you that the task <strong>'%1%'</strong>
has been performed on the page <a href="http://%4%/#/content/content/edit/%5%"><strong>'%2%'</strong></a>
by the user <strong>'%3%'</strong>
</p>
<div style="margin: 8px 0; padding: 8px; display: block;">
<br />
<a style="color: white; font-weight: bold; background-color: #5372c3; text-decoration : none; margin-right: 20px; border: 8px solid #5372c3; width: 150px;" href="http://%4%/#/content/content/edit/%5%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EDIT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a> &nbsp;
<br />
</div>
<p>
<h3>Update summary:</h3>
<table style="width: 100%;">
%6%
</table>
</p>
<div style="margin: 8px 0; padding: 8px; display: block;">
<br />
<a style="color: white; font-weight: bold; background-color: #5372c3; text-decoration : none; margin-right: 20px; border: 8px solid #5372c3; width: 150px;" href="http://%4%/#/content/content/edit/%5%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EDIT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a> &nbsp;
<br />
</div>
<p>Have a nice day!<br /><br />
Cheers from the Umbraco robot
</p>]]>
</key>
<key alias="mailSubject">[%0%] Notification about %1% performed on %2%</key>
@@ -937,9 +937,9 @@ To manage your website, simply open the Umbraco back office and start adding con
</area>
<area alias="packager">
<key alias="chooseLocalPackageText">
<![CDATA[
Choose Package from your machine, by clicking the Browse<br />
button and locating the package. Umbraco packages usually have a ".umb" or ".zip" extension.
<![CDATA[
Choose Package from your machine, by clicking the Browse<br />
button and locating the package. Umbraco packages usually have a ".umb" or ".zip" extension.
]]>
</key>
<key alias="dropHere">Drop to upload</key>
@@ -982,7 +982,7 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="packageName">Package name</key>
<key alias="packageNoItemsHeader">Package doesn't contain any items</key>
<key alias="packageNoItemsText">
<![CDATA[This package file doesn't contain any items to uninstall.<br/><br/>
<![CDATA[This package file doesn't contain any items to uninstall.<br/><br/>
You can safely remove this from the system by clicking "uninstall package" below.]]>
</key>
<key alias="packageNoUpgrades">No upgrades available</key>
@@ -994,8 +994,8 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="packageUninstalledText">The package was successfully uninstalled</key>
<key alias="packageUninstallHeader">Uninstall package</key>
<key alias="packageUninstallText">
<![CDATA[You can unselect items you do not wish to remove, at this time, below. When you click "confirm uninstall" all checked-off items will be removed.<br />
<span style="color: Red; font-weight: bold;">Notice:</span> any documents, media etc depending on the items you remove, will stop working, and could lead to system instability,
<![CDATA[You can unselect items you do not wish to remove, at this time, below. When you click "confirm uninstall" all checked-off items will be removed.<br />
<span style="color: Red; font-weight: bold;">Notice:</span> any documents, media etc depending on the items you remove, will stop working, and could lead to system instability,
so uninstall with caution. If in doubt, contact the package author.]]>
</key>
<key alias="packageUpgradeDownload">Download update from the repository</key>
@@ -1042,28 +1042,28 @@ To manage your website, simply open the Umbraco back office and start adding con
</area>
<area alias="publish">
<key alias="contentPublishedFailedAwaitingRelease">
<![CDATA[
%0% could not be published because the item is scheduled for release.
<![CDATA[
%0% could not be published because the item is scheduled for release.
]]>
</key>
<key alias="contentPublishedFailedExpired">
<![CDATA[
%0% could not be published because the item has expired.
<![CDATA[
%0% could not be published because the item has expired.
]]>
</key>
<key alias="contentPublishedFailedInvalid">
<![CDATA[
%0% could not be published because these properties: %1% did not pass validation rules.
<![CDATA[
%0% could not be published because these properties: %1% did not pass validation rules.
]]>
</key>
<key alias="contentPublishedFailedByEvent">
<![CDATA[
%0% could not be published, a 3rd party add-in cancelled the action.
<![CDATA[
%0% could not be published, a 3rd party add-in cancelled the action.
]]>
</key>
<key alias="contentPublishedFailedByParent">
<![CDATA[
%0% can not be published, because a parent page is not published.
<![CDATA[
%0% can not be published, because a parent page is not published.
]]>
</key>
<key alias="includeUnpublished">Include unpublished subpages</key>
@@ -1073,22 +1073,13 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="nodePublishAll">%0% and subpages have been published</key>
<key alias="publishAll">Publish %0% and all its subpages</key>
<key alias="publishHelp">
<![CDATA[Click <em>Publish</em> to publish <strong>%0%</strong> and thereby making its content publicly available.<br/><br />
You can publish this page and all its subpages by checking <em>Include unpublished subpages</em> below.
<![CDATA[Click <em>Publish</em> to publish <strong>%0%</strong> and thereby making its content publicly available.<br/><br />
You can publish this page and all its subpages by checking <em>Include unpublished subpages</em> below.
]]>
</key>
</area>
<area alias="colorpicker">
<key alias="noColors">You have not configured any approved colours</key>
</area>
<area alias="contentPicker">
<key alias="pickedTrashedItem">You have picked a content item currently deleted or in the recycle bin</key>
<key alias="pickedTrashedItems">You have picked content items currently deleted or in the recycle bin</key>
</area>
<area alias="mediaPicker">
<key alias="pickedTrashedItem">You have picked a media item currently deleted or in the recycle bin</key>
<key alias="pickedTrashedItems">You have picked media items currently deleted or in the recycle bin</key>
<key alias="deletedItem">Deleted item</key>
</area>
<area alias="contentPicker">
<key alias="pickedTrashedItem">You have picked a content item currently deleted or in the recycle bin</key>
@@ -1419,6 +1410,8 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="allowAllEditors">Allow all editors</key>
<key alias="allowAllRowConfigurations">Allow all row configurations</key>
<key alias="maxItemsDescription">Leave blank or set to 0 for unlimited</key>
<key alias="maxItems">Maximum items</key>
<key alias="setAsDefault">Set as default</key>
<key alias="chooseExtra">Choose extra</key>
<key alias="chooseDefault">Choose default</key>
@@ -1887,4 +1880,4 @@ To manage your website, simply open the Umbraco back office and start adding con
<area alias="textbox">
<key alias="characters_left">characters left</key>
</area>
</language>
</language>
@@ -1406,6 +1406,8 @@ To manage your website, simply open the Umbraco back office and start adding con
<key alias="allowAllEditors">Allow all editors</key>
<key alias="allowAllRowConfigurations">Allow all row configurations</key>
<key alias="maxItems">Maximum items</key>
<key alias="maxItemsDescription">Leave blank or set to 0 for unlimited</key>
<key alias="setAsDefault">Set as default</key>
<key alias="chooseExtra">Choose extra</key>
<key alias="chooseDefault">Choose default</key>
@@ -789,6 +789,9 @@
<key alias="allowAllEditors">Permitir todos los controles de edición</key>
<key alias="allowAllRowConfigurations">Permitir todas las configuraciones de fila</key>
<key alias="maxItems">Artículos máximos</key>
<key alias="maxItemsDescription">Laat dit leeg of is ingesteld op -1 voor onbeperkt</key>
<key alias="maxItemsDescription">Dejar en blanco o se establece en 0 para ilimitada</key>
</area>
<area alias="templateEditor">
<key alias="alternativeField">Campo opcional</key>
@@ -1077,7 +1077,9 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
<key alias="allowAllEditors">Alle editors toelaten</key>
<key alias="allowAllRowConfigurations">Alle rijconfiguraties toelaten</key>
<key alias="setAsDefault">Instellen als standaard</key>
<key alias="maxItems">Maximale artikelen</key>
<key alias="maxItemsDescription">Laat dit leeg of is ingesteld op -1 voor onbeperkt</key>
<key alias="setAsDefault">Instellen als standaard</key>
<key alias="chooseExtra">Kies extra</key>
<key alias="chooseDefault">Kies standaard</key>
<key alias="areAdded">zijn toegevoegd</key>
@@ -107,7 +107,7 @@ namespace Umbraco.Web.Models.Mapping
}
//fill in the template config to be passed to the template drop down.
var templateItemConfig = new Dictionary<string, string> {{"", localizedText.Localize("general/choose")}};
var templateItemConfig = new Dictionary<string, string>();
foreach (var t in content.ContentType.AllowedTemplates
.Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false))
{
@@ -158,7 +158,9 @@ namespace Umbraco.Web.Models.Mapping
{
Alias = string.Format("{0}template", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
Label = localizedText.Localize("template/template"),
Value = display.TemplateAlias,
Value = string.IsNullOrEmpty(display.TemplateAlias)
? (content.ContentType.DefaultTemplate == null ? "" : content.ContentType.DefaultTemplate.Alias)
: display.TemplateAlias,
View = "dropdown", //TODO: Hard coding until we make a real dropdown property editor to lookup
Config = new Dictionary<string, object>
{
@@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
@@ -11,7 +14,7 @@ namespace Umbraco.Web.PropertyEditors
{
internal class ColorListPreValueEditor : ValueListPreValueEditor
{
public ColorListPreValueEditor()
{
var field = Fields.First();
@@ -23,14 +26,98 @@ namespace Umbraco.Web.PropertyEditors
//change the label
field.Name = "Add color";
//need to have some custom validation happening here
field.Validators.Add(new ColorListValidator());
field.Validators.Add(new ColorListValidator());
Fields.Insert(0, new PreValueField
{
Name = "Include labels?",
View = "boolean",
Key = "useLabel",
Description = "Stores colors as a Json object containing both the color hex string and label, rather than just the hex string."
});
}
public override IDictionary<string, object> ConvertDbToEditor(IDictionary<string, object> defaultPreVals, PreValueCollection persistedPreVals)
{
var dictionary = persistedPreVals.FormatAsDictionary();
var arrayOfVals = dictionary.Select(item => item.Value).ToList();
return new Dictionary<string, object> { { "items", arrayOfVals.ToDictionary(x => x.Id, x => x.Value) } };
var items = dictionary
.Where(x => x.Key != "useLabel")
.ToDictionary(x => x.Value.Id, x => x.Value.Value);
var items2 = new Dictionary<int, object>();
foreach (var item in items)
{
if (item.Value.DetectIsJson() == false)
{
items2[item.Key] = item.Value;
continue;
}
try
{
items2[item.Key] = JsonConvert.DeserializeObject(item.Value);
}
catch
{
// let's say parsing Json failed, so what we have is the string - build json
items2[item.Key] = new JObject { { "color", item.Value }, { "label", item.Value } };
}
}
var result = new Dictionary<string, object> { { "items", items2 } };
var useLabel = dictionary.ContainsKey("useLabel") && dictionary["useLabel"].Value == "1";
if (useLabel)
result["useLabel"] = dictionary["useLabel"].Value;
return result;
}
public override IDictionary<string, PreValue> ConvertEditorToDb(IDictionary<string, object> editorValue, PreValueCollection currentValue)
{
var val = editorValue["items"] as JArray;
var result = new Dictionary<string, PreValue>();
if (val == null) return result;
try
{
object useLabelObj;
var useLabel = false;
if (editorValue.TryGetValue("useLabel", out useLabelObj))
{
useLabel = useLabelObj is string && (string) useLabelObj == "1";
result["useLabel"] = new PreValue(useLabel ? "1" : "0");
}
// get all non-empty values
var index = 0;
foreach (var preValue in val.OfType<JObject>()
.Where(x => x["value"] != null)
.Select(x =>
{
var idString = x["id"] == null ? "0" : x["id"].ToString();
int id;
if (int.TryParse(idString, out id) == false) id = 0;
var color = x["value"].ToString();
if (string.IsNullOrWhiteSpace(color)) return null;
var label = x["label"].ToString();
return new PreValue(id, useLabel
? JsonConvert.SerializeObject(new { value = color, label = label })
: color);
})
.WhereNotNull())
{
result.Add(index.ToInvariantString(), preValue);
index++;
}
}
catch (Exception ex)
{
LogHelper.Error<ValueListPreValueEditor>("Could not deserialize the posted value: " + val, ex);
}
return result;
}
internal class ColorListValidator : IPropertyValidator
@@ -39,7 +126,7 @@ namespace Umbraco.Web.PropertyEditors
{
var json = value as JArray;
if (json == null) yield break;
//validate each item which is a json object
for (var index = 0; index < json.Count; index++)
{
@@ -162,6 +162,13 @@ namespace umbraco.presentation.developer.packages
/*Data types */
cms.businesslogic.datatype.DataTypeDefinition[] umbDataType = cms.businesslogic.datatype.DataTypeDefinition.GetAll();
// sort array by name
Array.Sort(umbDataType, delegate(cms.businesslogic.datatype.DataTypeDefinition umbDataType1, cms.businesslogic.datatype.DataTypeDefinition umbDataType2)
{
return umbDataType1.Text.CompareTo(umbDataType2.Text);
});
foreach (cms.businesslogic.datatype.DataTypeDefinition umbDtd in umbDataType)
{
@@ -773,14 +773,20 @@ namespace umbraco.cms.businesslogic.member
{
var temp = new Hashtable();
var groupIds = new List<int>();
using (var sqlHelper = Application.SqlHelper)
using (var dr = sqlHelper.ExecuteReader(
"select memberGroup from cmsMember2MemberGroup where member = @id",
sqlHelper.CreateParameter("@id", Id)))
{
while (dr.Read())
temp.Add(dr.GetInt("memberGroup"),
new MemberGroup(dr.GetInt("memberGroup")));
groupIds.Add(dr.GetInt("memberGroup"));
}
foreach (var groupId in groupIds)
{
temp.Add(groupId, new MemberGroup(groupId));
}
_groups = temp;
}