Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e7f9902f6 | |||
| dcd2630d6b | |||
| b70f543790 | |||
| 24c1c15b66 | |||
| 4a0cd7228b | |||
| edfe212227 | |||
| e3bc98a155 | |||
| f85532f15e | |||
| b04d71ca5f | |||
| ab4de382f3 | |||
| a293c633fc | |||
| 507e3ece98 | |||
| b77826fd3d | |||
| 4c7358d63b | |||
| 4814612102 | |||
| 6dae4396bb | |||
| dd5560f00b | |||
| b56575fc50 | |||
| b06d30c0f9 | |||
| 9c50e1c48d | |||
| 0688835ac0 | |||
| 353b8f21cd | |||
| 30a0d553d5 | |||
| d0fbc362b2 | |||
| 39c534ef54 | |||
| 7f86166abf | |||
| 838e86469a | |||
| 24b147e2a6 | |||
| 11342ff1df | |||
| bf20af9345 | |||
| c69774e3f2 | |||
| 7de8f5a59a | |||
| 909e3788ea | |||
| 09a92ef6ce | |||
| 7d9c2bcce9 | |||
| 529ae961ff | |||
| 7367c8ef67 | |||
| 361ef2a475 | |||
| d382fcc919 | |||
| aac8451627 | |||
| c96c09f42f | |||
| 50f8f18503 | |||
| 9001cd8a6f | |||
| 1279fd234f |
+2
-2
@@ -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.
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+26
@@ -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>
|
||||
|
||||
+122
-16
@@ -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>
|
||||
|
||||
|
||||
+3
-2
@@ -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>
|
||||
|
||||
+37
-15
@@ -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>
|
||||
|
||||
+4
-1
@@ -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;
|
||||
|
||||
@@ -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">
|
||||
|
||||
|
||||
@@ -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><asp:content /></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%"> EDIT </a>
|
||||
<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%"> EDIT </a>
|
||||
<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%"> EDIT </a>
|
||||
<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%"> EDIT </a>
|
||||
<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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user