Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b0230a1586 |
@@ -113,7 +113,6 @@ build/ApiDocs/*
|
||||
build/ApiDocs/Output/*
|
||||
src/Umbraco.Web.UI.Client/bower_components/*
|
||||
/src/Umbraco.Web.UI/Umbraco/preview
|
||||
/src/Umbraco.Web.UI/Umbraco/preview.old
|
||||
|
||||
#Ignore Rule for output of generated documentation files from Grunt docserve
|
||||
src/Umbraco.Web.UI.Client/docs/api
|
||||
|
||||
@@ -24,7 +24,6 @@ Remember, we're a friendly bunch and are happy with whatever contribution you mi
|
||||
* [Working with the source code](#working-with-the-source-code)
|
||||
* [What branch should I target for my contributions?](#what-branch-should-i-target-for-my-contributions)
|
||||
* [Building Umbraco from source code](#building-umbraco-from-source-code)
|
||||
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
|
||||
|
||||
[How do I even begin?](#how-do-i-even-begin)
|
||||
|
||||
@@ -147,29 +146,6 @@ Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the commun
|
||||
|
||||
After this build completes, you should be able to hit `F5` in Visual Studio to build and run the project. A IISExpress webserver will start and the Umbraco installer will pop up in your browser, follow the directions there to get a working Umbraco install up and running.
|
||||
|
||||
### Keeping your Umbraco fork in sync with the main repository
|
||||
|
||||
We recommend you sync with our repository before you submit your pull request. That way, you can fix any potential merge conflicts and make our lives a little bit easier.
|
||||
|
||||
Also, if you've submitted a pull request three weeks ago and want to work on something new, you'll want to get the latest code to build against of course.
|
||||
|
||||
To sync your fork with this original one, you'll have to add the upstream url, you only have to do this once:
|
||||
|
||||
```
|
||||
git remote add upstream https://github.com/umbraco/Umbraco-CMS.git
|
||||
```
|
||||
|
||||
Then when you want to get the changes from the main repository:
|
||||
|
||||
```
|
||||
git fetch upstream
|
||||
git rebase upstream/dev-v7
|
||||
```
|
||||
|
||||
In this command we're syncing with the `dev-v7` branch, but you can of course choose another one if needed.
|
||||
|
||||
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
|
||||
|
||||
## How do I even begin?
|
||||
|
||||
Great question! The short version goes like this:
|
||||
|
||||
@@ -30,7 +30,7 @@ As an Open Source platform, Umbraco is more than just a CMS. We are transparent
|
||||
|
||||
[Umbraco Cloud](https://umbraco.com) is the easiest and fastest way to use Umbraco yet with full support for all your custom .NET code and intergrations. You're up and running in less than a minute and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14 day trial, no credit card needed.
|
||||
|
||||
If you want to DIY you can [download Umbraco](https://our.umbraco.org/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
|
||||
If you want to DIY you can [download Umbraco](https://our.umbraco.org/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Xloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
|
||||
|
||||
## Community
|
||||
|
||||
|
||||
@@ -376,7 +376,7 @@ function Prepare-Packages
|
||||
Copy-Files "$src\Umbraco.Web.UI\umbraco\js" "*" "$tmp\WebApp\umbraco\js"
|
||||
Copy-Files "$src\Umbraco.Web.UI\umbraco\lib" "*" "$tmp\WebApp\umbraco\lib"
|
||||
Copy-Files "$src\Umbraco.Web.UI\umbraco\views" "*" "$tmp\WebApp\umbraco\views"
|
||||
|
||||
Copy-Files "$src\Umbraco.Web.UI\umbraco\preview" "*" "$tmp\WebApp\umbraco\preview"
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
|
||||
<dependency id="Markdown" version="[1.14.7, 2.0.0)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.7.0, 5.0.0)" />
|
||||
<dependency id="System.ValueTuple" version="[4.4.0, 5.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
*** IMPORTANT NOTICE FOR UPGRADES FROM VERSIONS BELOW 7.7.0 ***
|
||||
*** IMPORTANT NOTICE FOR 7.7 UPGRADES ***
|
||||
|
||||
Be sure to read the version specific upgrade information before proceeding:
|
||||
https://our.umbraco.org/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
|
||||
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.10.3")]
|
||||
[assembly: AssemblyInformationalVersion("7.10.3")]
|
||||
[assembly: AssemblyFileVersion("7.9.2")]
|
||||
[assembly: AssemblyInformationalVersion("7.9.2")]
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.10.3");
|
||||
private static readonly Version Version = new Version("7.9.2");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -122,11 +122,6 @@ namespace Umbraco.Core
|
||||
/// Alias for the Dropdown list, publishing keys datatype.
|
||||
/// </summary>
|
||||
public const string DropdownlistPublishingKeysAlias = "Umbraco.DropdownlistPublishingKeys";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the "new" Dropdown list, that replaces the old four deprecated ones and works as other list based property editors
|
||||
/// </summary>
|
||||
public const string DropDownListFlexibleAlias = "Umbraco.DropDown.Flexible";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Folder browser datatype.
|
||||
@@ -457,4 +452,4 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -459,22 +459,6 @@ namespace Umbraco.Core
|
||||
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
|
||||
var connectionstrings = xml.Root.DescendantsAndSelf("connectionStrings").Single();
|
||||
|
||||
// honour configSource, if its set, change the xml file we are saving the configuration
|
||||
// to the one set in the configSource attribute
|
||||
if (connectionstrings.Attribute("configSource") != null)
|
||||
{
|
||||
var source = connectionstrings.Attribute("configSource").Value;
|
||||
var configFile = IOHelper.MapPath(string.Format("{0}/{1}", SystemDirectories.Root, source));
|
||||
LogHelper.Info<DatabaseContext>("storing ConnectionString in {0}", () => configFile);
|
||||
if (System.IO.File.Exists(configFile))
|
||||
{
|
||||
xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
|
||||
fileName = configFile;
|
||||
}
|
||||
|
||||
connectionstrings = xml.Root.DescendantsAndSelf("connectionStrings").Single();
|
||||
}
|
||||
|
||||
// Update connectionString if it exists, or else create a new appSetting for the given key and value
|
||||
var setting = connectionstrings.Descendants("add").FirstOrDefault(s => s.Attribute("name").Value == Constants.System.UmbracoConnectionName);
|
||||
if (setting == null)
|
||||
|
||||
@@ -203,6 +203,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
get
|
||||
{
|
||||
//by default the packages folder should exist in the data folder
|
||||
return IOHelper.ReturnPath("umbracoPreviewPath", Data + IOHelper.DirSepChar + "preview");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,8 @@ namespace Umbraco.Core
|
||||
if (underlying != null)
|
||||
{
|
||||
// Special case for empty strings for bools/dates which should return null if an empty string.
|
||||
if (input is string inputString)
|
||||
var inputString = input as string;
|
||||
if (inputString != null)
|
||||
{
|
||||
//TODO: Why the check against only bool/date when a string is null/empty? In what scenario can we convert to another type when the string is null or empty other than just being null?
|
||||
if (string.IsNullOrEmpty(inputString) && (underlying == typeof(DateTime) || underlying == typeof(bool)))
|
||||
@@ -167,7 +168,8 @@ namespace Umbraco.Core
|
||||
{
|
||||
// target is not a generic type
|
||||
|
||||
if (input is string inputString)
|
||||
var inputString = input as string;
|
||||
if (inputString != null)
|
||||
{
|
||||
// Try convert from string, returns an Attempt if the string could be
|
||||
// processed (either succeeded or failed), else null if we need to try
|
||||
@@ -216,7 +218,8 @@ namespace Umbraco.Core
|
||||
}
|
||||
|
||||
// Re-check convertables since we altered the input through recursion
|
||||
if (input is IConvertible convertible2)
|
||||
var convertible2 = input as IConvertible;
|
||||
if (convertible2 != null)
|
||||
{
|
||||
return Attempt.Succeed(Convert.ChangeType(convertible2, target));
|
||||
}
|
||||
@@ -274,7 +277,8 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (target == typeof(int))
|
||||
{
|
||||
if (int.TryParse(input, out var value))
|
||||
int value;
|
||||
if (int.TryParse(input, out value))
|
||||
{
|
||||
return Attempt<object>.Succeed(value);
|
||||
}
|
||||
@@ -282,26 +286,30 @@ namespace Umbraco.Core
|
||||
// Because decimal 100.01m will happily convert to integer 100, it
|
||||
// makes sense that string "100.01" *also* converts to integer 100.
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out var value2), Convert.ToInt32(value2));
|
||||
decimal value2;
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out value2), Convert.ToInt32(value2));
|
||||
}
|
||||
|
||||
if (target == typeof(long))
|
||||
{
|
||||
if (long.TryParse(input, out var value))
|
||||
long value;
|
||||
if (long.TryParse(input, out value))
|
||||
{
|
||||
return Attempt<object>.Succeed(value);
|
||||
}
|
||||
|
||||
// Same as int
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out var value2), Convert.ToInt64(value2));
|
||||
decimal value2;
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out value2), Convert.ToInt64(value2));
|
||||
}
|
||||
|
||||
// TODO: Should we do the decimal trick for short, byte, unsigned?
|
||||
|
||||
if (target == typeof(bool))
|
||||
{
|
||||
if (bool.TryParse(input, out var value))
|
||||
bool value;
|
||||
if (bool.TryParse(input, out value))
|
||||
{
|
||||
return Attempt<object>.Succeed(value);
|
||||
}
|
||||
@@ -314,42 +322,53 @@ namespace Umbraco.Core
|
||||
switch (Type.GetTypeCode(target))
|
||||
{
|
||||
case TypeCode.Int16:
|
||||
return Attempt<object>.SucceedIf(short.TryParse(input, out var value), value);
|
||||
short value;
|
||||
return Attempt<object>.SucceedIf(short.TryParse(input, out value), value);
|
||||
|
||||
case TypeCode.Double:
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
return Attempt<object>.SucceedIf(double.TryParse(input2, out var valueD), valueD);
|
||||
double valueD;
|
||||
return Attempt<object>.SucceedIf(double.TryParse(input2, out valueD), valueD);
|
||||
|
||||
case TypeCode.Single:
|
||||
var input3 = NormalizeNumberDecimalSeparator(input);
|
||||
return Attempt<object>.SucceedIf(float.TryParse(input3, out var valueF), valueF);
|
||||
float valueF;
|
||||
return Attempt<object>.SucceedIf(float.TryParse(input3, out valueF), valueF);
|
||||
|
||||
case TypeCode.Char:
|
||||
return Attempt<object>.SucceedIf(char.TryParse(input, out var valueC), valueC);
|
||||
char valueC;
|
||||
return Attempt<object>.SucceedIf(char.TryParse(input, out valueC), valueC);
|
||||
|
||||
case TypeCode.Byte:
|
||||
return Attempt<object>.SucceedIf(byte.TryParse(input, out var valueB), valueB);
|
||||
byte valueB;
|
||||
return Attempt<object>.SucceedIf(byte.TryParse(input, out valueB), valueB);
|
||||
|
||||
case TypeCode.SByte:
|
||||
return Attempt<object>.SucceedIf(sbyte.TryParse(input, out var valueSb), valueSb);
|
||||
sbyte valueSb;
|
||||
return Attempt<object>.SucceedIf(sbyte.TryParse(input, out valueSb), valueSb);
|
||||
|
||||
case TypeCode.UInt32:
|
||||
return Attempt<object>.SucceedIf(uint.TryParse(input, out var valueU), valueU);
|
||||
uint valueU;
|
||||
return Attempt<object>.SucceedIf(uint.TryParse(input, out valueU), valueU);
|
||||
|
||||
case TypeCode.UInt16:
|
||||
return Attempt<object>.SucceedIf(ushort.TryParse(input, out var valueUs), valueUs);
|
||||
ushort valueUs;
|
||||
return Attempt<object>.SucceedIf(ushort.TryParse(input, out valueUs), valueUs);
|
||||
|
||||
case TypeCode.UInt64:
|
||||
return Attempt<object>.SucceedIf(ulong.TryParse(input, out var valueUl), valueUl);
|
||||
ulong valueUl;
|
||||
return Attempt<object>.SucceedIf(ulong.TryParse(input, out valueUl), valueUl);
|
||||
}
|
||||
}
|
||||
else if (target == typeof(Guid))
|
||||
{
|
||||
return Attempt<object>.SucceedIf(Guid.TryParse(input, out var value), value);
|
||||
Guid value;
|
||||
return Attempt<object>.SucceedIf(Guid.TryParse(input, out value), value);
|
||||
}
|
||||
else if (target == typeof(DateTime))
|
||||
{
|
||||
if (DateTime.TryParse(input, out var value))
|
||||
DateTime value;
|
||||
if (DateTime.TryParse(input, out value))
|
||||
{
|
||||
switch (value.Kind)
|
||||
{
|
||||
@@ -369,20 +388,24 @@ namespace Umbraco.Core
|
||||
}
|
||||
else if (target == typeof(DateTimeOffset))
|
||||
{
|
||||
return Attempt<object>.SucceedIf(DateTimeOffset.TryParse(input, out var value), value);
|
||||
DateTimeOffset value;
|
||||
return Attempt<object>.SucceedIf(DateTimeOffset.TryParse(input, out value), value);
|
||||
}
|
||||
else if (target == typeof(TimeSpan))
|
||||
{
|
||||
return Attempt<object>.SucceedIf(TimeSpan.TryParse(input, out var value), value);
|
||||
TimeSpan value;
|
||||
return Attempt<object>.SucceedIf(TimeSpan.TryParse(input, out value), value);
|
||||
}
|
||||
else if (target == typeof(decimal))
|
||||
{
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out var value), value);
|
||||
decimal value;
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out value), value);
|
||||
}
|
||||
else if (input != null && target == typeof(Version))
|
||||
{
|
||||
return Attempt<object>.SucceedIf(Version.TryParse(input, out var value), value);
|
||||
Version value;
|
||||
return Attempt<object>.SucceedIf(Version.TryParse(input, out value), value);
|
||||
}
|
||||
|
||||
// E_NOTIMPL IPAddress, BigInteger
|
||||
@@ -667,7 +690,8 @@ namespace Umbraco.Core
|
||||
{
|
||||
var key = new CompositeTypeTypeKey(source, target);
|
||||
|
||||
if (InputTypeConverterCache.TryGetValue(key, out TypeConverter typeConverter))
|
||||
TypeConverter typeConverter;
|
||||
if (InputTypeConverterCache.TryGetValue(key, out typeConverter))
|
||||
{
|
||||
return typeConverter;
|
||||
}
|
||||
@@ -687,7 +711,8 @@ namespace Umbraco.Core
|
||||
{
|
||||
var key = new CompositeTypeTypeKey(source, target);
|
||||
|
||||
if (DestinationTypeConverterCache.TryGetValue(key, out TypeConverter typeConverter))
|
||||
TypeConverter typeConverter;
|
||||
if (DestinationTypeConverterCache.TryGetValue(key, out typeConverter))
|
||||
{
|
||||
return typeConverter;
|
||||
}
|
||||
@@ -705,7 +730,8 @@ namespace Umbraco.Core
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Type GetCachedGenericNullableType(Type type)
|
||||
{
|
||||
if (NullableGenericCache.TryGetValue(type, out Type underlyingType))
|
||||
Type underlyingType;
|
||||
if (NullableGenericCache.TryGetValue(type, out underlyingType))
|
||||
{
|
||||
return underlyingType;
|
||||
}
|
||||
@@ -724,7 +750,8 @@ namespace Umbraco.Core
|
||||
private static bool GetCachedCanAssign(object input, Type source, Type target)
|
||||
{
|
||||
var key = new CompositeTypeTypeKey(source, target);
|
||||
if (AssignableTypeCache.TryGetValue(key, out bool canConvert))
|
||||
bool canConvert;
|
||||
if (AssignableTypeCache.TryGetValue(key, out canConvert))
|
||||
{
|
||||
return canConvert;
|
||||
}
|
||||
@@ -743,7 +770,8 @@ namespace Umbraco.Core
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool GetCachedCanConvertToBoolean(Type type)
|
||||
{
|
||||
if (BoolConvertCache.TryGetValue(type, out bool result))
|
||||
bool result;
|
||||
if (BoolConvertCache.TryGetValue(type, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
+7
-17
@@ -6,7 +6,6 @@ using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZero
|
||||
@@ -344,24 +343,15 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe
|
||||
|
||||
if (tables.InvariantContains("umbracoUserType") && tables.InvariantContains("umbracoUser"))
|
||||
{
|
||||
if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql)
|
||||
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser") && x.Item3.InvariantEquals("FK_umbracoUser_umbracoUserType_id")))
|
||||
{
|
||||
//In MySql, this will drop the FK according to it's special naming rules
|
||||
Delete.ForeignKey().FromTable("umbracoUser").ForeignColumn("userType").ToTable("umbracoUserType").PrimaryColumn("id");
|
||||
Delete.ForeignKey("FK_umbracoUser_umbracoUserType_id").OnTable("umbracoUser");
|
||||
}
|
||||
else
|
||||
//This is the super old constraint name of the FK for user type so check this one too
|
||||
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser") && x.Item3.InvariantEquals("FK_user_userType")))
|
||||
{
|
||||
//Delete the FK if it exists before dropping the column
|
||||
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser") && x.Item3.InvariantEquals("FK_umbracoUser_umbracoUserType_id")))
|
||||
{
|
||||
Delete.ForeignKey("FK_umbracoUser_umbracoUserType_id").OnTable("umbracoUser");
|
||||
}
|
||||
//This is the super old constraint name of the FK for user type so check this one too
|
||||
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser") && x.Item3.InvariantEquals("FK_user_userType")))
|
||||
{
|
||||
Delete.ForeignKey("FK_user_userType").OnTable("umbracoUser");
|
||||
}
|
||||
}
|
||||
Delete.ForeignKey("FK_user_userType").OnTable("umbracoUser");
|
||||
}
|
||||
|
||||
Delete.Column("userType").FromTable("umbracoUser");
|
||||
Delete.Table("umbracoUserType");
|
||||
@@ -371,4 +361,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe
|
||||
public override void Down()
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
using System.IO;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTenZero
|
||||
{
|
||||
/// <summary>
|
||||
/// Renames the preview folder containing static html files to ensure it does not interfere with the MVC route
|
||||
/// that is now supposed to render these views dynamically. We don't want to delete as people may have made
|
||||
/// customizations to these files that would need to be migrated to the new .cshtml view files.
|
||||
/// </summary>
|
||||
[Migration("7.10.0", 1, Constants.System.UmbracoMigrationName)]
|
||||
public class RenamePreviewFolder : MigrationBase
|
||||
{
|
||||
public RenamePreviewFolder(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
: base(sqlSyntax, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
var previewFolderPath = IOHelper.MapPath(SystemDirectories.Umbraco + "/preview");
|
||||
if (Directory.Exists(previewFolderPath))
|
||||
{
|
||||
var newPath = previewFolderPath.Replace("preview", "preview.old");
|
||||
if (Directory.Exists(newPath) == false)
|
||||
{
|
||||
Directory.Move(previewFolderPath, newPath);
|
||||
var readmeText =
|
||||
$"Static html files used for preview and canvas editing functionality no longer live in this directory.\r\n" +
|
||||
$"Instead they have been recreated as MVC views and can now be found in '~/Umbraco/Views/Preview'.\r\n" +
|
||||
$"See issue: http://issues.umbraco.org/issue/U4-11090";
|
||||
File.WriteAllText(Path.Combine(newPath, "readme.txt"), readmeText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -402,7 +402,7 @@ namespace Umbraco.Core.Persistence
|
||||
}
|
||||
|
||||
// Helper to handle named parameters from object properties
|
||||
static readonly Regex rxParams = new Regex(@"(?<!@)@\w+", RegexOptions.Compiled);
|
||||
static Regex rxParams = new Regex(@"(?<!@)@\w+", RegexOptions.Compiled);
|
||||
public static string ProcessParams(string _sql, object[] args_src, List<object> args_dest)
|
||||
{
|
||||
return rxParams.Replace(_sql, m =>
|
||||
@@ -545,7 +545,7 @@ namespace Umbraco.Core.Persistence
|
||||
}
|
||||
|
||||
// Create a command
|
||||
static readonly Regex rxParamsPrefix = new Regex(@"(?<!@)@\w+", RegexOptions.Compiled);
|
||||
static Regex rxParamsPrefix = new Regex(@"(?<!@)@\w+", RegexOptions.Compiled);
|
||||
public IDbCommand CreateCommand(IDbConnection connection, string sql, params object[] args)
|
||||
{
|
||||
// Perform named argument replacements
|
||||
@@ -666,8 +666,8 @@ namespace Umbraco.Core.Persistence
|
||||
return ExecuteScalar<T>(sql.SQL, sql.Arguments);
|
||||
}
|
||||
|
||||
static readonly Regex rxSelect = new Regex(@"\A\s*(SELECT|EXECUTE|CALL)\s", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
static readonly Regex rxFrom = new Regex(@"\A\s*FROM\s", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
Regex rxSelect = new Regex(@"\A\s*(SELECT|EXECUTE|CALL)\s", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
Regex rxFrom = new Regex(@"\A\s*FROM\s", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
string AddSelectClause<T>(string sql)
|
||||
{
|
||||
if (sql.StartsWith(";"))
|
||||
@@ -701,9 +701,9 @@ namespace Umbraco.Core.Persistence
|
||||
return Fetch<T>(sql.SQL, sql.Arguments);
|
||||
}
|
||||
|
||||
static readonly Regex rxColumns = new Regex(@"\A\s*SELECT\s+((?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?<!,\s+)\bFROM\b", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
static readonly Regex rxOrderBy = new Regex(@"\bORDER\s+BY\s+(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
static readonly Regex rxDistinct = new Regex(@"\ADISTINCT\s", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
static Regex rxColumns = new Regex(@"\A\s*SELECT\s+((?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?<!,\s+)\bFROM\b", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
static Regex rxOrderBy = new Regex(@"\bORDER\s+BY\s+(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
static Regex rxDistinct = new Regex(@"\ADISTINCT\s", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
public static bool SplitSqlForPaging(string sql, out string sqlCount, out string sqlSelectRemoved, out string sqlOrderBy)
|
||||
{
|
||||
sqlSelectRemoved = null;
|
||||
@@ -2546,4 +2546,5 @@ namespace Umbraco.Core.Persistence
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
@@ -15,7 +14,19 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
return source.TryConvertTo<int>().Result;
|
||||
if (source == null) return 0;
|
||||
|
||||
// in XML an integer is a string
|
||||
var sourceString = source as string;
|
||||
if (sourceString != null)
|
||||
{
|
||||
int i;
|
||||
return (int.TryParse(sourceString, out i)) ? i : 0;
|
||||
}
|
||||
|
||||
// in the database an integer is an integer
|
||||
// default value is zero
|
||||
return (source is int) ? source : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace Umbraco.Core.Scoping
|
||||
public NoScope(ScopeProvider scopeProvider)
|
||||
{
|
||||
_scopeProvider = scopeProvider;
|
||||
Timestamp = DateTime.Now;
|
||||
#if DEBUG_SCOPES
|
||||
_scopeProvider.RegisterScope(this);
|
||||
#endif
|
||||
@@ -29,8 +28,6 @@ namespace Umbraco.Core.Scoping
|
||||
private readonly Guid _instanceId = Guid.NewGuid();
|
||||
public Guid InstanceId { get { return _instanceId; } }
|
||||
|
||||
public DateTime Timestamp { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CallContext { get { return false; } }
|
||||
|
||||
|
||||
@@ -374,7 +374,7 @@ namespace Umbraco.Core.Scoping
|
||||
}
|
||||
|
||||
var parent = ParentScope;
|
||||
_scopeProvider.AmbientScope = parent; // might be null = this is how scopes are removed from context objects
|
||||
_scopeProvider.AmbientScope = parent;
|
||||
|
||||
#if DEBUG_SCOPES
|
||||
_scopeProvider.Disposed(this);
|
||||
|
||||
@@ -2,12 +2,10 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
#if DEBUG_SCOPES
|
||||
using System.Linq;
|
||||
@@ -68,38 +66,22 @@ namespace Umbraco.Core.Scoping
|
||||
// tests, any other things (see https://msdn.microsoft.com/en-us/library/dn458353(v=vs.110).aspx),
|
||||
// but we don't want to make all of our objects serializable since they are *not* meant to be
|
||||
// used in cross-AppDomain scenario anyways.
|
||||
//
|
||||
// in addition, whatever goes into the logical call context is serialized back and forth any
|
||||
// time cross-AppDomain code executes, so if we put an "object" there, we'll get *another*
|
||||
// "object" instance back - and so we cannot use a random object as a key.
|
||||
//
|
||||
// time cross-AppDomain code executes, so if we put an "object" there, we'll can *another*
|
||||
// "object" instance - and so we cannot use a random object as a key.
|
||||
// so what we do is: we register a guid in the call context, and we keep a table mapping those
|
||||
// guids to the actual objects. the guid serializes back and forth without causing any issue,
|
||||
// and we can retrieve the actual objects from the table.
|
||||
// only issue: how are we supposed to clear the table? we can't, really. objects should take
|
||||
// care of de-registering themselves from context.
|
||||
// everything we use does, except the NoScope scope, which just stays there
|
||||
//
|
||||
// so far, the only objects that go into this table are scopes (using ScopeItemKey) and
|
||||
// scope contexts (using ContextItemKey).
|
||||
// during tests, NoScope can to into call context... nothing much we can do about it
|
||||
|
||||
private static readonly object StaticCallContextObjectsLock = new object();
|
||||
private static readonly Dictionary<Guid, object> StaticCallContextObjects
|
||||
= new Dictionary<Guid, object>();
|
||||
|
||||
// normal scopes and scope contexts take greate care removing themselves when disposed, so it
|
||||
// is all safe. OTOH the NoScope *CANNOT* remove itself, this is by design, it *WILL* leak and
|
||||
// there is little (nothing) we can do about it - NoScope exists for backward compatibility
|
||||
// reasons and relying on it is greatly discouraged.
|
||||
//
|
||||
// however... we can *try* at protecting the app against memory leaks, by collecting NoScope
|
||||
// instances that are too old. if anything actually *need* to retain a NoScope instance for
|
||||
// a long time, it will break. but that's probably ok. so: the constants below define how
|
||||
// long a NoScope instance can stay in the table before being removed, and how often we should
|
||||
// collect the table - and collecting happens anytime SetCallContextObject is invoked
|
||||
|
||||
private static readonly TimeSpan StaticCallContextNoScopeLifeSpan = TimeSpan.FromMinutes(30);
|
||||
private static readonly TimeSpan StaticCallContextCollectPeriod = TimeSpan.FromMinutes(4);
|
||||
private static DateTime _staticCallContextLastCollect = DateTime.MinValue;
|
||||
|
||||
|
||||
#if DEBUG_SCOPES
|
||||
public Dictionary<Guid, object> CallContextObjects
|
||||
{
|
||||
@@ -174,7 +156,6 @@ namespace Umbraco.Core.Scoping
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("At:\r\n" + Head(Environment.StackTrace, 24));
|
||||
#endif
|
||||
StaticCallContextObjects.Remove(objectKey);
|
||||
CollectStaticCallContextObjectsLocked();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -190,37 +171,11 @@ namespace Umbraco.Core.Scoping
|
||||
//Logging.LogHelper.Debug<ScopeProvider>("At:\r\n" + Head(Environment.StackTrace, 24));
|
||||
#endif
|
||||
StaticCallContextObjects.Add(objectKey, value);
|
||||
CollectStaticCallContextObjectsLocked();
|
||||
}
|
||||
CallContext.LogicalSetData(key, objectKey);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CollectStaticCallContextObjectsLocked()
|
||||
{
|
||||
// is it time to collect?
|
||||
var now = DateTime.Now;
|
||||
if (now - _staticCallContextLastCollect <= StaticCallContextCollectPeriod)
|
||||
return;
|
||||
|
||||
// disable warning: this method is invoked from within a lock
|
||||
// ReSharper disable InconsistentlySynchronizedField
|
||||
var threshold = now.Add(-StaticCallContextNoScopeLifeSpan);
|
||||
var guids = StaticCallContextObjects
|
||||
.Where(x => x.Value is NoScope noScope && noScope.Timestamp < threshold)
|
||||
.Select(x => x.Key)
|
||||
.ToList();
|
||||
if (guids.Count > 0)
|
||||
{
|
||||
LogHelper.Warn<ScopeProvider>($"Collected {guids.Count} NoScope instances from StaticCallContextObjects.");
|
||||
foreach (var guid in guids)
|
||||
StaticCallContextObjects.Remove(guid);
|
||||
}
|
||||
// ReSharper restore InconsistentlySynchronizedField
|
||||
|
||||
_staticCallContextLastCollect = now;
|
||||
}
|
||||
|
||||
// this is for tests exclusively until we have a proper accessor in v8
|
||||
internal static Func<IDictionary> HttpContextItemsGetter { get; set; }
|
||||
|
||||
|
||||
@@ -37,15 +37,15 @@ namespace Umbraco.Core.Security
|
||||
var username = identity.GetUserName();
|
||||
var session = identity.FindFirstValue(Constants.Security.SessionIdClaimType);
|
||||
var securityStamp = identity.FindFirstValue(Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType);
|
||||
var startContentId = identity.FindFirstValue(Constants.Security.StartContentNodeIdClaimType);
|
||||
var startContentId = identity.FindFirstValue(Constants.Security.StartContentNodeIdClaimType);
|
||||
var startMediaId = identity.FindFirstValue(Constants.Security.StartMediaNodeIdClaimType);
|
||||
|
||||
var culture = identity.FindFirstValue(ClaimTypes.Locality);
|
||||
var id = identity.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
var id = identity.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
var realName = identity.FindFirstValue(ClaimTypes.GivenName);
|
||||
|
||||
if (username == null || startContentId == null || startMediaId == null
|
||||
|| culture == null || id == null
|
||||
if (username == null || startContentId == null || startMediaId == null
|
||||
|| culture == null || id == null
|
||||
|| realName == null || session == null)
|
||||
throw new InvalidOperationException("Cannot create a " + typeof(UmbracoBackOfficeIdentity) + " from " + typeof(ClaimsIdentity) + " since there are missing required claims");
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Umbraco.Core.Security
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot create a " + typeof(UmbracoBackOfficeIdentity) + " from " + typeof(ClaimsIdentity) + " since the data is not formatted correctly - either content or media start Ids could not be parsed as JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
var roles = identity.FindAll(x => x.Type == DefaultRoleClaimType).Select(role => role.Value).ToList();
|
||||
var allowedApps = identity.FindAll(x => x.Type == Constants.Security.AllowedApplicationsClaimType).Select(app => app.Value).ToList();
|
||||
@@ -165,7 +165,7 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
foreach (var claim in claimsIdentity.Claims)
|
||||
{
|
||||
//In one special case we will replace a claim if it exists already and that is the
|
||||
//In one special case we will replace a claim if it exists already and that is the
|
||||
// Forms auth claim for name which automatically gets added
|
||||
TryRemoveClaim(FindFirst(x => x.Type == claim.Type && x.Issuer == "Forms"));
|
||||
|
||||
@@ -187,15 +187,15 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
ClaimTypes.NameIdentifier, //id
|
||||
ClaimTypes.Name, //username
|
||||
ClaimTypes.GivenName,
|
||||
ClaimTypes.GivenName,
|
||||
Constants.Security.StartContentNodeIdClaimType,
|
||||
Constants.Security.StartMediaNodeIdClaimType,
|
||||
ClaimTypes.Locality,
|
||||
Constants.Security.StartMediaNodeIdClaimType,
|
||||
ClaimTypes.Locality,
|
||||
Constants.Security.SessionIdClaimType,
|
||||
Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds claims based on the UserData data
|
||||
@@ -222,19 +222,23 @@ namespace Umbraco.Core.Security
|
||||
AddClaim(new Claim(ClaimTypes.Locality, Culture, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
|
||||
if (HasClaim(x => x.Type == Constants.Security.SessionIdClaimType) == false && SessionId.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
AddClaim(new Claim(Constants.Security.SessionIdClaimType, SessionId, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
|
||||
//The security stamp claim is also required... this is because this claim type is hard coded
|
||||
// by the SecurityStampValidator, see: https://katanaproject.codeplex.com/workitem/444
|
||||
if (HasClaim(x => x.Type == Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType) == false)
|
||||
AddClaim(new Claim(Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType, SecurityStamp, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
//The security stamp claim is also required... this is because this claim type is hard coded
|
||||
// by the SecurityStampValidator, see: https://katanaproject.codeplex.com/workitem/444
|
||||
if (HasClaim(x => x.Type == Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType) == false)
|
||||
{
|
||||
AddClaim(new Claim(Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType, SecurityStamp, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
}
|
||||
}
|
||||
|
||||
//Add each app as a separate claim
|
||||
if (HasClaim(x => x.Type == Constants.Security.AllowedApplicationsClaimType) == false)
|
||||
{
|
||||
foreach (var application in AllowedApplications)
|
||||
{
|
||||
AddClaim(new Claim(Constants.Security.AllowedApplicationsClaimType, application, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
AddClaim(new Claim(Constants.Security.AllowedApplicationsClaimType, application, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,8 +253,8 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected internal UserData UserData { get; private set; }
|
||||
@@ -328,4 +332,4 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -23,139 +22,13 @@ namespace Umbraco.Core.Services
|
||||
// note - no need for uow, scope would be enough, but a pain to wire
|
||||
// note - for pure read-only we might want to *not* enforce a transaction?
|
||||
|
||||
// notes
|
||||
//
|
||||
// - this class assumes that the id/guid map is unique; that is, if an id and a guid map
|
||||
// to each other, then the id will never map to another guid, and the guid will never map
|
||||
// to another id
|
||||
//
|
||||
// - LeeK's solution in 7.7 was to look for the id/guid in the content cache "on demand" via
|
||||
// XPath, which is probably fast enough but cannot deal with media ids + it maintains a
|
||||
// separate, duplicate cache
|
||||
// see https://github.com/umbraco/Umbraco-CMS/pull/2398
|
||||
//
|
||||
// - Andy's solution in a package was to prefetch all by sql; it cannot prefecth reserved ids
|
||||
// as we don't know the corresponding object type, but that's not a big issue - but then we
|
||||
// have a full database query on startup
|
||||
// see https://github.com/AndyButland/UmbracoUdiToIdCache
|
||||
//
|
||||
// - the original IdkMap implementation that was used by services, did a database lookup on
|
||||
// each cache miss, which is fine enough for services, but would be really slow at content
|
||||
// cache level
|
||||
//
|
||||
// - cache is cleared by MediaCacheRefresher, UnpublishedPageCacheRefresher, and other
|
||||
// refreshers - because id/guid map is unique, we only clear to avoid leaking memory, 'cos
|
||||
// we don't risk caching obsolete values - and only when actually deleting
|
||||
//
|
||||
// so...
|
||||
//
|
||||
// - there's a single caching point, and it's idkMap
|
||||
// - there are no "helper methods" - the published content cache itself knows about Guids
|
||||
// - when the published content cache is instanciated, it populates the idkMap with what it knows
|
||||
// and it registers a way for the idkMap to look for id/keys in the published content cache
|
||||
// - we do NOT prefetch anything from database
|
||||
// - when a request comes in:
|
||||
// the published content cache uses the idkMap to map id/key
|
||||
// if the idkMap already knows about the map, it returns the value
|
||||
// else it tries the published cache via XPath
|
||||
// else it hits the database
|
||||
|
||||
|
||||
private readonly ConcurrentDictionary<UmbracoObjectTypes, (Func<int, Guid> id2key, Func<Guid, int> key2id)> _dictionary
|
||||
= new ConcurrentDictionary<UmbracoObjectTypes, (Func<int, Guid> id2key, Func<Guid, int> key2id)>();
|
||||
|
||||
internal void SetMapper(UmbracoObjectTypes umbracoObjectType, Func<int, Guid> id2key, Func<Guid, int> key2id)
|
||||
{
|
||||
_dictionary[umbracoObjectType] = (id2key, key2id);
|
||||
}
|
||||
|
||||
internal void Populate(IEnumerable<(int id, Guid key)> pairs, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
foreach (var pair in pairs)
|
||||
{
|
||||
_id2Key.Add(pair.id, new TypedId<Guid>(pair.key, umbracoObjectType));
|
||||
_key2Id.Add(pair.key, new TypedId<int>(pair.id, umbracoObjectType));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsWriteLockHeld)
|
||||
_locker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
#if POPULATE_FROM_DATABASE
|
||||
private void PopulateLocked()
|
||||
{
|
||||
// don't if not empty
|
||||
if (_key2Id.Count > 0) return;
|
||||
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
// populate content and media items
|
||||
var types = new[] { Constants.ObjectTypes.Document, Constants.ObjectTypes.Media };
|
||||
var values = uow.Database.Query<TypedIdDto>("SELECT id, uniqueId, nodeObjectType FROM umbracoNode WHERE nodeObjectType IN @types", new { types });
|
||||
foreach (var value in values)
|
||||
{
|
||||
var umbracoObjectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(value.NodeObjectType);
|
||||
_id2Key.Add(value.Id, new TypedId<Guid>(value.UniqueId, umbracoObjectType));
|
||||
_key2Id.Add(value.UniqueId, new TypedId<int>(value.Id, umbracoObjectType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Attempt<int> PopulateAndGetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
|
||||
PopulateLocked();
|
||||
|
||||
return _key2Id.TryGetValue(key, out var id) && id.UmbracoObjectType == umbracoObjectType
|
||||
? Attempt.Succeed(id.Id)
|
||||
: Attempt<int>.Fail();
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsReadLockHeld)
|
||||
_locker.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
private Attempt<Guid> PopulateAndGetKeyForId(int id, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
|
||||
PopulateLocked();
|
||||
|
||||
return _id2Key.TryGetValue(id, out var key) && key.UmbracoObjectType == umbracoObjectType
|
||||
? Attempt.Succeed(key.Id)
|
||||
: Attempt<Guid>.Fail();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsReadLockHeld)
|
||||
_locker.ExitReadLock();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public Attempt<int> GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
bool empty;
|
||||
|
||||
TypedId<int> id;
|
||||
try
|
||||
{
|
||||
_locker.EnterReadLock();
|
||||
if (_key2Id.TryGetValue(key, out var id) && id.UmbracoObjectType == umbracoObjectType) return Attempt.Succeed(id.Id);
|
||||
empty = _key2Id.Count == 0;
|
||||
if (_key2Id.TryGetValue(key, out id) && id.UmbracoObjectType == umbracoObjectType) return Attempt.Succeed(id.Id);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -163,37 +36,20 @@ namespace Umbraco.Core.Services
|
||||
_locker.ExitReadLock();
|
||||
}
|
||||
|
||||
#if POPULATE_FROM_DATABASE
|
||||
// if cache is empty and looking for a document or a media,
|
||||
// populate the cache at once and return what we found
|
||||
if (empty && (umbracoObjectType == UmbracoObjectTypes.Document || umbracoObjectType == UmbracoObjectTypes.Media))
|
||||
return PopulateAndGetIdForKey(key, umbracoObjectType);
|
||||
#endif
|
||||
|
||||
// optimize for read speed: reading database outside a lock means that we could read
|
||||
// multiple times, but we don't lock the cache while accessing the database = better
|
||||
|
||||
int? val = null;
|
||||
|
||||
if (_dictionary.TryGetValue(umbracoObjectType, out var mappers))
|
||||
if ((val = mappers.key2id(key)) == default(int)) val = null;
|
||||
|
||||
if (val == null)
|
||||
int? val;
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
//if it's unknown don't include the nodeObjectType in the query
|
||||
if (umbracoObjectType == UmbracoObjectTypes.Unknown)
|
||||
{
|
||||
//if it's unknown don't include the nodeObjectType in the query
|
||||
if (umbracoObjectType == UmbracoObjectTypes.Unknown)
|
||||
{
|
||||
val = uow.Database.ExecuteScalar<int?>("SELECT id FROM umbracoNode WHERE uniqueId=@id", new { id = key});
|
||||
}
|
||||
else
|
||||
{
|
||||
val = uow.Database.ExecuteScalar<int?>("SELECT id FROM umbracoNode WHERE uniqueId=@id AND (nodeObjectType=@type OR nodeObjectType=@reservation)",
|
||||
new { id = key, type = GetNodeObjectTypeGuid(umbracoObjectType), reservation = Constants.ObjectTypes.IdReservationGuid });
|
||||
}
|
||||
uow.Commit();
|
||||
val = uow.Database.ExecuteScalar<int?>("SELECT id FROM umbracoNode WHERE uniqueId=@id", new { id = key});
|
||||
}
|
||||
else
|
||||
{
|
||||
val = uow.Database.ExecuteScalar<int?>("SELECT id FROM umbracoNode WHERE uniqueId=@id AND (nodeObjectType=@type OR nodeObjectType=@reservation)",
|
||||
new { id = key, type = GetNodeObjectTypeGuid(umbracoObjectType), reservation = Constants.ObjectTypes.IdReservationGuid });
|
||||
}
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
if (val == null) return Attempt<int>.Fail();
|
||||
@@ -227,23 +83,13 @@ namespace Umbraco.Core.Services
|
||||
return GetIdForKey(guidUdi.Guid, umbracoType);
|
||||
}
|
||||
|
||||
public Attempt<Udi> GetUdiForId(int id, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
var keyAttempt = GetKeyForId(id, umbracoObjectType);
|
||||
return keyAttempt
|
||||
? Attempt.Succeed<Udi>(new GuidUdi(Constants.UdiEntityType.FromUmbracoObjectType(umbracoObjectType), keyAttempt.Result))
|
||||
: Attempt<Udi>.Fail();
|
||||
}
|
||||
|
||||
public Attempt<Guid> GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
bool empty;
|
||||
|
||||
TypedId<Guid> key;
|
||||
try
|
||||
{
|
||||
_locker.EnterReadLock();
|
||||
if (_id2Key.TryGetValue(id, out var key) && key.UmbracoObjectType == umbracoObjectType) return Attempt.Succeed(key.Id);
|
||||
empty = _id2Key.Count == 0;
|
||||
if (_id2Key.TryGetValue(id, out key) && key.UmbracoObjectType == umbracoObjectType) return Attempt.Succeed(key.Id);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -251,37 +97,20 @@ namespace Umbraco.Core.Services
|
||||
_locker.ExitReadLock();
|
||||
}
|
||||
|
||||
#if POPULATE_FROM_DATABASE
|
||||
// if cache is empty and looking for a document or a media,
|
||||
// populate the cache at once and return what we found
|
||||
if (empty && (umbracoObjectType == UmbracoObjectTypes.Document || umbracoObjectType == UmbracoObjectTypes.Media))
|
||||
return PopulateAndGetKeyForId(id, umbracoObjectType);
|
||||
#endif
|
||||
|
||||
// optimize for read speed: reading database outside a lock means that we could read
|
||||
// multiple times, but we don't lock the cache while accessing the database = better
|
||||
|
||||
Guid? val = null;
|
||||
|
||||
if (_dictionary.TryGetValue(umbracoObjectType, out var mappers))
|
||||
if ((val = mappers.id2key(id)) == default(Guid)) val = null;
|
||||
|
||||
if (val == null)
|
||||
Guid? val;
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
//if it's unknown don't include the nodeObjectType in the query
|
||||
if (umbracoObjectType == UmbracoObjectTypes.Unknown)
|
||||
{
|
||||
//if it's unknown don't include the nodeObjectType in the query
|
||||
if (umbracoObjectType == UmbracoObjectTypes.Unknown)
|
||||
{
|
||||
val = uow.Database.ExecuteScalar<Guid?>("SELECT uniqueId FROM umbracoNode WHERE id=@id", new { id });
|
||||
}
|
||||
else
|
||||
{
|
||||
val = uow.Database.ExecuteScalar<Guid?>("SELECT uniqueId FROM umbracoNode WHERE id=@id AND (nodeObjectType=@type OR nodeObjectType=@reservation)",
|
||||
new { id, type = GetNodeObjectTypeGuid(umbracoObjectType), reservation = Constants.ObjectTypes.IdReservationGuid });
|
||||
}
|
||||
uow.Commit();
|
||||
val = uow.Database.ExecuteScalar<Guid?>("SELECT uniqueId FROM umbracoNode WHERE id=@id", new { id });
|
||||
}
|
||||
else
|
||||
{
|
||||
val = uow.Database.ExecuteScalar<Guid?>("SELECT uniqueId FROM umbracoNode WHERE id=@id AND (nodeObjectType=@type OR nodeObjectType=@reservation)",
|
||||
new { id, type = GetNodeObjectTypeGuid(umbracoObjectType), reservation = Constants.ObjectTypes.IdReservationGuid });
|
||||
}
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
if (val == null) return Attempt<Guid>.Fail();
|
||||
@@ -313,8 +142,6 @@ namespace Umbraco.Core.Services
|
||||
return guid;
|
||||
}
|
||||
|
||||
// invoked on UnpublishedPageCacheRefresher.RefreshAll
|
||||
// anything else will use the id-specific overloads
|
||||
public void ClearCache()
|
||||
{
|
||||
try
|
||||
@@ -335,7 +162,8 @@ namespace Umbraco.Core.Services
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
if (_id2Key.TryGetValue(id, out var key) == false) return;
|
||||
TypedId<Guid> key;
|
||||
if (_id2Key.TryGetValue(id, out key) == false) return;
|
||||
_id2Key.Remove(id);
|
||||
_key2Id.Remove(key.Id);
|
||||
}
|
||||
@@ -351,7 +179,8 @@ namespace Umbraco.Core.Services
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
if (_key2Id.TryGetValue(key, out var id) == false) return;
|
||||
TypedId<int> id;
|
||||
if (_key2Id.TryGetValue(key, out id) == false) return;
|
||||
_id2Key.Remove(id.Id);
|
||||
_key2Id.Remove(key);
|
||||
}
|
||||
@@ -362,28 +191,26 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
// ReSharper disable ClassNeverInstantiated.Local
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
||||
private class TypedIdDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public Guid UniqueId { get; set; }
|
||||
public Guid NodeObjectType { get; set; }
|
||||
}
|
||||
// ReSharper restore ClassNeverInstantiated.Local
|
||||
// ReSharper restore UnusedAutoPropertyAccessor.Local
|
||||
|
||||
private struct TypedId<T>
|
||||
{
|
||||
public TypedId(T id, UmbracoObjectTypes umbracoObjectType)
|
||||
private readonly T _id;
|
||||
private readonly UmbracoObjectTypes _umbracoObjectType;
|
||||
|
||||
public T Id
|
||||
{
|
||||
UmbracoObjectType = umbracoObjectType;
|
||||
Id = id;
|
||||
get { return _id; }
|
||||
}
|
||||
|
||||
public UmbracoObjectTypes UmbracoObjectType { get; }
|
||||
public UmbracoObjectTypes UmbracoObjectType
|
||||
{
|
||||
get { return _umbracoObjectType; }
|
||||
}
|
||||
|
||||
public T Id { get; }
|
||||
public TypedId(T id, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
_umbracoObjectType = umbracoObjectType;
|
||||
_id = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,17 +207,20 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
return repository.GetByUsername(username, includeSecurityData: true);
|
||||
}
|
||||
catch (DbException ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
//we need to handle this one specific case which is when we are upgrading to 7.7 since the user group
|
||||
//tables don't exist yet. This is the 'easiest' way to deal with this without having to create special
|
||||
//version checks in the BackOfficeSignInManager and calling into other special overloads that we'd need
|
||||
//like "GetUserById(int id, bool includeSecurityData)" which may cause confusion because the result of
|
||||
//that method would not be cached.
|
||||
if (ApplicationContext.Current.IsUpgrading)
|
||||
if (ex is SqlException || ex is SqlCeException)
|
||||
{
|
||||
//NOTE: this will not be cached
|
||||
return repository.GetByUsername(username, includeSecurityData: false);
|
||||
//we need to handle this one specific case which is when we are upgrading to 7.7 since the user group
|
||||
//tables don't exist yet. This is the 'easiest' way to deal with this without having to create special
|
||||
//version checks in the BackOfficeSignInManager and calling into other special overloads that we'd need
|
||||
//like "GetUserById(int id, bool includeSecurityData)" which may cause confusion because the result of
|
||||
//that method would not be cached.
|
||||
if (ApplicationContext.Current.IsUpgrading)
|
||||
{
|
||||
//NOTE: this will not be cached
|
||||
return repository.GetByUsername(username, includeSecurityData: false);
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
@@ -786,17 +789,20 @@ namespace Umbraco.Core.Services
|
||||
var result = repository.Get(id);
|
||||
return result;
|
||||
}
|
||||
catch (DbException ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
//we need to handle this one specific case which is when we are upgrading to 7.7 since the user group
|
||||
//tables don't exist yet. This is the 'easiest' way to deal with this without having to create special
|
||||
//version checks in the BackOfficeSignInManager and calling into other special overloads that we'd need
|
||||
//like "GetUserById(int id, bool includeSecurityData)" which may cause confusion because the result of
|
||||
//that method would not be cached.
|
||||
if (ApplicationContext.Current.IsUpgrading)
|
||||
if (ex is SqlException || ex is SqlCeException)
|
||||
{
|
||||
//NOTE: this will not be cached
|
||||
return repository.Get(id, includeSecurityData: false);
|
||||
//we need to handle this one specific case which is when we are upgrading to 7.7 since the user group
|
||||
//tables don't exist yet. This is the 'easiest' way to deal with this without having to create special
|
||||
//version checks in the BackOfficeSignInManager and calling into other special overloads that we'd need
|
||||
//like "GetUserById(int id, bool includeSecurityData)" which may cause confusion because the result of
|
||||
//that method would not be cached.
|
||||
if (ApplicationContext.Current.IsUpgrading)
|
||||
{
|
||||
//NOTE: this will not be cached
|
||||
return repository.Get(id, includeSecurityData: false);
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -115,9 +115,6 @@
|
||||
<Reference Include="System.Runtime.Caching" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.ApplicationServices" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
@@ -606,7 +603,6 @@
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\NormalizeTemplateGuids.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\RemovePropertyDataIdIndex.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenSixZero\RemoveUmbracoDeployTables.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTenZero\RenamePreviewFolder.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeTwo\EnsureMigrationsTableIdentityIsCorrect.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFourZero\EnsureContentTypeUniqueIdsAreConsistent.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddExternalLoginsTable.cs" />
|
||||
|
||||
@@ -18,5 +18,4 @@
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="semver" version="1.1.2" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.ValueTuple" version="4.4.0" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -139,8 +139,8 @@
|
||||
<Reference Include="System.Threading.Thread, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
|
||||
<Reference Include="System.ValueTuple, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
|
||||
@@ -62,10 +62,6 @@
|
||||
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -51,7 +51,7 @@
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Threading.Tasks.Parallel" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Threading.Thread" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.ValueTuple" version="4.4.0" targetFramework="net46" />
|
||||
<package id="System.ValueTuple" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="net46" />
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.UI;
|
||||
|
||||
@@ -0,0 +1,605 @@
|
||||
module.exports = function (grunt) {
|
||||
|
||||
|
||||
|
||||
// Default task.
|
||||
grunt.registerTask('default', ['jshint:dev', 'build', 'karma:unit']);
|
||||
grunt.registerTask('dev', ['jshint:dev', 'build-dev', 'webserver', 'open:dev', 'watch']);
|
||||
grunt.registerTask('docserve', ['docs:api', 'connect:docserver', 'open:docs', 'watch:docs']);
|
||||
grunt.registerTask('vs', ['jshint:dev', 'build-dev', 'watch']);
|
||||
|
||||
//TODO: Too much watching, this brings windows to it's knees when in dev mode
|
||||
//run by the watch task
|
||||
grunt.registerTask('watch-js', ['jshint:dev', 'concat', 'copy:app', 'copy:mocks', 'copy:canvasdesigner', 'copy:vs', 'karma:unit']);
|
||||
grunt.registerTask('watch-less', ['recess:build', 'recess:installer', 'recess:nonodes', 'recess:canvasdesigner', 'postcss', 'copy:canvasdesigner', 'copy:assets', 'copy:vs']);
|
||||
grunt.registerTask('watch-html', ['copy:views', 'copy:vs']);
|
||||
grunt.registerTask('watch-installer', ['concat:install', 'concat:installJs', 'copy:installer', 'copy:vs']);
|
||||
grunt.registerTask('watch-canvasdesigner', ['copy:canvasdesigner', 'concat:canvasdesignerJs', 'copy:vs']);
|
||||
grunt.registerTask('watch-test', ['jshint:dev', 'karma:unit']);
|
||||
|
||||
//triggered from grunt
|
||||
grunt.registerTask('build', ['concat', 'recess:build', 'recess:installer', 'recess:nonodes', 'recess:canvasdesigner', 'postcss', 'bower-install-simple', 'bower', 'copy', 'clean:post']);
|
||||
|
||||
//triggered from grunt dev vs or grunt vs
|
||||
grunt.registerTask('build-dev', ['clean:pre', 'concat', 'recess:build', 'recess:installer', 'recess:nonodes', 'postcss', 'bower-install-simple', 'bower', 'copy']);
|
||||
|
||||
//utillity tasks
|
||||
grunt.registerTask('docs', ['ngdocs']);
|
||||
grunt.registerTask('webserver', ['connect:devserver']);
|
||||
|
||||
|
||||
// Print a timestamp (useful for when watching)
|
||||
grunt.registerTask('timestamp', function () {
|
||||
grunt.log.subhead(Date());
|
||||
});
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
buildVersion: grunt.option('buildversion') || '7',
|
||||
connect: {
|
||||
devserver: {
|
||||
options: {
|
||||
port: 9990,
|
||||
hostname: '0.0.0.0',
|
||||
base: './build',
|
||||
middleware: function(connect, options) {
|
||||
return [
|
||||
//uncomment to enable CSP
|
||||
// util.csp(),
|
||||
//util.rewrite(),
|
||||
connect.favicon('images/favicon.ico'),
|
||||
connect.static(options.base),
|
||||
connect.directory(options.base)
|
||||
];
|
||||
}
|
||||
}
|
||||
},
|
||||
testserver: {},
|
||||
docserver: {
|
||||
options: {
|
||||
port: 8880,
|
||||
hostname: '0.0.0.0',
|
||||
base: './docs/api',
|
||||
middleware: function(connect, options) {
|
||||
return [
|
||||
//uncomment to enable CSP
|
||||
// util.csp(),
|
||||
//util.rewrite(),
|
||||
connect.static(options.base),
|
||||
connect.directory(options.base)
|
||||
];
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
open: {
|
||||
dev: {
|
||||
path: 'http://localhost:9990/belle/'
|
||||
},
|
||||
docs: {
|
||||
path: 'http://localhost:8880/index.html'
|
||||
}
|
||||
},
|
||||
|
||||
distdir: 'build/belle',
|
||||
vsdir: '../Umbraco.Web.UI/umbraco',
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
banner:
|
||||
'/*! <%= pkg.title || pkg.name %>\n' +
|
||||
'<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
|
||||
' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
|
||||
' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
|
||||
src: {
|
||||
js: ['src/**/*.js', 'src/*.js'],
|
||||
|
||||
common: ['src/common/**/*.js'],
|
||||
controllers: ['src/**/*.controller.js'],
|
||||
|
||||
specs: ['test/**/*.spec.js'],
|
||||
scenarios: ['test/**/*.scenario.js'],
|
||||
samples: ['sample files/*.js'],
|
||||
html: ['src/index.html', 'src/install.html'],
|
||||
|
||||
everything: ['src/**/*.*', 'test/**/*.*', 'docs/**/*.*'],
|
||||
|
||||
tpl: {
|
||||
app: ['src/views/**/*.html'],
|
||||
common: ['src/common/**/*.tpl.html']
|
||||
},
|
||||
less: ['src/less/belle.less'], // recess:build doesn't accept ** in its file patterns
|
||||
prod: ['<%= distdir %>/js/*.js']
|
||||
},
|
||||
|
||||
clean: {
|
||||
pre: ['<%= distdir %>/*'],
|
||||
post: ['<%= distdir %>/js/*.dev.js']
|
||||
},
|
||||
|
||||
copy: {
|
||||
assets: {
|
||||
files: [{ dest: '<%= distdir %>/assets', src: '**', expand: true, cwd: 'src/assets/' }]
|
||||
},
|
||||
|
||||
config: {
|
||||
files: [{ dest: '<%= distdir %>/../config', src: '**', expand: true, cwd: 'src/config/' }]
|
||||
},
|
||||
|
||||
installer: {
|
||||
files: [{ dest: '<%= distdir %>/views/install', src: '**/*.html', expand: true, cwd: 'src/installer/steps' }]
|
||||
},
|
||||
|
||||
canvasdesigner: {
|
||||
files: [
|
||||
{ dest: '<%= distdir %>/preview', src: '**/*.html', expand: true, cwd: 'src/canvasdesigner' },
|
||||
{ dest: '<%= distdir %>/preview/editors', src: '**/*.html', expand: true, cwd: 'src/canvasdesigner/editors' },
|
||||
{ dest: '<%= distdir %>/assets/less', src: '**/*.less', expand: true, cwd: 'src/canvasdesigner/editors' },
|
||||
{ dest: '<%= distdir %>/js', src: 'canvasdesigner.config.js', expand: true, cwd: 'src/canvasdesigner/config' },
|
||||
{ dest: '<%= distdir %>/js', src: 'canvasdesigner.palettes.js', expand: true, cwd: 'src/canvasdesigner/config' },
|
||||
{ dest: '<%= distdir %>/js', src: 'canvasdesigner.front.js', expand: true, cwd: 'src/canvasdesigner' }
|
||||
]
|
||||
},
|
||||
|
||||
vendor: {
|
||||
files: [{ dest: '<%= distdir %>/lib', src: '**', expand: true, cwd: 'lib/' }]
|
||||
},
|
||||
|
||||
views: {
|
||||
files: [{ dest: '<%= distdir %>/views', src: ['**/*.*', '!**/*.controller.js'], expand: true, cwd: 'src/views' }]
|
||||
},
|
||||
|
||||
app: {
|
||||
files: [
|
||||
{ dest: '<%= distdir %>/js', src: '*.js', expand: true, cwd: 'src/' }
|
||||
]
|
||||
},
|
||||
|
||||
mocks: {
|
||||
files: [{ dest: '<%= distdir %>/js', src: '*.js', expand: true, cwd: 'src/common/mocks/' }]
|
||||
},
|
||||
|
||||
vs: {
|
||||
files: [
|
||||
//everything except the index.html root file!
|
||||
//then we need to figure out how to not copy all the test stuff either!?
|
||||
{ dest: '<%= vsdir %>/assets', src: '**', expand: true, cwd: '<%= distdir %>/assets' },
|
||||
{ dest: '<%= vsdir %>/js', src: '**', expand: true, cwd: '<%= distdir %>/js' },
|
||||
{ dest: '<%= vsdir %>/views', src: '**', expand: true, cwd: '<%= distdir %>/views' },
|
||||
{ dest: '<%= vsdir %>/preview', src: '**', expand: true, cwd: '<%= distdir %>/preview' },
|
||||
{ dest: '<%= vsdir %>/lib', src: '**', expand: true, cwd: '<%= distdir %>/lib' }
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
karma: {
|
||||
unit: { configFile: 'test/config/karma.conf.js', keepalive: true },
|
||||
e2e: { configFile: 'test/config/e2e.js', keepalive: true },
|
||||
watch: { configFile: 'test/config/unit.js', singleRun: false, autoWatch: true, keepalive: true }
|
||||
},
|
||||
|
||||
concat: {
|
||||
index: {
|
||||
src: ['src/index.html'],
|
||||
dest: '<%= distdir %>/index.html',
|
||||
options: {
|
||||
process: true
|
||||
}
|
||||
},
|
||||
install: {
|
||||
src: ['src/installer/installer.html'],
|
||||
dest: '<%= distdir %>/installer.html',
|
||||
options: {
|
||||
process: true
|
||||
}
|
||||
},
|
||||
|
||||
installJs: {
|
||||
src: ['src/installer/**/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.installer.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
canvasdesignerJs: {
|
||||
src: ['src/canvasdesigner/canvasdesigner.global.js', 'src/canvasdesigner/canvasdesigner.controller.js', 'src/canvasdesigner/editors/*.js', 'src/canvasdesigner/lib/*.js'],
|
||||
dest: '<%= distdir %>/js/canvasdesigner.panel.js'
|
||||
},
|
||||
|
||||
controllers: {
|
||||
src: ['src/controllers/**/*.controller.js', 'src/views/**/*.controller.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.controllers.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
services: {
|
||||
src: ['src/common/services/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.services.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
security: {
|
||||
src: ['src/common/security/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.security.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
resources: {
|
||||
src: ['src/common/resources/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.resources.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
testing: {
|
||||
src: ['src/common/mocks/*/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.testing.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
directives: {
|
||||
src: ['src/common/directives/**/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.directives.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
filters: {
|
||||
src: ['src/common/filters/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.filters.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
uglify: {
|
||||
options: {
|
||||
mangle: true
|
||||
},
|
||||
combine: {
|
||||
files: {
|
||||
'<%= distdir %>/js/umbraco.min.js': ['<%= distdir %>/js/umbraco.*.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
recess: {
|
||||
build: {
|
||||
files: {
|
||||
'<%= distdir %>/assets/css/<%= pkg.name %>.css':
|
||||
['<%= src.less %>']
|
||||
},
|
||||
options: {
|
||||
compile: true,
|
||||
compress: true
|
||||
}
|
||||
},
|
||||
nonodes: {
|
||||
files: {
|
||||
'<%= distdir %>/assets/css/nonodes.style.min.css':
|
||||
['src/less/pages/nonodes.less']
|
||||
},
|
||||
options: {
|
||||
compile: true,
|
||||
compress: true
|
||||
}
|
||||
},
|
||||
installer: {
|
||||
files: {
|
||||
'<%= distdir %>/assets/css/installer.css':
|
||||
['src/less/installer.less']
|
||||
},
|
||||
options: {
|
||||
compile: true,
|
||||
compress: true
|
||||
}
|
||||
},
|
||||
canvasdesigner: {
|
||||
files: {
|
||||
'<%= distdir %>/assets/css/canvasdesigner.css':
|
||||
['src/less/canvas-designer.less', 'src/less/helveticons.less']
|
||||
},
|
||||
options: {
|
||||
compile: true,
|
||||
compress: true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
postcss: {
|
||||
options: {
|
||||
processors: [
|
||||
// add vendor prefixes
|
||||
require('autoprefixer-core')({
|
||||
browsers: 'last 2 versions'
|
||||
})
|
||||
]
|
||||
},
|
||||
dist: {
|
||||
src: '<%= distdir %>/assets/css/<%= pkg.name %>.css'
|
||||
}
|
||||
},
|
||||
|
||||
ngTemplateCache: {
|
||||
views: {
|
||||
files: {
|
||||
'<%= distdir %>/js/umbraco.views.js': 'src/views/**/*.html'
|
||||
},
|
||||
options: {
|
||||
trim: 'src/',
|
||||
module: 'umbraco.views'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
docs: {
|
||||
files: ['docs/src/**/*.md'],
|
||||
tasks: ['watch-docs', 'timestamp']
|
||||
},
|
||||
css: {
|
||||
files: 'src/**/*.less',
|
||||
tasks: ['watch-less', 'timestamp'],
|
||||
options: {
|
||||
livereload: true,
|
||||
},
|
||||
},
|
||||
js: {
|
||||
files: ['src/**/*.js', 'src/*.js'],
|
||||
tasks: ['watch-js', 'timestamp'],
|
||||
},
|
||||
test: {
|
||||
files: ['test/**/*.js'],
|
||||
tasks: ['watch-test', 'timestamp'],
|
||||
},
|
||||
installer: {
|
||||
files: ['src/installer/**/*.*'],
|
||||
tasks: ['watch-installer', 'timestamp'],
|
||||
},
|
||||
canvasdesigner: {
|
||||
files: ['src/canvasdesigner/**/*.*'],
|
||||
tasks: ['watch-canvasdesigner', 'timestamp'],
|
||||
},
|
||||
html: {
|
||||
files: ['src/views/**/*.html', 'src/*.html'],
|
||||
tasks: ['watch-html', 'timestamp']
|
||||
},
|
||||
options: {
|
||||
interval: 500
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
ngdocs: {
|
||||
options: {
|
||||
dest: 'docs/api',
|
||||
startPage: '/api',
|
||||
title: "Umbraco Backoffice UI API Documentation",
|
||||
html5Mode: false,
|
||||
styles: [
|
||||
'docs/umb-docs.css'
|
||||
],
|
||||
image: "https://our.umbraco.org/assets/images/logo.svg"
|
||||
},
|
||||
api: {
|
||||
src: ['src/common/**/*.js', 'docs/src/api/**/*.ngdoc'],
|
||||
title: 'API Documentation'
|
||||
},
|
||||
tutorials: {
|
||||
src: [],
|
||||
title: ''
|
||||
}
|
||||
},
|
||||
|
||||
eslint:{
|
||||
src: ['<%= src.common %>','<%= src.controllers %>'],
|
||||
options: {quiet: true}
|
||||
},
|
||||
|
||||
jshint: {
|
||||
dev: {
|
||||
files: {
|
||||
src: ['<%= src.common %>']
|
||||
},
|
||||
options: {
|
||||
curly: true,
|
||||
eqeqeq: true,
|
||||
immed: true,
|
||||
latedef: "nofunc",
|
||||
newcap: true,
|
||||
noarg: true,
|
||||
sub: true,
|
||||
boss: true,
|
||||
//NOTE: This is required so it doesn't barf on reserved words like delete when doing $http.delete
|
||||
es5: true,
|
||||
eqnull: true,
|
||||
//NOTE: we need to use eval sometimes so ignore it
|
||||
evil: true,
|
||||
//NOTE: we need to check for strings such as "javascript:" so don't throw errors regarding those
|
||||
scripturl: true,
|
||||
//NOTE: we ignore tabs vs spaces because enforcing that causes lots of errors depending on the text editor being used
|
||||
smarttabs: true,
|
||||
globals: {}
|
||||
}
|
||||
},
|
||||
build: {
|
||||
files: {
|
||||
src: ['<%= src.prod %>']
|
||||
},
|
||||
options: {
|
||||
curly: true,
|
||||
eqeqeq: true,
|
||||
immed: true,
|
||||
latedef: "nofunc",
|
||||
newcap: true,
|
||||
noarg: true,
|
||||
sub: true,
|
||||
boss: true,
|
||||
//NOTE: This is required so it doesn't barf on reserved words like delete when doing $http.delete
|
||||
es5: true,
|
||||
eqnull: true,
|
||||
//NOTE: we need to use eval sometimes so ignore it
|
||||
evil: true,
|
||||
//NOTE: we need to check for strings such as "javascript:" so don't throw errors regarding those
|
||||
scripturl: true,
|
||||
//NOTE: we ignore tabs vs spaces because enforcing that causes lots of errors depending on the text editor being used
|
||||
smarttabs: true,
|
||||
globalstrict: true,
|
||||
globals: { $: false, jQuery: false, define: false, require: false, window: false }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
bower: {
|
||||
dev: {
|
||||
dest: '<%= distdir %>/lib',
|
||||
options: {
|
||||
expand: true,
|
||||
ignorePackages: ['bootstrap'],
|
||||
packageSpecific: {
|
||||
'moment': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['min/moment-with-locales.js']
|
||||
},
|
||||
'typeahead.js': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['dist/typeahead.bundle.min.js']
|
||||
},
|
||||
'underscore': {
|
||||
files: ['underscore-min.js', 'underscore-min.map']
|
||||
},
|
||||
'rgrove-lazyload': {
|
||||
files: ['lazyload.js']
|
||||
},
|
||||
'bootstrap-social': {
|
||||
files: ['bootstrap-social.css']
|
||||
},
|
||||
'font-awesome': {
|
||||
files: ['css/font-awesome.min.css', 'fonts/*']
|
||||
},
|
||||
"jquery": {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['dist/jquery.min.js', 'dist/jquery.min.map']
|
||||
},
|
||||
'jquery-ui': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['jquery-ui.min.js']
|
||||
},
|
||||
'jquery-migrate': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['jquery-migrate.min.js']
|
||||
},
|
||||
'tinymce': {
|
||||
files: ['plugins/**', 'themes/**', 'tinymce.min.js']
|
||||
},
|
||||
'angular-dynamic-locale': {
|
||||
files: ['tmhDynamicLocale.min.js', 'tmhDynamicLocale.min.js.map']
|
||||
},
|
||||
'ng-file-upload': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['ng-file-upload.min.js']
|
||||
},
|
||||
'angular-local-storage': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['dist/angular-local-storage.min.js']
|
||||
},
|
||||
'codemirror': {
|
||||
files: [
|
||||
'lib/codemirror.js',
|
||||
'lib/codemirror.css',
|
||||
|
||||
'mode/css/*',
|
||||
'mode/javascript/*',
|
||||
'mode/xml/*',
|
||||
'mode/htmlmixed/*',
|
||||
|
||||
'addon/search/*',
|
||||
'addon/edit/*',
|
||||
'addon/selection/*',
|
||||
'addon/dialog/*'
|
||||
]
|
||||
},
|
||||
'ace-builds': {
|
||||
files: [
|
||||
'src-min-noconflict/ace.js',
|
||||
|
||||
'src-min-noconflict/ext-language_tools.js',
|
||||
'src-min-noconflict/ext-searchbox.js',
|
||||
'src-min-noconflict/ext-settings_menu.js',
|
||||
|
||||
'src-min-noconflict/snippets/text.js',
|
||||
'src-min-noconflict/snippets/javascript.js',
|
||||
|
||||
'src-min-noconflict/theme-chrome.js',
|
||||
|
||||
'src-min-noconflict/mode-razor.js',
|
||||
'src-min-noconflict/mode-javascript.js',
|
||||
|
||||
'src-min-noconflict/worker-javascript.js',
|
||||
]
|
||||
},
|
||||
'clipboard': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['dist/clipboard.min.js']
|
||||
},
|
||||
'angular-moment': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['angular-moment.min.js']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
options: {
|
||||
expand: true
|
||||
}
|
||||
},
|
||||
|
||||
"bower-install-simple": {
|
||||
options: {
|
||||
color: true
|
||||
},
|
||||
"dev": {}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-recess');
|
||||
grunt.loadNpmTasks('grunt-postcss');
|
||||
|
||||
grunt.loadNpmTasks('grunt-karma');
|
||||
|
||||
grunt.loadNpmTasks('grunt-open');
|
||||
grunt.loadNpmTasks('grunt-contrib-connect');
|
||||
grunt.loadNpmTasks("grunt-bower-install-simple");
|
||||
grunt.loadNpmTasks('grunt-bower');
|
||||
grunt.loadNpmTasks('grunt-ngdocs');
|
||||
|
||||
grunt.loadNpmTasks('grunt-eslint');
|
||||
grunt.loadNpmTasks('grunt-hustler');
|
||||
};
|
||||
@@ -73,6 +73,7 @@ var sources = {
|
||||
js: {
|
||||
preview: { files: ["src/canvasdesigner/**/*.js"], out: "umbraco.canvasdesigner.js" },
|
||||
installer: { files: ["src/installer/**/*.js"], out: "umbraco.installer.js" },
|
||||
|
||||
controllers: { files: ["src/{views,controllers}/**/*.controller.js"], out: "umbraco.controllers.js" },
|
||||
directives: { files: ["src/common/directives/**/*.js"], out: "umbraco.directives.js" },
|
||||
filters: { files: ["src/common/filters/**/*.js"], out: "umbraco.filters.js" },
|
||||
@@ -84,7 +85,8 @@ var sources = {
|
||||
//selectors for copying all views into the build
|
||||
//processed in the views task
|
||||
views:{
|
||||
umbraco: {files: ["src/views/**/*.html"], folder: ""},
|
||||
umbraco: {files: ["src/views/**/*html"], folder: ""},
|
||||
preview: { files: ["src/canvasdesigner/**/*.html"], folder: "../preview"},
|
||||
installer: {files: ["src/installer/steps/*.html"], folder: "install"}
|
||||
},
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-concat": "^2.6.0",
|
||||
"gulp-connect": "5.0.0",
|
||||
"gulp-less": "^3.5.0",
|
||||
"gulp-less": "^3.1.0",
|
||||
"gulp-ngdocs": "^0.3.0",
|
||||
"gulp-open": "^2.1.0",
|
||||
"gulp-open": "^2.0.0",
|
||||
"gulp-postcss": "^6.2.0",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-sort": "^2.0.0",
|
||||
@@ -38,11 +38,11 @@
|
||||
"gulp-wrap-js": "^0.4.1",
|
||||
"jasmine-core": "2.5.2",
|
||||
"karma": "^1.7.0",
|
||||
"karma-jasmine": "^1.1.1",
|
||||
"karma-jasmine": "^1.1.0",
|
||||
"karma-phantomjs-launcher": "^1.0.4",
|
||||
"less": "^2.7.3",
|
||||
"lodash": "^4.17.5",
|
||||
"less": "^2.6.1",
|
||||
"lodash": "^4.16.3",
|
||||
"merge-stream": "^1.0.1",
|
||||
"run-sequence": "^2.2.1"
|
||||
"run-sequence": "^2.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
@inherits System.Web.Mvc.WebViewPage
|
||||
|
||||
<div ng-controller="Umbraco.canvasdesigner.background">
|
||||
|
||||
<div class="box-slider">
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
@inherits System.Web.Mvc.WebViewPage
|
||||
|
||||
<div ng-controller="Umbraco.canvasdesigner.border" class="bordereditor">
|
||||
|
||||
<div class="box-slider">
|
||||
@@ -17,4 +17,4 @@
|
||||
<div ui-slider min="0" max="40" step="1" ng-model="selectedBorder.size"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="box-slider">
|
||||
<div colorpicker ng-model="item.values.color"></div>
|
||||
</div>
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
@inherits System.Web.Mvc.WebViewPage
|
||||
|
||||
<div ng-controller="Umbraco.canvasdesigner.googlefontpicker">
|
||||
|
||||
<div class="box-slider">
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
@inherits System.Web.Mvc.WebViewPage
|
||||
|
||||
<div ng-controller="Umbraco.canvasdesigner.gridRow">
|
||||
|
||||
<div class="box-slider">
|
||||
<input type="checkbox" ng-model="item.values.fullsize" /><label>Full size</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
@inherits System.Web.Mvc.WebViewPage
|
||||
|
||||
<div ng-controller="Umbraco.canvasdesigner.layout">
|
||||
|
||||
<div class="box-slider">
|
||||
@@ -7,4 +7,4 @@
|
||||
<input type="radio" ng-model="item.values.layout" value="full"> Full
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
@inherits System.Web.Mvc.WebViewPage
|
||||
|
||||
<div ng-controller="Umbraco.canvasdesigner.margin">
|
||||
|
||||
<div class="box-slider">
|
||||
<div class="box-slider">
|
||||
<ul class="box-preview">
|
||||
<li ng-repeat="margin in marginList" class="border-{{margin}}" ng-class="{selected: selectedmargin.name == margin}" ng-click="setSelectedmargin(margin)"></li>
|
||||
</ul>
|
||||
@@ -11,4 +11,4 @@
|
||||
<div ui-slider min="0" max="400" step="1" ng-model="selectedmargin.value"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
@inherits System.Web.Mvc.WebViewPage
|
||||
|
||||
<div ng-controller="Umbraco.canvasdesigner.padding">
|
||||
|
||||
<div class="box-slider">
|
||||
@@ -11,4 +11,4 @@
|
||||
<div ui-slider min="0" max="400" step="1" ng-model="selectedpadding.value"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
@inherits System.Web.Mvc.WebViewPage
|
||||
|
||||
<div ng-controller="Umbraco.canvasdesigner.radius">
|
||||
|
||||
<div class="box-slider">
|
||||
<ul class="box-preview">
|
||||
|
||||
|
||||
<li ng-repeat="radius in radiusList" ng-class="{selected: selectedradius.name == radius}" ng-click="setSelectedradius(radius)">
|
||||
<span ng-show="radius == 'topleft' || radius == 'all'" class="radius-top-left"></span>
|
||||
<span ng-show="radius == 'topright' || radius == 'all'" class="radius-top-right"></span>
|
||||
@@ -18,4 +18,4 @@
|
||||
<div ui-slider min="0" max="40" step="1" ng-model="selectedradius.value"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
@inherits System.Web.Mvc.WebViewPage
|
||||
|
||||
<div ng-controller="Umbraco.canvasdesigner.shadow">
|
||||
|
||||
<div class="box-slider">
|
||||
<div ui-slider min="0" max="100" step="1" ng-model="item.values.shadow"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
@inherits System.Web.Mvc.WebViewPage
|
||||
|
||||
<div ng-controller="Umbraco.canvasdesigner.slider">
|
||||
|
||||
<div class="box-slider">
|
||||
<div ui-slider min="{{item.min}}" max="{{item.max}}" step="1" ng-model="item.values.slider"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
+32
-17
@@ -1,9 +1,4 @@
|
||||
@using System.Web.Mvc.Html
|
||||
@inherits System.Web.Mvc.WebViewPage<Umbraco.Web.Models.ContentEditing.BackOfficePreview>
|
||||
@{
|
||||
var disableDevicePreview = Model.DisableDevicePreview.ToString().ToLowerInvariant();
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Umbraco Canvas Designer</title>
|
||||
@@ -11,25 +6,27 @@
|
||||
<link href="../lib/spectrum/spectrum.css" type="text/css" rel="stylesheet" />
|
||||
<link href="../lib/jquery-ui/jquery-ui-1.10.4.custom.min.css" type="text/css" rel="stylesheet" />
|
||||
</head>
|
||||
<body id="canvasdesignerPanel" ng-mouseover="outlinePositionHide()" ng-class="{ leftOpen: (showStyleEditor || showPalettePicker) && !showDevicesPreview }" ng-controller="Umbraco.canvasdesignerController">
|
||||
<div class="wait" ng-show="!frameLoaded"></div>
|
||||
|
||||
@if (string.IsNullOrWhiteSpace(Model.PreviewExtendedHeaderView) == false)
|
||||
{
|
||||
@Html.Partial(Model.PreviewExtendedHeaderView)
|
||||
}
|
||||
<body id="canvasdesignerPanel" ng-mouseover="outlinePositionHide()" ng-class="{ leftOpen: (showStyleEditor || showPalettePicker) && !showDevicesPreview }" ng-controller="Umbraco.canvasdesignerController">
|
||||
|
||||
<div class="wait" ng-show="!frameLoaded"></div>
|
||||
|
||||
<div id="demo-iframe-wrapper" ng-show="frameLoaded" class="{{previewDevice.css}}">
|
||||
<iframe id="resultFrame" ng-src="{{pageUrl}}" frameborder="0" iframe-is-loaded></iframe>
|
||||
</div>
|
||||
<div class="canvasdesigner" ng-init="showDevicesPreview = true; showDevices = !@(disableDevicePreview); showPalettePicker = true" ng-mouseenter="positionSelectedHide()">
|
||||
|
||||
<div class="canvasdesigner" ng-init="showDevicesPreview = true; showPalettePicker = true" ng-mouseenter="positionSelectedHide()">
|
||||
|
||||
<div class="fix-left-menu selected">
|
||||
|
||||
<div class="avatar">
|
||||
<img ng-src="../assets/img/application/logo.png"
|
||||
ng-srcset="../assets/img/application/logo@2x.png 2x,
|
||||
<img
|
||||
ng-src="../assets/img/application/logo.png"
|
||||
ng-srcset="../assets/img/application/logo@2x.png 2x,
|
||||
../assets/img/application/logo@3x.png 3x" />
|
||||
</div>
|
||||
<ul class="sections" ng-class="{selected: showDevicesPreview && showDevices}">
|
||||
|
||||
<ul class="sections" ng-class="{selected: showDevicesPreview}">
|
||||
<li ng-repeat="device in devices" ng-class="{ current:previewDevice==device }" ng-click="updatePreviewDevice(device)">
|
||||
<a href="#"><i class="icon {{device.icon}}" title="{{device.title}}"></i><span></span></a>
|
||||
</li>
|
||||
@@ -42,8 +39,9 @@
|
||||
</li>
|
||||
<li ng-click="exitPreview()">
|
||||
<a href="#" title="Exit Preview"><i class="icon icon-wrong"></i><span> </span></a>
|
||||
</li>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="sections" ng-class="{selected: !showDevicesPreview}" ng-if="enableCanvasdesigner > 0">
|
||||
<li ng-click="openPreviewDevice()">
|
||||
<a href="#"><i class="icon {{previewDevice.icon}}"></i><span>Preview</span></a>
|
||||
@@ -55,11 +53,15 @@
|
||||
<a href="#"><i class="icon icon-paint-roller"></i><span>UI Designer</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="main-panel" ng-class="{selected: !showDevicesPreview && ( showPalettePicker || showStyleEditor )}">
|
||||
|
||||
<div class="header">
|
||||
<h3>Palette Style</h3>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<ul class="samples">
|
||||
<li ng-repeat="palette in canvasdesignerPalette">
|
||||
@@ -76,6 +78,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-success" ng-click="saveStyle()">Save Style</a>
|
||||
<a class="btn btn-success dropdown-toggle" ng-click="opendropdown = !opendropdown">
|
||||
@@ -87,8 +90,11 @@
|
||||
<li><a ng-click="makePreset();opendropdown = false">Make preset</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="main-panel" ng-class="{selected: !showDevicesPreview && showStyleEditor}">
|
||||
|
||||
<div ng-show="!currentSelected">
|
||||
<div class="header">
|
||||
<h3>Select</h3>
|
||||
@@ -106,6 +112,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-repeat="configItem in canvasdesignerModel.configs" ng-show="currentSelected && currentSelected.name.toLowerCase() == configItem.name.toLowerCase()
|
||||
&& currentSelected.schema.toLowerCase() == configItem.schema.toLowerCase()" on-finish-render-filters>
|
||||
<div class="header">
|
||||
@@ -127,6 +134,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-success" ng-click="saveStyle()">Save Style</a>
|
||||
<a class="btn btn-success dropdown-toggle" ng-click="opendropdown = !opendropdown">
|
||||
@@ -138,13 +146,20 @@
|
||||
<li><a ng-click="makePreset();opendropdown = false">Make preset</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="float-panel"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="speechbubble">
|
||||
<p>Styles saved and published</p>
|
||||
</div>
|
||||
|
||||
<script src="../lib/rgrove-lazyload/lazyload.js"></script>
|
||||
<script src="../js/canvasdesigner.loader.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+3
-1
@@ -255,9 +255,11 @@
|
||||
else {
|
||||
$scope.save().then(function (data) {
|
||||
previewWindow.location.href = redirect;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$scope.restore = function (content) {
|
||||
|
||||
-2
@@ -8,8 +8,6 @@
|
||||
var evts = [];
|
||||
var isInfoTab = false;
|
||||
scope.publishStatus = {};
|
||||
|
||||
scope.disableTemplates = Umbraco.Sys.ServerVariables.features.disabledFeatures.disableTemplates;
|
||||
|
||||
function onInit() {
|
||||
|
||||
|
||||
@@ -145,12 +145,6 @@ angular.module("umbraco.directives")
|
||||
}
|
||||
}
|
||||
}
|
||||
if (val === "true") {
|
||||
tinyMceConfig.customConfig[i] = true;
|
||||
}
|
||||
if (val === "false") {
|
||||
tinyMceConfig.customConfig[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
angular.extend(baseLineConfigObj, tinyMceConfig.customConfig);
|
||||
|
||||
+3
-5
@@ -59,6 +59,7 @@
|
||||
</pre>
|
||||
|
||||
<h1>General Options</h1>
|
||||
Lorem ipsum dolor sit amet..
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -73,7 +74,7 @@
|
||||
<td>Set the title of the overlay.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.subtitle</td>
|
||||
<td>model.subTitle</td>
|
||||
<td>String</td>
|
||||
<td>Set the subtitle of the overlay.</td>
|
||||
</tr>
|
||||
@@ -495,7 +496,6 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
var activeElementType = document.activeElement.tagName;
|
||||
var clickableElements = ["A", "BUTTON"];
|
||||
var submitOnEnter = document.activeElement.hasAttribute("overlay-submit-on-enter");
|
||||
var submitOnEnterValue = submitOnEnter ? document.activeElement.getAttribute("overlay-submit-on-enter") : "";
|
||||
|
||||
if(clickableElements.indexOf(activeElementType) === 0) {
|
||||
document.activeElement.click();
|
||||
@@ -503,9 +503,7 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
} else if(activeElementType === "TEXTAREA" && !submitOnEnter) {
|
||||
|
||||
|
||||
} else if (submitOnEnter && submitOnEnterValue === "false") {
|
||||
// don't do anything
|
||||
}else {
|
||||
} else {
|
||||
scope.$apply(function () {
|
||||
scope.submitForm(scope.model);
|
||||
});
|
||||
|
||||
+1
-1
@@ -125,7 +125,7 @@
|
||||
function link(scope, el, attr, ngModel) {
|
||||
|
||||
// Load in ace library
|
||||
assetsService.load(['lib/ace-builds/src-min-noconflict/ace.js', 'lib/ace-builds/src-min-noconflict/ext-language_tools.js'], scope).then(function () {
|
||||
assetsService.load(['lib/ace-builds/src-min-noconflict/ace.js', 'lib/ace-builds/src-min-noconflict/ext-language_tools.js']).then(function () {
|
||||
if (angular.isUndefined(window.ace)) {
|
||||
throw new Error('ui-ace need ace to work... (o rly?)');
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@
|
||||
var clipboard;
|
||||
var target = element[0];
|
||||
|
||||
assetsService.loadJs("lib/clipboard/clipboard.min.js", scope)
|
||||
assetsService.loadJs("lib/clipboard/clipboard.min.js")
|
||||
.then(function () {
|
||||
|
||||
if(scope.umbClipboardTarget) {
|
||||
|
||||
+2
-2
@@ -92,10 +92,10 @@ Use this directive to render a date time picker
|
||||
scope.hasTranscludedContent = element.find('.js-datePicker__transcluded-content')[0].children.length > 0;
|
||||
|
||||
// load css file for the date picker
|
||||
assetsService.loadCss('lib/datetimepicker/bootstrap-datetimepicker.min.css', scope);
|
||||
assetsService.loadCss('lib/datetimepicker/bootstrap-datetimepicker.min.css');
|
||||
|
||||
// load the js file for the date picker
|
||||
assetsService.loadJs('lib/datetimepicker/bootstrap-datetimepicker.js', scope).then(function () {
|
||||
assetsService.loadJs('lib/datetimepicker/bootstrap-datetimepicker.js').then(function () {
|
||||
// init date picker
|
||||
initDatePicker();
|
||||
});
|
||||
|
||||
@@ -129,12 +129,14 @@ angular.module('umbraco.services')
|
||||
asset.state = "loading";
|
||||
LazyLoad.css(appendRnd(path), function () {
|
||||
if (!scope) {
|
||||
scope = $rootScope;
|
||||
}
|
||||
asset.state = "loaded";
|
||||
angularHelper.safeApply(scope, function () {
|
||||
asset.state = "loaded";
|
||||
asset.deferred.resolve(true);
|
||||
});
|
||||
} else {
|
||||
asset.state = "loaded";
|
||||
angularHelper.safeApply(scope, function () {
|
||||
asset.deferred.resolve(true);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (asset.state === "loaded") {
|
||||
asset.deferred.resolve(true);
|
||||
@@ -169,12 +171,14 @@ angular.module('umbraco.services')
|
||||
|
||||
LazyLoad.js(appendRnd(path), function () {
|
||||
if (!scope) {
|
||||
scope = $rootScope;
|
||||
}
|
||||
asset.state = "loaded";
|
||||
angularHelper.safeApply(scope, function () {
|
||||
asset.state = "loaded";
|
||||
asset.deferred.resolve(true);
|
||||
});
|
||||
} else {
|
||||
asset.state = "loaded";
|
||||
angularHelper.safeApply(scope, function () {
|
||||
asset.deferred.resolve(true);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
} else if (asset.state === "loaded") {
|
||||
@@ -230,7 +234,8 @@ angular.module('umbraco.services')
|
||||
assets.push(asset);
|
||||
}
|
||||
|
||||
//we need to always push to the promises collection to monitor correct execution
|
||||
//we need to always push to the promises collection to monitor correct
|
||||
//execution
|
||||
promises.push(asset.deferred.promise);
|
||||
}
|
||||
});
|
||||
@@ -251,7 +256,8 @@ angular.module('umbraco.services')
|
||||
function assetLoaded(asset) {
|
||||
asset.state = "loaded";
|
||||
if (!scope) {
|
||||
scope = $rootScope;
|
||||
asset.deferred.resolve(true);
|
||||
return;
|
||||
}
|
||||
angularHelper.safeApply(scope,
|
||||
function () {
|
||||
@@ -274,4 +280,4 @@ angular.module('umbraco.services')
|
||||
};
|
||||
|
||||
return service;
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
function javascriptLibraryService($q, $http, umbRequestHelper) {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
umbRequestHelper.getApiUrl(
|
||||
"backOfficeAssetsApiBaseUrl",
|
||||
"GetSupportedMomentLocales")),
|
||||
"Failed to get cultures").then(function(locales) {
|
||||
'Failed to get cultures').then(function(locales) {
|
||||
existingLocales = locales;
|
||||
deferred.resolve(existingLocales);
|
||||
});
|
||||
@@ -30,8 +30,11 @@
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco.services").factory("javascriptLibraryService", javascriptLibraryService);
|
||||
angular.module('umbraco.services').factory('javascriptLibraryService', javascriptLibraryService);
|
||||
|
||||
|
||||
})();
|
||||
|
||||
|
||||
@@ -288,12 +288,9 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
throw "args.tree cannot be null";
|
||||
}
|
||||
|
||||
if (mainTreeEventHandler) {
|
||||
|
||||
if (mainTreeEventHandler.syncTree) {
|
||||
//returns a promise,
|
||||
return mainTreeEventHandler.syncTree(args);
|
||||
}
|
||||
if (mainTreeEventHandler) {
|
||||
//returns a promise
|
||||
return mainTreeEventHandler.syncTree(args);
|
||||
}
|
||||
|
||||
//couldn't sync
|
||||
|
||||
@@ -278,6 +278,8 @@ angular.module('umbraco.services')
|
||||
|
||||
/** Loads the Moment.js Locale for the current user. */
|
||||
loadMomentLocaleForCurrentUser: function () {
|
||||
var deferred = $q.defer();
|
||||
|
||||
|
||||
function loadLocales(currentUser, supportedLocales) {
|
||||
var locale = currentUser.locale.toLowerCase();
|
||||
@@ -292,14 +294,11 @@ angular.module('umbraco.services')
|
||||
localeUrls.push('lib/moment/' + majorLocale);
|
||||
}
|
||||
}
|
||||
return assetsService.load(localeUrls, $rootScope);
|
||||
}
|
||||
else {
|
||||
//return a noop promise
|
||||
var deferred = $q.defer();
|
||||
var promise = deferred.promise;
|
||||
deferred.resolve(true);
|
||||
return promise;
|
||||
assetsService.load(localeUrls).then(function () {
|
||||
deferred.resolve(localeUrls);
|
||||
});
|
||||
} else {
|
||||
deferred.resolve(['']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,11 +307,11 @@ angular.module('umbraco.services')
|
||||
supportedLocales: javascriptLibraryService.getSupportedLocalesForMoment()
|
||||
}
|
||||
|
||||
return $q.all(promises).then(function (values) {
|
||||
return loadLocales(values.currentUser, values.supportedLocales);
|
||||
$q.all(promises).then((values) => {
|
||||
loadLocales(values.currentUser, values.supportedLocales);
|
||||
});
|
||||
|
||||
|
||||
return deferred.promise;
|
||||
|
||||
},
|
||||
|
||||
|
||||
@@ -168,9 +168,6 @@
|
||||
//used for property editors
|
||||
@import "property-editors.less";
|
||||
|
||||
//used for prevalue editors
|
||||
@import "components/prevalues/multivalues.less";
|
||||
|
||||
|
||||
@import "typeahead.less";
|
||||
@import "hacks.less";
|
||||
@@ -178,4 +175,4 @@
|
||||
@import "healthcheck.less";
|
||||
|
||||
// cleanup properties.less when it is done
|
||||
@import "properties.less";
|
||||
@import "properties.less";
|
||||
@@ -1,53 +0,0 @@
|
||||
.umb-prevalues-multivalues {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__left {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__right {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__add {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__add input {
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__add input {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__add button {
|
||||
margin: 0 6px 0 0;
|
||||
float: right
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__listitem {
|
||||
display: flex;
|
||||
padding: 6px;
|
||||
margin: 10px 0px !important;
|
||||
background: #F3F3F5;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__listitem i {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 5px
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__listitem a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__listitem input {
|
||||
width: 295px;
|
||||
}
|
||||
@@ -280,6 +280,7 @@
|
||||
.umb-grid .umb-control {
|
||||
position: relative;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
@@ -40,16 +40,6 @@
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.umb-contentpicker__min-max-help {
|
||||
font-size: 13px;
|
||||
margin-top: 5px;
|
||||
color: @gray-4;
|
||||
}
|
||||
|
||||
.show-validation .umb-contentpicker__min-max-help {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.umb-contentpicker small {
|
||||
|
||||
&:not(:last-child) {
|
||||
@@ -119,22 +109,22 @@ ul.color-picker li a {
|
||||
}
|
||||
|
||||
/* pre-value editor */
|
||||
/*.control-group.color-picker-preval:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
/*.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;
|
||||
}*/
|
||||
|
||||
/*.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;
|
||||
}*/
|
||||
.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;
|
||||
@@ -146,18 +136,18 @@ ul.color-picker li a {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval btn {
|
||||
.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;
|
||||
.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;
|
||||
@@ -213,22 +203,10 @@ ul.color-picker li a {
|
||||
|
||||
|
||||
|
||||
.umb-thumbnails {
|
||||
position: relative;
|
||||
display: flex;
|
||||
-ms-flex-direction: row;
|
||||
-webkit-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-ms-flex-wrap: wrap;
|
||||
-webkit-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
.umb-thumbnails{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.umb-thumbnails > li.icon {
|
||||
width: 14%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.umb-thumbnails i{margin: auto;}
|
||||
.umb-thumbnails a{
|
||||
|
||||
@@ -100,27 +100,6 @@
|
||||
.color-green, .color-green i{color: @green-d1 !important;}
|
||||
.color-yellow, .color-yellow i{color: @yellow-d1 !important;}
|
||||
|
||||
/* Colors based on http://zavoloklom.github.io/material-design-color-palette/colors.html */
|
||||
.color-black, .color-black i { color: #000 !important; }
|
||||
.color-blue-grey, .color-blue-grey i { color: #607d8b !important; }
|
||||
.color-grey, .color-grey i { color: #9e9e9e !important; }
|
||||
.color-brown, .color-brown i { color: #795548 !important; }
|
||||
.color-blue, .color-blue i { color: #2196f3 !important; }
|
||||
.color-light-blue, .color-light-blue i {color: #03a9f4 !important; }
|
||||
.color-cyan, .color-cyan i { color: #00bcd4 !important; }
|
||||
.color-green, .color-green i { color: #4caf50 !important; }
|
||||
.color-light-green, .color-light-green i {color: #8bc34a !important; }
|
||||
.color-lime, .color-lime i { color: #cddc39 !important; }
|
||||
.color-yellow, .color-yellow i { color: #ffeb3b !important; }
|
||||
.color-amber, .color-amber i { color: #ffc107 !important; }
|
||||
.color-orange, .color-orange i { color: #ff9800 !important; }
|
||||
.color-deep-orange, .color-deep-orange i { color: #ff5722 !important; }
|
||||
.color-red, .color-red i { color: #f44336 !important; }
|
||||
.color-pink, .color-pink i { color: #e91e63 !important; }
|
||||
.color-purple,.color-purple i { color: #9c27b0 !important; }
|
||||
.color-deep-purple, .color-deep-purple i { color: #673ab7 !important; }
|
||||
.color-indigo, .color-indigo i { color: #3f51b5 !important; }
|
||||
|
||||
|
||||
// Scaffolding
|
||||
// -------------------------
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Dialogs.ApprovedColorPickerController", function ($scope, $http, umbPropEditorHelper, assetsService) {
|
||||
assetsService.loadJs("lib/cssparser/cssparser.js", $scope)
|
||||
assetsService.loadJs("lib/cssparser/cssparser.js")
|
||||
.then(function () {
|
||||
|
||||
var cssPath = $scope.dialogData.cssPath;
|
||||
@@ -19,7 +19,7 @@ angular.module("umbraco")
|
||||
$scope.classes.splice(0, 0, "noclass");
|
||||
})
|
||||
|
||||
assetsService.loadCss("/App_Plugins/Lecoati.uSky.Grid/lib/uSky.Grid.ApprovedColorPicker.css", $scope);
|
||||
assetsService.loadCss(cssPath, $scope);
|
||||
assetsService.loadCss("/App_Plugins/Lecoati.uSky.Grid/lib/uSky.Grid.ApprovedColorPicker.css");
|
||||
assetsService.loadCss(cssPath);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -7,13 +7,14 @@ angular.module("umbraco")
|
||||
$scope.icons = icons;
|
||||
});
|
||||
|
||||
$scope.submitClass = function(icon){
|
||||
$scope.submitClass = function (icon) {
|
||||
if($scope.color) {
|
||||
$scope.submit(icon + " " + $scope.color);
|
||||
}
|
||||
else {
|
||||
$scope.submit(icon);
|
||||
else {
|
||||
$scope.submit(icon);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
@@ -16,25 +16,24 @@
|
||||
|
||||
<div class="umb-control-group">
|
||||
<select ng-model="color" class="input-block-level">
|
||||
<option value=""><localize key="colors_black">Black</localize></option>
|
||||
<option value="color-blue-grey"><localize key="colors_bluegrey">Blue Grey</localize></option>
|
||||
<option value="color-grey"><localize key="colors_grey">Grey</localize></option>
|
||||
<option value="color-brown"><localize key="colors_brown">Brown</localize></option>
|
||||
<option value="color-blue"><localize key="colors_blue">Blue</localize></option>
|
||||
<option value="color-light-blue"><localize key="colors_lightblue">Light Blue</localize></option>
|
||||
<option value="color-cyan"><localize key="colors_cyan">Cyan</localize></option>
|
||||
<option value="color-green"><localize key="colors_green">Green</localize></option>
|
||||
<option value="color-light-green"><localize key="colors_lightgreen">Light Green</localize></option>
|
||||
<option value="color-yellow"><localize key="colors_yellow">Yellow</localize></option>
|
||||
<option value="color-lime"><localize key="colors_lime">Lime</localize></option>
|
||||
<option value="color-amber"><localize key="colors_amber">Amber</localize></option>
|
||||
<option value="color-orange"><localize key="colors_orange">Orange</localize></option>
|
||||
<option value="color-deep-orange"><localize key="colors_deeporange">Deep Orange</localize></option>
|
||||
<option value="color-red"><localize key="colors_red">Red</localize></option>
|
||||
<option value="color-pink"><localize key="colors_pink">Pink</localize></option>
|
||||
<option value="color-purple"><localize key="colors_purple">Purple</localize></option>
|
||||
<option value="color-deep-purple"><localize key="colors_deeppurple">Deep Purple</localize></option>
|
||||
<option value="color-indigo"><localize key="colors_indigo">Indigo</localize></option>
|
||||
<option value="">
|
||||
<localize key="colors_black">Black</localize>
|
||||
</option>
|
||||
<option value="color-green">
|
||||
<localize key="colors_green">Green</localize>
|
||||
</option>
|
||||
<option value="color-yellow">
|
||||
<localize key="colors_yellow">Yellow</localize>
|
||||
</option>
|
||||
<option value="color-orange">
|
||||
<localize key="colors_orange">Orange</localize>
|
||||
</option>
|
||||
<option value="color-blue">
|
||||
<localize key="colors_blue">Blue</localize>
|
||||
</option>
|
||||
<option value="color-red">
|
||||
<localize key="colors_red">Red</localize>
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -171,25 +171,27 @@
|
||||
{{publishStatus.label}}
|
||||
</umb-badge>
|
||||
</umb-control-group>
|
||||
|
||||
|
||||
<umb-control-group data-element="node-info-create-date" label="@template_createdDate">
|
||||
{{node.createDateFormatted}} <localize key="general_by">by</localize> {{ node.owner.name }}
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group data-element="node-info-document-type" label="@content_documentType">
|
||||
<umb-node-preview style="max-width: 100%; margin-bottom: 0;"
|
||||
icon="documentType.icon"
|
||||
name="documentType.name"
|
||||
allow-open="allowOpen"
|
||||
on-open="openDocumentType(documentType)">
|
||||
<umb-node-preview
|
||||
style="max-width: 100%; margin-bottom: 0;"
|
||||
icon="documentType.icon"
|
||||
name="documentType.name"
|
||||
allow-open="allowOpen"
|
||||
on-open="openDocumentType(documentType)">
|
||||
</umb-node-preview>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group ng-if="disableTemplates == false" data-element="node-info-template" label="@template_template">
|
||||
<select class="input-block-level"
|
||||
ng-model="node.template"
|
||||
ng-options="key as value for (key, value) in availableTemplates"
|
||||
ng-change="updateTemplate(node.template)">
|
||||
<umb-control-group data-element="node-info-template" label="@template_template">
|
||||
<select
|
||||
class="input-block-level"
|
||||
ng-model="node.template"
|
||||
ng-options="key as value for (key, value) in availableTemplates"
|
||||
ng-change="updateTemplate(node.template)">
|
||||
<option value=""><localize key="general_choose">Choose</localize>...</option>
|
||||
</select>
|
||||
</umb-control-group>
|
||||
@@ -198,7 +200,7 @@
|
||||
<div>{{ node.id }}</div>
|
||||
<small>{{ node.key }}</small>
|
||||
</umb-control-group>
|
||||
|
||||
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
</div>
|
||||
|
||||
@@ -47,17 +47,7 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="umb-table-cell" ng-repeat="column in itemProperties">
|
||||
<span title="{{column.header}}: {{item[column.alias]}}">
|
||||
|
||||
<div ng-if="!column.isSensitive">
|
||||
{{item[column.alias]}}
|
||||
</div>
|
||||
|
||||
<em ng-show="column.isSensitive" class="muted">
|
||||
<localize key="content_isSensitiveValue_short"></localize>
|
||||
</em>
|
||||
|
||||
</span>
|
||||
<span title="{{column.header}}: {{item[column.alias]}}">{{item[column.alias]}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@ function startUpVideosDashboardController($scope, xmlhelper, $log, $http) {
|
||||
angular.module("umbraco").controller("Umbraco.Dashboard.StartupVideosController", startUpVideosDashboardController);
|
||||
|
||||
|
||||
function startUpDynamicContentController($timeout, $scope, dashboardResource, assetsService, tourService, eventsService) {
|
||||
function startUpDynamicContentController($timeout, dashboardResource, assetsService, tourService, eventsService) {
|
||||
var vm = this;
|
||||
var evts = [];
|
||||
|
||||
@@ -95,7 +95,7 @@ function startUpDynamicContentController($timeout, $scope, dashboardResource, as
|
||||
}));
|
||||
|
||||
//proxy remote css through the local server
|
||||
assetsService.loadCss(dashboardResource.getRemoteDashboardCssUrl("content"), $scope);
|
||||
assetsService.loadCss( dashboardResource.getRemoteDashboardCssUrl("content") );
|
||||
dashboardResource.getRemoteDashboardContent("content").then(
|
||||
function (data) {
|
||||
|
||||
|
||||
@@ -14,21 +14,18 @@ function DocumentTypesCreateController($scope, $location, navigationService, con
|
||||
creatingFolder: false,
|
||||
};
|
||||
|
||||
var disableTemplates = Umbraco.Sys.ServerVariables.features.disabledFeatures.disableTemplates;
|
||||
$scope.model.disableTemplates = disableTemplates;
|
||||
|
||||
var node = $scope.dialogOptions.currentNode,
|
||||
localizeCreateFolder = localizationService.localize("defaultdialog_createFolder");
|
||||
|
||||
$scope.showCreateFolder = function () {
|
||||
$scope.showCreateFolder = function() {
|
||||
$scope.model.creatingFolder = true;
|
||||
};
|
||||
|
||||
$scope.createContainer = function () {
|
||||
$scope.createContainer = function() {
|
||||
|
||||
if (formHelper.submitForm({ scope: $scope, formCtrl: this.createFolderForm, statusMessage: localizeCreateFolder })) {
|
||||
if (formHelper.submitForm({scope: $scope, formCtrl: this.createFolderForm, statusMessage: localizeCreateFolder})) {
|
||||
|
||||
contentTypeResource.createContainer(node.id, $scope.model.folderName).then(function (folderId) {
|
||||
contentTypeResource.createContainer(node.id, $scope.model.folderName).then(function(folderId) {
|
||||
|
||||
navigationService.hideMenu();
|
||||
|
||||
@@ -47,7 +44,7 @@ function DocumentTypesCreateController($scope, $location, navigationService, con
|
||||
|
||||
var section = appState.getSectionState("currentSection");
|
||||
|
||||
}, function (err) {
|
||||
}, function(err) {
|
||||
|
||||
$scope.error = err;
|
||||
|
||||
@@ -61,17 +58,14 @@ function DocumentTypesCreateController($scope, $location, navigationService, con
|
||||
}
|
||||
};
|
||||
|
||||
// Disabling logic for creating document type with template if disableTemplates is set to true
|
||||
if (!disableTemplates) {
|
||||
$scope.createDocType = function () {
|
||||
$location.search('create', null);
|
||||
$location.search('notemplate', null);
|
||||
$location.path("/settings/documenttypes/edit/" + node.id).search("create", "true");
|
||||
navigationService.hideMenu();
|
||||
};
|
||||
}
|
||||
$scope.createDocType = function() {
|
||||
$location.search('create', null);
|
||||
$location.search('notemplate', null);
|
||||
$location.path("/settings/documenttypes/edit/" + node.id).search("create", "true");
|
||||
navigationService.hideMenu();
|
||||
};
|
||||
|
||||
$scope.createComponent = function () {
|
||||
$scope.createComponent = function() {
|
||||
$location.search('create', null);
|
||||
$location.search('notemplate', null);
|
||||
$location.path("/settings/documenttypes/edit/" + node.id).search("create", "true").search("notemplate", "true");
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<h5><localize key="create_createUnder">Create an item under</localize> {{currentNode.name}}</h5>
|
||||
|
||||
<ul class="umb-actions umb-actions-child">
|
||||
<li data-element="action-documentType" ng-hide="model.disableTemplates">
|
||||
<li data-element="action-documentType">
|
||||
<a href="" ng-click="createDocType()" umb-auto-focus>
|
||||
|
||||
<i class="large icon-item-arrangement"></i>
|
||||
@@ -15,14 +15,10 @@
|
||||
</a>
|
||||
</li>
|
||||
<li data-element="action-documentTypeWithoutTemplate">
|
||||
<a href="" ng-click="createComponent()">
|
||||
<i class="large icon-item-arrangement"></i>
|
||||
|
||||
<span class="menu-label">
|
||||
<localize ng-if="model.disableTemplates == false" key="create_documentTypeWithoutTemplate"></localize>
|
||||
<localize ng-if="model.disableTemplates == true" key="content_documentType">Document type></localize>
|
||||
</span>
|
||||
</a>
|
||||
<a href="" ng-click="createComponent()">
|
||||
<i class="large icon-item-arrangement"></i>
|
||||
<span class="menu-label"><localize key="create_documentTypeWithoutTemplate"></localize></span>
|
||||
</a>
|
||||
</li>
|
||||
<li data-element="action-folder" ng-if="model.allowCreateFolder">
|
||||
<a href="" ng-click="showCreateFolder()">
|
||||
@@ -37,7 +33,7 @@
|
||||
<form novalidate name="createFolderForm"
|
||||
ng-submit="createContainer()"
|
||||
val-form-manager>
|
||||
|
||||
|
||||
<div ng-show="error">
|
||||
<h5 class="text-error">{{error.errorMsg}}</h5>
|
||||
<p class="text-error">{{error.data.message}}</p>
|
||||
|
||||
@@ -15,36 +15,6 @@
|
||||
var localizeSaving = localizationService.localize("general_saving");
|
||||
var evts = [];
|
||||
|
||||
var disableTemplates = Umbraco.Sys.ServerVariables.features.disabledFeatures.disableTemplates;
|
||||
|
||||
var buttons = [
|
||||
{
|
||||
"name": localizationService.localize("general_design"),
|
||||
"alias": "design",
|
||||
"icon": "icon-document-dashed-line",
|
||||
"view": "views/documenttypes/views/design/design.html",
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("general_listView"),
|
||||
"alias": "listView",
|
||||
"icon": "icon-list",
|
||||
"view": "views/documenttypes/views/listview/listview.html"
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("general_rights"),
|
||||
"alias": "permissions",
|
||||
"icon": "icon-keychain",
|
||||
"view": "views/documenttypes/views/permissions/permissions.html"
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("treeHeaders_templates"),
|
||||
"alias": "templates",
|
||||
"icon": "icon-layout",
|
||||
"view": "views/documenttypes/views/templates/templates.html"
|
||||
}
|
||||
];
|
||||
|
||||
vm.save = save;
|
||||
|
||||
vm.currentNode = null;
|
||||
@@ -53,73 +23,97 @@
|
||||
vm.page = {};
|
||||
vm.page.loading = false;
|
||||
vm.page.saveButtonState = "init";
|
||||
vm.page.navigation = [];
|
||||
|
||||
loadButtons();
|
||||
vm.page.navigation = [
|
||||
{
|
||||
"name": localizationService.localize("general_design"),
|
||||
"alias": "design",
|
||||
"icon": "icon-document-dashed-line",
|
||||
"view": "views/documenttypes/views/design/design.html",
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("general_listView"),
|
||||
"alias": "listView",
|
||||
"icon": "icon-list",
|
||||
"view": "views/documenttypes/views/listview/listview.html"
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("general_rights"),
|
||||
"alias": "permissions",
|
||||
"icon": "icon-keychain",
|
||||
"view": "views/documenttypes/views/permissions/permissions.html"
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("treeHeaders_templates"),
|
||||
"alias": "templates",
|
||||
"icon": "icon-layout",
|
||||
"view": "views/documenttypes/views/templates/templates.html"
|
||||
}
|
||||
];
|
||||
|
||||
vm.page.keyboardShortcutsOverview = [
|
||||
{
|
||||
"name": localizationService.localize("main_sections"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_navigateSections"),
|
||||
"keys": [{ "key": "1" }, { "key": "4" }],
|
||||
"keyRange": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("general_design"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_addTab"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_addProperty"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "p" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_addEditor"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "e" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_editDataType"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("general_listView"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_toggleListView"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "l" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("general_rights"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_toggleAllowAsRoot"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "r" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_addChildNode"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "c" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("treeHeaders_templates"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_addTemplate"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }]
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": localizationService.localize("main_sections"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_navigateSections"),
|
||||
"keys": [{ "key": "1" }, { "key": "4" }],
|
||||
"keyRange": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("general_design"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_addTab"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_addProperty"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "p" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_addEditor"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "e" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_editDataType"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("general_listView"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_toggleListView"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "l" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("general_rights"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_toggleAllowAsRoot"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "r" }]
|
||||
},
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_addChildNode"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "c" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": localizationService.localize("treeHeaders_templates"),
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": localizationService.localize("shortcuts_addTemplate"),
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
contentTypeHelper.checkModelsBuilderStatus().then(function (result) {
|
||||
@@ -150,7 +144,7 @@
|
||||
vm.page.saveButtonState = "busy";
|
||||
|
||||
localizationService.localize("modelsBuilder_buildingModels").then(function (headerValue) {
|
||||
localizationService.localize("modelsBuilder_waitingMessage").then(function (msgValue) {
|
||||
localizationService.localize("modelsBuilder_waitingMessage").then(function(msgValue) {
|
||||
notificationsService.info(headerValue, msgValue);
|
||||
});
|
||||
});
|
||||
@@ -161,26 +155,26 @@
|
||||
if (!result.lastError) {
|
||||
|
||||
//re-check model status
|
||||
contentTypeHelper.checkModelsBuilderStatus().then(function (statusResult) {
|
||||
contentTypeHelper.checkModelsBuilderStatus().then(function(statusResult) {
|
||||
vm.page.modelsBuilder = statusResult;
|
||||
});
|
||||
|
||||
//clear and add success
|
||||
vm.page.saveButtonState = "init";
|
||||
localizationService.localize("modelsBuilder_modelsGenerated").then(function (value) {
|
||||
localizationService.localize("modelsBuilder_modelsGenerated").then(function(value) {
|
||||
notificationsService.success(value);
|
||||
});
|
||||
|
||||
} else {
|
||||
vm.page.saveButtonState = "error";
|
||||
localizationService.localize("modelsBuilder_modelsExceptionInUlog").then(function (value) {
|
||||
localizationService.localize("modelsBuilder_modelsExceptionInUlog").then(function(value) {
|
||||
notificationsService.error(value);
|
||||
});
|
||||
}
|
||||
|
||||
}, function () {
|
||||
vm.page.saveButtonState = "error";
|
||||
localizationService.localize("modelsBuilder_modelsGeneratedError").then(function (value) {
|
||||
localizationService.localize("modelsBuilder_modelsGeneratedError").then(function(value) {
|
||||
notificationsService.error(value);
|
||||
});
|
||||
});
|
||||
@@ -195,7 +189,7 @@
|
||||
|
||||
//we are creating so get an empty data type item
|
||||
contentTypeResource.getScaffold($routeParams.id)
|
||||
.then(function (dt) {
|
||||
.then(function(dt) {
|
||||
init(dt);
|
||||
vm.page.loading = false;
|
||||
});
|
||||
@@ -213,26 +207,12 @@
|
||||
});
|
||||
}
|
||||
|
||||
function loadButtons() {
|
||||
|
||||
angular.forEach(buttons,
|
||||
function (val, index) {
|
||||
|
||||
if (disableTemplates === true && val.alias === "templates") {
|
||||
buttons.splice(index, 1);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
vm.page.navigation = buttons;
|
||||
}
|
||||
|
||||
/* ---------- SAVE ---------- */
|
||||
|
||||
function save() {
|
||||
|
||||
// only save if there is no overlays open
|
||||
if (overlayHelper.getNumberOfOverlays() === 0) {
|
||||
if(overlayHelper.getNumberOfOverlays() === 0) {
|
||||
|
||||
var deferred = $q.defer();
|
||||
|
||||
@@ -253,7 +233,7 @@
|
||||
// we need to rebind... the IDs that have been created!
|
||||
rebindCallback: function (origContentType, savedContentType) {
|
||||
vm.contentType.id = savedContentType.id;
|
||||
vm.contentType.groups.forEach(function (group) {
|
||||
vm.contentType.groups.forEach(function(group) {
|
||||
if (!group.name) return;
|
||||
var k = 0;
|
||||
while (k < savedContentType.groups.length && savedContentType.groups[k].name != group.name)
|
||||
@@ -293,7 +273,7 @@
|
||||
}
|
||||
else {
|
||||
localizationService.localize("speechBubbles_validationFailedHeader").then(function (headerValue) {
|
||||
localizationService.localize("speechBubbles_validationFailedMessage").then(function (msgValue) {
|
||||
localizationService.localize("speechBubbles_validationFailedMessage").then(function(msgValue) {
|
||||
notificationsService.error(headerValue, msgValue);
|
||||
});
|
||||
});
|
||||
@@ -351,7 +331,7 @@
|
||||
function getDataTypeDetails(property) {
|
||||
if (property.propertyState !== "init") {
|
||||
dataTypeResource.getById(property.dataTypeId)
|
||||
.then(function (dataType) {
|
||||
.then(function(dataType) {
|
||||
property.dataTypeIcon = dataType.icon;
|
||||
property.dataTypeName = dataType.name;
|
||||
});
|
||||
@@ -365,7 +345,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
evts.push(eventsService.on("app.refreshEditor", function (name, error) {
|
||||
evts.push(eventsService.on("app.refreshEditor", function(name, error) {
|
||||
loadDocumentType();
|
||||
}));
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@
|
||||
|
||||
function init() {
|
||||
//we need to load this somewhere, for now its here.
|
||||
assetsService.loadCss("lib/ace-razor-mode/theme/razor_chrome.css", $scope);
|
||||
assetsService.loadCss("lib/ace-razor-mode/theme/razor_chrome.css");
|
||||
|
||||
if ($routeParams.create) {
|
||||
|
||||
@@ -355,4 +355,4 @@
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.PartialViewMacros.EditController", partialViewMacrosEditController);
|
||||
})();
|
||||
})();
|
||||
@@ -242,7 +242,7 @@
|
||||
|
||||
function init() {
|
||||
//we need to load this somewhere, for now its here.
|
||||
assetsService.loadCss("lib/ace-razor-mode/theme/razor_chrome.css", $scope);
|
||||
assetsService.loadCss("lib/ace-razor-mode/theme/razor_chrome.css");
|
||||
|
||||
if ($routeParams.create) {
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
angular.module("umbraco").controller("Umbraco.PrevalueEditors.BooleanController",
|
||||
function ($scope) {
|
||||
$scope.htmlId = "bool-" + String.CreateGuid();
|
||||
});
|
||||
@@ -1,4 +1 @@
|
||||
<label ng-controller="Umbraco.PrevalueEditors.BooleanController" for="{{htmlId}}" class="checkbox">
|
||||
<input name="boolean" type="checkbox" ng-model="model.value" ng-true-value="1" ng-false-value="0" id="{{htmlId}}" />
|
||||
<localize key="general_yes">Yes</localize>
|
||||
</label>
|
||||
<input name="boolean" type="checkbox" ng-model="model.value" ng-true-value="1" ng-false-value="0" />
|
||||
@@ -5,7 +5,6 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.MultiValuesControl
|
||||
|
||||
$scope.newItem = "";
|
||||
$scope.hasError = false;
|
||||
$scope.focusOnNew = false;
|
||||
|
||||
if (!angular.isArray($scope.model.value)) {
|
||||
|
||||
@@ -44,7 +43,6 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.MultiValuesControl
|
||||
$scope.model.value.push({ value: $scope.newItem });
|
||||
$scope.newItem = "";
|
||||
$scope.hasError = false;
|
||||
$scope.focusOnNew = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -75,12 +73,6 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.MultiValuesControl
|
||||
}
|
||||
};
|
||||
|
||||
$scope.createNew = function (event) {
|
||||
if (event.keyCode == 13) {
|
||||
$scope.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
function getElementIndexByPrevalueText(value) {
|
||||
for (var i = 0; i < $scope.model.value.length; i++) {
|
||||
if ($scope.model.value[i].value === value) {
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
<div class="umb-editor umb-prevalues-multivalues" ng-controller="Umbraco.PrevalueEditors.MultiValuesController">
|
||||
<div class="control-group umb-prevalues-multivalues__add">
|
||||
<div class="umb-prevalues-multivalues__left">
|
||||
<input overlay-submit-on-enter="false" name="newItem" focus-when="{{focusOnNew}}" ng-keydown="createNew($event)" type="text" ng-model="newItem" val-highlight="{{hasError}}" />
|
||||
</div>
|
||||
<div class="umb-prevalues-multivalues__right">
|
||||
<button class="btn btn-info" ng-click="add($event)">Add</button>
|
||||
</div>
|
||||
<div class="umb-editor" ng-controller="Umbraco.PrevalueEditors.MultiValuesController">
|
||||
<div class="control-group">
|
||||
<input name="newItem" type="text" ng-model="newItem" val-highlight="{{hasError}}" />
|
||||
<button class="btn" ng-click="add($event)">Add</button>
|
||||
</div>
|
||||
<div ui-sortable="sortableOptions">
|
||||
<div class="control-group umb-prevalues-multivalues__listitem" ng-repeat="item in model.value">
|
||||
<div class="control-group" ng-repeat="item in model.value">
|
||||
<i class="icon icon-navigation handle"></i>
|
||||
<div class="umb-prevalues-multivalues__left">
|
||||
<input type="text" ng-model="item.value" val-server="item_{{$index}}" required />
|
||||
</div>
|
||||
<div class="umb-prevalues-multivalues__right">
|
||||
<a class="umb-node-preview__action" ng-click="remove(item, $event)">Remove</a>
|
||||
</div>
|
||||
<input type="text" ng-model="item.value" val-server="item_{{$index}}" required />
|
||||
<button class="btn btn-danger" ng-click="remove(item, $event)">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -105,5 +105,5 @@
|
||||
};
|
||||
|
||||
//load the separate css for the editor to avoid it blocking our js loading
|
||||
assetsService.loadCss("lib/spectrum/spectrum.css", $scope);
|
||||
assetsService.loadCss("lib/spectrum/spectrum.css");
|
||||
});
|
||||
|
||||
-2
@@ -66,8 +66,6 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
showOpenButton: false,
|
||||
showEditButton: false,
|
||||
showPathOnHover: false,
|
||||
maxNumber: 1,
|
||||
minNumber : 0,
|
||||
startNode: {
|
||||
query: "",
|
||||
type: "content",
|
||||
|
||||
+1
-34
@@ -20,7 +20,7 @@
|
||||
</umb-node-preview>
|
||||
</div>
|
||||
|
||||
<a ng-show="model.config.multiPicker === true && renderModel.length < model.config.maxNumber || renderModel.length === 0 || !model.config.maxNumber"
|
||||
<a ng-show="model.config.multiPicker === true || renderModel.length === 0"
|
||||
class="umb-node-preview-add"
|
||||
href=""
|
||||
ng-click="openContentPicker()"
|
||||
@@ -28,39 +28,6 @@
|
||||
<localize key="general_add">Add</localize>
|
||||
</a>
|
||||
|
||||
<div class="umb-contentpicker__min-max-help" ng-if="model.config.multiPicker === true">
|
||||
|
||||
<!-- Both min and max items -->
|
||||
<span ng-if="model.config.minNumber && model.config.maxNumber && model.config.minNumber !== model.config.maxNumber">
|
||||
<span ng-if="renderModel.length < model.config.maxNumber">Add between {{model.config.minNumber}} and {{model.config.maxNumber}} items</span>
|
||||
<span ng-if="renderModel.length > model.config.maxNumber">
|
||||
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected"> items selected</localize>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- Equal min and max -->
|
||||
<span ng-if="model.config.minNumber && model.config.maxNumber && model.config.minNumber === model.config.maxNumber">
|
||||
<span ng-if="renderModel.length < model.config.maxNumber">Add {{model.config.minNumber - renderModel.length}} item(s)</span>
|
||||
<span ng-if="renderModel.length > model.config.maxNumber">
|
||||
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected"> items selected</localize>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- Only max -->
|
||||
<span ng-if="!model.config.minNumber && model.config.maxNumber">
|
||||
<span ng-if="renderModel.length < model.config.maxNumber">Add up to {{model.config.maxNumber}} items</span>
|
||||
<span ng-if="renderModel.length > model.config.maxNumber">
|
||||
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected">items selected</localize>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- Only min -->
|
||||
<span ng-if="model.config.minNumber && !model.config.maxNumber && renderModel.length < model.config.minNumber">
|
||||
Add at least {{model.config.minNumber}} item(s)
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<!--These are here because we need ng-form fields to validate against-->
|
||||
<input type="hidden" name="minCount" ng-model="renderModel" />
|
||||
<input type="hidden" name="maxCount" ng-model="renderModel" />
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ function dateTimePickerController($scope, notificationsService, assetsService, a
|
||||
//get the current user to see if we can localize this picker
|
||||
userService.getCurrentUser().then(function (user) {
|
||||
|
||||
assetsService.loadCss('lib/datetimepicker/bootstrap-datetimepicker.min.css', $scope).then(function() {
|
||||
assetsService.loadCss('lib/datetimepicker/bootstrap-datetimepicker.min.css').then(function() {
|
||||
|
||||
var filesToLoad = ["lib/datetimepicker/bootstrap-datetimepicker.js"];
|
||||
|
||||
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleController",
|
||||
function($scope) {
|
||||
|
||||
//setup the default config
|
||||
var config = {
|
||||
items: [],
|
||||
multiple: false
|
||||
};
|
||||
|
||||
//map the user config
|
||||
angular.extend(config, $scope.model.config);
|
||||
|
||||
//map back to the model
|
||||
$scope.model.config = config;
|
||||
|
||||
function convertArrayToDictionaryArray(model){
|
||||
//now we need to format the items in the dictionary because we always want to have an array
|
||||
var newItems = [];
|
||||
for (var i = 0; i < model.length; i++) {
|
||||
newItems.push({ id: model[i], sortOrder: 0, value: model[i] });
|
||||
}
|
||||
|
||||
return newItems;
|
||||
}
|
||||
|
||||
|
||||
function convertObjectToDictionaryArray(model){
|
||||
//now we need to format the items in the dictionary because we always want to have an array
|
||||
var newItems = [];
|
||||
var vals = _.values($scope.model.config.items);
|
||||
var keys = _.keys($scope.model.config.items);
|
||||
|
||||
for (var i = 0; i < vals.length; i++) {
|
||||
var label = vals[i].value ? vals[i].value : vals[i];
|
||||
newItems.push({ id: keys[i], sortOrder: vals[i].sortOrder, value: label });
|
||||
}
|
||||
|
||||
return newItems;
|
||||
}
|
||||
|
||||
$scope.updateSingleDropdownValue = function() {
|
||||
$scope.model.value = [$scope.model.singleDropdownValue];
|
||||
}
|
||||
|
||||
if (angular.isArray($scope.model.config.items)) {
|
||||
//PP: I dont think this will happen, but we have tests that expect it to happen..
|
||||
//if array is simple values, convert to array of objects
|
||||
if(!angular.isObject($scope.model.config.items[0])){
|
||||
$scope.model.config.items = convertArrayToDictionaryArray($scope.model.config.items);
|
||||
}
|
||||
}
|
||||
else if (angular.isObject($scope.model.config.items)) {
|
||||
$scope.model.config.items = convertObjectToDictionaryArray($scope.model.config.items);
|
||||
}
|
||||
else {
|
||||
throw "The items property must be either an array or a dictionary";
|
||||
}
|
||||
|
||||
|
||||
//sort the values
|
||||
$scope.model.config.items.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); });
|
||||
|
||||
//now we need to check if the value is null/undefined, if it is we need to set it to "" so that any value that is set
|
||||
// to "" gets selected by default
|
||||
if ($scope.model.value === null || $scope.model.value === undefined) {
|
||||
if ($scope.model.config.multiple) {
|
||||
$scope.model.value = [];
|
||||
}
|
||||
else {
|
||||
$scope.model.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
// if we run in single mode we'll store the value in a local variable
|
||||
// so we can pass an array as the model as our PropertyValueEditor expects that
|
||||
$scope.model.singleDropdownValue = "";
|
||||
if ($scope.model.config.multiple === "0") {
|
||||
$scope.model.singleDropdownValue = Array.isArray($scope.model.value) ? $scope.model.value[0] : $scope.model.value;
|
||||
}
|
||||
|
||||
});
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
<div ng-controller="Umbraco.PropertyEditors.DropdownFlexibleController" ng-switch="model.config.multiple">
|
||||
|
||||
<select name="dropDownList"
|
||||
class="umb-editor umb-dropdown"
|
||||
ng-switch-default
|
||||
ng-change="updateSingleDropdownValue()"
|
||||
ng-model="model.singleDropdownValue"
|
||||
ng-options="item.id as item.value for item in model.config.items">
|
||||
<option></option>
|
||||
</select>
|
||||
|
||||
<!--NOTE: This ng-switch is required because ng-multiple doesn't actually support dynamic bindings with multi-select lists -->
|
||||
<select name="dropDownList"
|
||||
class="umb-editor umb-dropdown"
|
||||
ng-switch-when="1"
|
||||
multiple
|
||||
ng-model="model.value"
|
||||
ng-options="item.id as item.value for item in model.config.items"></select>
|
||||
</div>
|
||||
+2
-2
@@ -2,7 +2,7 @@ angular.module("umbraco")
|
||||
.controller("Umbraco.PropertyEditors.GoogleMapsController",
|
||||
function ($element, $rootScope, $scope, notificationsService, dialogService, assetsService, $log, $timeout) {
|
||||
|
||||
assetsService.loadJs('https://www.google.com/jsapi', $scope)
|
||||
assetsService.loadJs('https://www.google.com/jsapi')
|
||||
.then(function () {
|
||||
google.load("maps", "3",
|
||||
{
|
||||
@@ -94,4 +94,4 @@ angular.module("umbraco")
|
||||
//update the display val again if it has changed from the server
|
||||
initMap();
|
||||
};
|
||||
});
|
||||
});
|
||||
+2
-22
@@ -30,14 +30,15 @@
|
||||
vm.dragLeave = dragLeave;
|
||||
vm.onFilesQueue = onFilesQueue;
|
||||
vm.onUploadComplete = onUploadComplete;
|
||||
markAsSensitive();
|
||||
|
||||
function activate() {
|
||||
|
||||
if ($scope.entityType === 'media') {
|
||||
mediaTypeHelper.getAllowedImagetypes(vm.nodeId).then(function (types) {
|
||||
vm.acceptedMediatypes = types;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function selectAll($event) {
|
||||
@@ -86,27 +87,6 @@
|
||||
$scope.getContent($scope.contentId);
|
||||
}
|
||||
|
||||
function markAsSensitive() {
|
||||
angular.forEach($scope.options.includeProperties, function (option) {
|
||||
option.isSensitive = false;
|
||||
|
||||
angular.forEach($scope.items,
|
||||
function (item) {
|
||||
|
||||
angular.forEach(item.properties,
|
||||
function (property) {
|
||||
|
||||
if (option.alias === property.alias) {
|
||||
option.isSensitive = property.isSensitive;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
activate();
|
||||
|
||||
}
|
||||
|
||||
+2
-8
@@ -46,7 +46,6 @@ function MarkdownEditorController($scope, $element, assetsService, dialogService
|
||||
// init the md editor after this digest because the DOM needs to be ready first
|
||||
// so run the init on a timeout
|
||||
$timeout(function () {
|
||||
$scope.markdownEditorInitComplete = false;
|
||||
var converter2 = new Markdown.Converter();
|
||||
var editor2 = new Markdown.Editor(converter2, "-" + $scope.model.alias);
|
||||
editor2.run();
|
||||
@@ -60,12 +59,7 @@ function MarkdownEditorController($scope, $element, assetsService, dialogService
|
||||
editor2.hooks.set("onPreviewRefresh", function () {
|
||||
// We must manually update the model as there is no way to hook into the markdown editor events without exstensive edits to the library.
|
||||
if ($scope.model.value !== $("textarea", $element).val()) {
|
||||
if ($scope.markdownEditorInitComplete) {
|
||||
//only set dirty after init load to avoid "unsaved" dialogue when we don't want it
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
} else {
|
||||
$scope.markdownEditorInitComplete = true;
|
||||
}
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
$scope.model.value = $("textarea", $element).val();
|
||||
}
|
||||
});
|
||||
@@ -74,7 +68,7 @@ function MarkdownEditorController($scope, $element, assetsService, dialogService
|
||||
});
|
||||
|
||||
//load the seperat css for the editor to avoid it blocking our js loading TEMP HACK
|
||||
assetsService.loadCss("lib/markdown/markdown.css", $scope);
|
||||
assetsService.loadCss("lib/markdown/markdown.css");
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -185,12 +185,6 @@ angular.module("umbraco")
|
||||
//cannot parse, we'll just leave it
|
||||
}
|
||||
}
|
||||
if (val === "true") {
|
||||
tinyMceConfig.customConfig[i] = true;
|
||||
}
|
||||
if (val === "false") {
|
||||
tinyMceConfig.customConfig[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,8 +359,7 @@ angular.module("umbraco")
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server;
|
||||
//uses an empty string in the editor when the value is null
|
||||
tinyMceEditor.setContent(newVal || "", { format: 'raw' });
|
||||
tinyMceEditor.setContent(newVal, { format: 'raw' });
|
||||
//we need to manually fire this event since it is only ever fired based on loading from the DOM, this
|
||||
// is required for our plugins listening to this event to execute
|
||||
tinyMceEditor.fire('LoadContent', null);
|
||||
|
||||
@@ -117,5 +117,5 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.RteController",
|
||||
});
|
||||
|
||||
// load TinyMCE skin which contains css for font-icons
|
||||
assetsService.loadCss("lib/tinymce/skins/umbraco/skin.min.css", $scope);
|
||||
});
|
||||
assetsService.loadCss("lib/tinymce/skins/umbraco/skin.min.css");
|
||||
});
|
||||
@@ -92,6 +92,7 @@
|
||||
$scope.model.config.ticksPositions = _.map($scope.model.config.ticksPositions.split(','), function (item) {
|
||||
return parseInt(item.trim());
|
||||
});
|
||||
console.log($scope.model.config.ticksPositions);
|
||||
}
|
||||
|
||||
if (!$scope.model.config.ticksLabels) {
|
||||
@@ -211,7 +212,7 @@
|
||||
});
|
||||
|
||||
//load the separate css for the editor to avoid it blocking our js loading
|
||||
assetsService.loadCss("lib/slider/bootstrap-slider.css", $scope);
|
||||
assetsService.loadCss("lib/slider/bootstrap-slider-custom.css", $scope);
|
||||
assetsService.loadCss("lib/slider/bootstrap-slider.css");
|
||||
assetsService.loadCss("lib/slider/bootstrap-slider-custom.css");
|
||||
}
|
||||
angular.module("umbraco").controller("Umbraco.PropertyEditors.SliderController", sliderController);
|
||||
angular.module("umbraco").controller("Umbraco.PropertyEditors.SliderController", sliderController);
|
||||
@@ -7,7 +7,7 @@ angular.module("umbraco")
|
||||
$scope.isLoading = true;
|
||||
$scope.tagToAdd = "";
|
||||
|
||||
assetsService.loadJs("lib/typeahead.js/typeahead.bundle.min.js", $scope).then(function () {
|
||||
assetsService.loadJs("lib/typeahead.js/typeahead.bundle.min.js").then(function () {
|
||||
|
||||
$scope.isLoading = false;
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
function init() {
|
||||
|
||||
//we need to load this somewhere, for now its here.
|
||||
assetsService.loadCss("lib/ace-razor-mode/theme/razor_chrome.css", $scope);
|
||||
assetsService.loadCss("lib/ace-razor-mode/theme/razor_chrome.css");
|
||||
|
||||
if ($routeParams.create) {
|
||||
codefileResource.getScaffold("scripts", $routeParams.id).then(function (script) {
|
||||
@@ -199,4 +199,4 @@
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Scripts.EditController", ScriptsEditController);
|
||||
})();
|
||||
})();
|
||||
@@ -105,7 +105,7 @@
|
||||
vm.init = function () {
|
||||
|
||||
//we need to load this somewhere, for now its here.
|
||||
assetsService.loadCss("lib/ace-razor-mode/theme/razor_chrome.css", $scope);
|
||||
assetsService.loadCss("lib/ace-razor-mode/theme/razor_chrome.css");
|
||||
|
||||
//load templates - used in the master template picker
|
||||
templateResource.getAll()
|
||||
|
||||
@@ -837,19 +837,6 @@
|
||||
<Content Include="Views\Partials\Grid\Editors\Base.cshtml" />
|
||||
<Content Include="Views\Partials\Grid\Bootstrap3-Fluid.cshtml" />
|
||||
<Content Include="Views\Partials\Grid\Bootstrap2-Fluid.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\Background.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\Border.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\Color.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\Googlefontpicker.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\GridRow.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\Index.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\Layout.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\Margin.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\Padding.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\Radius.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\Shadow.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\Slider.cshtml" />
|
||||
<Content Include="Umbraco\Views\Preview\web.config" />
|
||||
<None Include="Web.Debug.config.transformed" />
|
||||
<None Include="web.Template.Debug.config">
|
||||
<DependentUpon>Web.Template.config</DependentUpon>
|
||||
@@ -1007,6 +994,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="App_Data\" />
|
||||
<Folder Include="Umbraco\preview\" />
|
||||
<Folder Include="Views\MacroPartials\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -1035,9 +1023,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7103</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7920</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7103</IISUrl>
|
||||
<IISUrl>http://localhost:7920</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
@inherits System.Web.Mvc.WebViewPage
|
||||
<div class="box-slider">
|
||||
<div colorpicker ng-model="item.values.color"></div>
|
||||
</div>
|
||||
@@ -1,41 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
|
||||
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
|
||||
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
<system.web.webPages.razor>
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
|
||||
<pages pageBaseType="System.Web.Mvc.WebViewPage">
|
||||
<namespaces>
|
||||
<add namespace="System.Web.Mvc" />
|
||||
<add namespace="System.Web.Mvc.Ajax" />
|
||||
<add namespace="System.Web.Mvc.Html" />
|
||||
<add namespace="System.Web.Routing" />
|
||||
</namespaces>
|
||||
</pages>
|
||||
</system.web.webPages.razor>
|
||||
|
||||
<appSettings>
|
||||
<add key="webpages:Enabled" value="false" />
|
||||
</appSettings>
|
||||
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<remove name="BlockViewHandler"/>
|
||||
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
|
||||
</handlers>
|
||||
</system.webServer>
|
||||
|
||||
<system.web>
|
||||
<compilation>
|
||||
<assemblies>
|
||||
<add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
|
||||
</assemblies>
|
||||
</compilation>
|
||||
</system.web>
|
||||
</configuration>
|
||||
@@ -19,7 +19,6 @@
|
||||
<header>Macro</header>
|
||||
<usercontrol>/create/xslt.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="XsltTasks" />
|
||||
<delete assembly="umbraco" type="XsltTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
<header>Macro</header>
|
||||
<usercontrol>/create/xslt.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="XsltTasks" />
|
||||
<delete assembly="umbraco" type="XsltTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
|
||||
@@ -661,7 +661,7 @@
|
||||
<area alias="graphicheadline">
|
||||
<key alias="backgroundcolor">Baggrundsfarve</key>
|
||||
<key alias="bold">Fed</key>
|
||||
<key alias="color">Tekstfarve</key>
|
||||
<key alias="color">Tekst farve</key>
|
||||
<key alias="font">Skrifttype</key>
|
||||
<key alias="text">Tekst</key>
|
||||
</area>
|
||||
@@ -1259,9 +1259,9 @@ Mange hilsner fra Umbraco robotten
|
||||
|
||||
|
||||
<key alias="styles">Typografi</key>
|
||||
<key alias="stylesDetails">Vælg hvilke typografiværdier en redaktør kan ændre</key>
|
||||
<key alias="stylesDetails">Vælg, hvilke typografiværdier, en redaktør kan ændre</key>
|
||||
|
||||
<key alias="settingDialogDetails">Indstillinger gemmes kun, hvis den indtastede json-konfiguration er gyldig</key>
|
||||
<key alias="settingDialogDetails">Indstillinger gemmes kun, hvis den indtaste json-konfiguration er gyldig</key>
|
||||
|
||||
<key alias="allowAllEditors">Tillad alle editorer</key>
|
||||
<key alias="allowAllRowConfigurations">Tillad alle rækkekonfigurationer</key>
|
||||
@@ -1272,7 +1272,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="areAdded">er tilføjet</key>
|
||||
|
||||
<key alias="maxItems">Maksimalt emner</key>
|
||||
<key alias="maxItemsDescription">Efterlad blank eller sæt til 0 for ubegrænset</key>
|
||||
<key alias="maxItemsDescription">Efterlad blank eller sat til 0 ubegrænset for</key>
|
||||
|
||||
</area>
|
||||
<area alias="contentTypeEditor">
|
||||
@@ -1282,7 +1282,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="addNewTab">Tilføj ny fane</key>
|
||||
<key alias="addAnotherTab">Tilføj endnu en fane</key>
|
||||
<key alias="inheritedFrom">Nedarvet fra</key>
|
||||
<key alias="addProperty">Tilføj egenskab</key>
|
||||
<key alias="addProperty">Tilføj property</key>
|
||||
<key alias="requiredLabel">Påkrævet label</key>
|
||||
|
||||
<key alias="enableListViewHeading">Aktiver listevisning</key>
|
||||
@@ -1473,6 +1473,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="noLogin">har endnu ikke logget ind</key>
|
||||
<key alias="oldPassword">Gammelt kodeord</key>
|
||||
<key alias="password">Adgangskode</key>
|
||||
<key alias="removePhoto">Fjern billede</key>
|
||||
<key alias="resetPassword">Nulstil kodeord</key>
|
||||
<key alias="passwordChanged">Dit kodeord er blevet ændret!</key>
|
||||
<key alias="passwordConfirm">Bekræft venligst dit nye kodeord</key>
|
||||
|
||||
@@ -229,7 +229,6 @@
|
||||
<key alias="removeTextBox">Remove this text box</key>
|
||||
<key alias="contentRoot">Content root</key>
|
||||
<key alias="isSensitiveValue">This value is hidden. If you need access to view this value please contact your website administrator.</key>
|
||||
<key alias="isSensitiveValue_short">This value is hidden.</key>
|
||||
</area>
|
||||
<area alias="blueprints">
|
||||
<key alias="createBlueprintFrom">Create a new Content Template from '%0%'</key>
|
||||
@@ -663,20 +662,7 @@
|
||||
<key alias="yellow">Yellow</key>
|
||||
<key alias="orange">Orange</key>
|
||||
<key alias="blue">Blue</key>
|
||||
<key alias="bluegrey">Blue Grey</key>
|
||||
<key alias="grey">Grey</key>
|
||||
<key alias="brown">Brown</key>
|
||||
<key alias="lightblue">Light Blue</key>
|
||||
<key alias="cyan">Cyan</key>
|
||||
<key alias="lightgreen">Light Green</key>
|
||||
<key alias="lime">Lime</key>
|
||||
<key alias="amber">Amber</key>
|
||||
<key alias="deeporange">Deep Orange</key>
|
||||
<key alias="red">Red</key>
|
||||
<key alias="pink">Pink</key>
|
||||
<key alias="purple">Purple</key>
|
||||
<key alias="deeppurple">Deep Purple</key>
|
||||
<key alias="indigo">Indigo</key>
|
||||
</area>
|
||||
|
||||
<area alias="shortcuts">
|
||||
|
||||
@@ -229,7 +229,6 @@
|
||||
<key alias="removeTextBox">Remove this text box</key>
|
||||
<key alias="contentRoot">Content root</key>
|
||||
<key alias="isSensitiveValue">This value is hidden. If you need access to view this value please contact your website administrator.</key>
|
||||
<key alias="isSensitiveValue_short">This value is hidden.</key>
|
||||
</area>
|
||||
<area alias="blueprints">
|
||||
<key alias="createBlueprintFrom">Create a new Content Template from '%0%'</key>
|
||||
@@ -661,20 +660,7 @@
|
||||
<key alias="yellow">Yellow</key>
|
||||
<key alias="orange">Orange</key>
|
||||
<key alias="blue">Blue</key>
|
||||
<key alias="bluegrey">Blue Grey</key>
|
||||
<key alias="grey">Grey</key>
|
||||
<key alias="brown">Brown</key>
|
||||
<key alias="lightblue">Light Blue</key>
|
||||
<key alias="cyan">Cyan</key>
|
||||
<key alias="lightgreen">Light Green</key>
|
||||
<key alias="lime">Lime</key>
|
||||
<key alias="amber">Amber</key>
|
||||
<key alias="deeporange">Deep Orange</key>
|
||||
<key alias="red">Red</key>
|
||||
<key alias="pink">Pink</key>
|
||||
<key alias="purple">Purple</key>
|
||||
<key alias="deeppurple">Deep Purple</key>
|
||||
<key alias="indigo">Indigo</key>
|
||||
</area>
|
||||
<area alias="shortcuts">
|
||||
<key alias="addTab">Add tab</key>
|
||||
|
||||
@@ -9,7 +9,6 @@ using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Sync;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Web.Scheduling;
|
||||
|
||||
namespace Umbraco.Web
|
||||
@@ -22,12 +21,9 @@ namespace Umbraco.Web
|
||||
/// </remarks>
|
||||
public class BatchedDatabaseServerMessenger : DatabaseServerMessenger
|
||||
{
|
||||
private readonly ApplicationContext _appContext;
|
||||
|
||||
public BatchedDatabaseServerMessenger(ApplicationContext appContext, bool enableDistCalls, DatabaseServerMessengerOptions options)
|
||||
: base(appContext, enableDistCalls, options)
|
||||
{
|
||||
_appContext = appContext;
|
||||
Scheduler.Initializing += Scheduler_Initializing;
|
||||
}
|
||||
|
||||
@@ -46,7 +42,7 @@ namespace Umbraco.Web
|
||||
//start the background task runner for processing instructions
|
||||
const int delayMilliseconds = 60000;
|
||||
var instructionProcessingRunner = new BackgroundTaskRunner<IBackgroundTask>("InstructionProcessing", ApplicationContext.ProfilingLogger.Logger);
|
||||
var instructionProcessingTask = new InstructionProcessing(instructionProcessingRunner, this, _appContext.ScopeProvider, delayMilliseconds, Options.ThrottleSeconds * 1000);
|
||||
var instructionProcessingTask = new InstructionProcessing(instructionProcessingRunner, this, delayMilliseconds, Options.ThrottleSeconds * 1000);
|
||||
instructionProcessingRunner.TryAdd(instructionProcessingTask);
|
||||
e.Add(instructionProcessingTask);
|
||||
}
|
||||
@@ -77,31 +73,18 @@ namespace Umbraco.Web
|
||||
private class InstructionProcessing : RecurringTaskBase
|
||||
{
|
||||
private readonly DatabaseServerMessenger _messenger;
|
||||
private readonly IScopeProvider _scopeProvider;
|
||||
|
||||
public InstructionProcessing(IBackgroundTaskRunner<RecurringTaskBase> runner,
|
||||
DatabaseServerMessenger messenger,
|
||||
IScopeProvider scopeProvider,
|
||||
int delayMilliseconds, int periodMilliseconds)
|
||||
: base(runner, delayMilliseconds, periodMilliseconds)
|
||||
{
|
||||
_messenger = messenger;
|
||||
_scopeProvider = scopeProvider;
|
||||
}
|
||||
|
||||
public override bool PerformRun()
|
||||
{
|
||||
// beware!
|
||||
// DatabaseServerMessenger uses _appContext.DatabaseContext.Database without creating
|
||||
// scopes, and since we are running in a background task, there will be no ambient
|
||||
// scope (as would be the case within a web request), and so we would end up creating
|
||||
// (and leaking) a NoScope instance, which is bad - better make sure we have a true
|
||||
// scope here! - see U4-11207
|
||||
using (var scope = _scopeProvider.CreateScope())
|
||||
{
|
||||
_messenger.Sync();
|
||||
scope.Complete();
|
||||
}
|
||||
_messenger.Sync();
|
||||
//return true to repeat
|
||||
return true;
|
||||
}
|
||||
@@ -138,17 +121,14 @@ namespace Umbraco.Web
|
||||
batch.Clear();
|
||||
|
||||
//Write the instructions but only create JSON blobs with a max instruction count equal to MaxProcessingInstructionCount
|
||||
using (var scope = _appContext.ScopeProvider.CreateScope())
|
||||
foreach (var instructionsBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
|
||||
{
|
||||
foreach (var instructionsBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
|
||||
{
|
||||
WriteInstructions(scope, instructionsBatch);
|
||||
}
|
||||
scope.Complete();
|
||||
WriteInstructions(instructionsBatch);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void WriteInstructions(IScope scope, IEnumerable<RefreshInstruction> instructions)
|
||||
private void WriteInstructions(IEnumerable<RefreshInstruction> instructions)
|
||||
{
|
||||
var dto = new CacheInstructionDto
|
||||
{
|
||||
@@ -157,7 +137,8 @@ namespace Umbraco.Web
|
||||
OriginIdentity = LocalIdentity,
|
||||
InstructionCount = instructions.Sum(x => x.JsonIdCount)
|
||||
};
|
||||
scope.Database.Insert(dto);
|
||||
|
||||
ApplicationContext.DatabaseContext.Database.Insert(dto);
|
||||
}
|
||||
|
||||
protected ICollection<RefreshInstructionEnvelope> GetBatch(bool create)
|
||||
@@ -198,19 +179,16 @@ namespace Umbraco.Web
|
||||
if (batch == null)
|
||||
{
|
||||
//only write the json blob with a maximum count of the MaxProcessingInstructionCount
|
||||
using (var scope = _appContext.ScopeProvider.CreateScope())
|
||||
foreach (var maxBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
|
||||
{
|
||||
foreach (var maxBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
|
||||
{
|
||||
WriteInstructions(scope, maxBatch);
|
||||
}
|
||||
scope.Complete();
|
||||
WriteInstructions(maxBatch);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
batch.Add(new RefreshInstructionEnvelope(servers, refresher, instructions));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,8 +155,7 @@ namespace Umbraco.Web.Cache
|
||||
|
||||
foreach (var payload in payloads)
|
||||
{
|
||||
if (payload.Operation == OperationType.Deleted)
|
||||
ApplicationContext.Current.Services.IdkMap.ClearCache(payload.Id);
|
||||
ApplicationContext.Current.Services.IdkMap.ClearCache(payload.Id);
|
||||
|
||||
var mediaCache = ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<IMedia>();
|
||||
|
||||
@@ -191,4 +190,4 @@ namespace Umbraco.Web.Cache
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,7 @@ namespace Umbraco.Web.Cache
|
||||
|
||||
public override void Refresh(int id)
|
||||
{
|
||||
ApplicationContext.Current.Services.IdkMap.ClearCache(id);
|
||||
ClearRepositoryCacheItemById(id);
|
||||
ClearAllIsolatedCacheByEntityType<PublicAccessEntry>();
|
||||
content.Instance.UpdateSortOrder(id);
|
||||
@@ -103,6 +104,7 @@ namespace Umbraco.Web.Cache
|
||||
|
||||
public override void Refresh(IContent instance)
|
||||
{
|
||||
ApplicationContext.Current.Services.IdkMap.ClearCache(instance.Id);
|
||||
ClearRepositoryCacheItemById(instance.Id);
|
||||
ClearAllIsolatedCacheByEntityType<PublicAccessEntry>();
|
||||
content.Instance.UpdateSortOrder(instance);
|
||||
@@ -148,4 +150,4 @@ namespace Umbraco.Web.Cache
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user