Compare commits
153 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d51082f651 | |||
| f2fb275b34 | |||
| c5f388f6bc | |||
| 4419af427b | |||
| dbdee5fc2c | |||
| 25f5179b29 | |||
| 1a03bd9624 | |||
| 6a1d60c5a7 | |||
| 4fef17190f | |||
| 143b9c605b | |||
| db809f30fe | |||
| dcb50d10c4 | |||
| a91a67ed8d | |||
| 1f3e568a0d | |||
| cb539e82d0 | |||
| 1432d602ba | |||
| 841d2a7010 | |||
| 7cdb48b6c9 | |||
| a667058422 | |||
| 4ffa6bb41b | |||
| 77af16db55 | |||
| 2a44b73056 | |||
| 85d85fa587 | |||
| bd27ed739d | |||
| 3938868115 | |||
| 140792430f | |||
| c04cf1fe2e | |||
| d1d83c84a0 | |||
| 98acc50e13 | |||
| 1a0a02463e | |||
| 96c499a47e | |||
| f7e8aefeab | |||
| dfa803293f | |||
| 7ade64f855 | |||
| 346e8dcaf0 | |||
| ddfd07bf4a | |||
| a9fe46da0c | |||
| aca1f0d186 | |||
| 9eb415d398 | |||
| 8f6b728534 | |||
| 2e0c09ab39 | |||
| f211344786 | |||
| f8764cdd20 | |||
| 1d17bfd59a | |||
| 98ad6ad366 | |||
| 68702b98f5 | |||
| f93caf277b | |||
| 32db674397 | |||
| e0a7698780 | |||
| 783c74d3ba | |||
| 96d7bc3898 | |||
| 21963c03a2 | |||
| a2a9794fdb | |||
| 879a132077 | |||
| 9650d314c6 | |||
| fcc0c452bb | |||
| 606ebcae92 | |||
| af10ae9e34 | |||
| a23c150738 | |||
| 085a678266 | |||
| c73fb6144b | |||
| bfd201efcc | |||
| 5a2b4f031b | |||
| cf7cafeb4c | |||
| 870657affa | |||
| fe11d4770d | |||
| ac75d8148d | |||
| 4a32cddf08 | |||
| 7461e7c55b | |||
| c8fe9030c7 | |||
| 2ae236e98d | |||
| 802fb95784 | |||
| 0297fdb32f | |||
| 5bede4bf9f | |||
| d37106576d | |||
| ed0f0f7942 | |||
| 3d81c73495 | |||
| e7a540e717 | |||
| bb886c237e | |||
| 6c1e271fa8 | |||
| 4c1b807e4f | |||
| 3b22c0cdd7 | |||
| 31d8f49d3b | |||
| 631404743f | |||
| 1e154e8bc9 | |||
| d5c9639170 | |||
| b90cccbfff | |||
| 94b7c36d62 | |||
| 22f0641c54 | |||
| e465a937c5 | |||
| d2164bc94d | |||
| df9d09725b | |||
| 1ffdd1abd1 | |||
| a06de1b165 | |||
| 0a56f46b12 | |||
| 972f9b3546 | |||
| 0fd3af6828 | |||
| fafb207799 | |||
| b1aea424e8 | |||
| 3598acaddc | |||
| 8e03a1ffca | |||
| ded8afa8fc | |||
| dcd2b1eb6b | |||
| c04ef47be3 | |||
| 62f3c87e8a | |||
| 1b9776ecfb | |||
| 7b1efa718e | |||
| f60ad15f70 | |||
| 28ab176466 | |||
| 3f3db006e7 | |||
| 7801cdf9ff | |||
| 836e1bba54 | |||
| de9c5b88ab | |||
| 77981f889f | |||
| 0a132ed5ed | |||
| 5a953761b0 | |||
| 27ee192c8f | |||
| dfa58183c6 | |||
| e8668f3ed4 | |||
| c84e3dac38 | |||
| 72ab51ea60 | |||
| 1bfb63fe86 | |||
| 2cf68ab263 | |||
| 215bc64a83 | |||
| 1b17f4e9df | |||
| 73f0b1992d | |||
| 21f54dd4ff | |||
| a5903ec419 | |||
| ac496b0cf6 | |||
| 6036136938 | |||
| a9c7a7a405 | |||
| ce8286dadd | |||
| 532b177d2e | |||
| 504aac0350 | |||
| 454aad2170 | |||
| fd0cb7da23 | |||
| 4093fd9b79 | |||
| 3d6f91cbef | |||
| fffd508bb2 | |||
| f4eb37d44d | |||
| c79aaa9c48 | |||
| 6aa00c52dc | |||
| 333b35d8b9 | |||
| 890673a197 | |||
| 6344ad28aa | |||
| eadc3c8c5a | |||
| 27539d4aad | |||
| f7f23015d0 | |||
| e432b7061d | |||
| 30f63eefb3 | |||
| 6114193fd5 | |||
| 82420605ef | |||
| fc92d40b3a |
@@ -33,7 +33,7 @@
|
|||||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
|
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
|
||||||
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
|
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
|
||||||
<dependency id="Newtonsoft.Json" version="[9.0.1, 10.0.0)" />
|
<dependency id="Newtonsoft.Json" version="[9.0.1, 10.0.0)" />
|
||||||
<dependency id="Examine" version="[0.1.81, 1.0.0)" />
|
<dependency id="Examine" version="[0.1.82, 1.0.0)" />
|
||||||
<dependency id="ImageProcessor" version="[2.5.2, 3.0.0)" />
|
<dependency id="ImageProcessor" version="[2.5.2, 3.0.0)" />
|
||||||
<dependency id="ImageProcessor.Web" version="[4.8.2, 5.0.0)" />
|
<dependency id="ImageProcessor.Web" version="[4.8.2, 5.0.0)" />
|
||||||
<dependency id="semver" version="[2.0.4, 3.0.0)" />
|
<dependency id="semver" version="[2.0.4, 3.0.0)" />
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
<httpRuntime xdt:Transform="InsertIfMissing" />
|
<httpRuntime xdt:Transform="InsertIfMissing" />
|
||||||
<httpRuntime maxRequestLength="51200" fcnMode="Single" xdt:Transform="SetAttributes(fcnMode,maxRequestLength)" />
|
<httpRuntime maxRequestLength="51200" fcnMode="Single" xdt:Transform="SetAttributes(fcnMode,maxRequestLength)" />
|
||||||
<httpRuntime targetFramework="4.5" xdt:Locator="Condition(count(@targetFramework) != 1)" xdt:Transform="SetAttributes(targetFramework)" />
|
<httpRuntime targetFramework="4.5" xdt:Locator="Condition(count(@targetFramework) != 1)" xdt:Transform="SetAttributes(targetFramework)" />
|
||||||
|
|
||||||
<membership defaultProvider="DefaultMembershipProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove" />
|
<membership defaultProvider="DefaultMembershipProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove" />
|
||||||
<roleManager defaultProvider="DefaultRoleProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>
|
<roleManager defaultProvider="DefaultRoleProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>
|
||||||
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
|
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
|
||||||
@@ -337,7 +337,7 @@
|
|||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
<dependentAssembly xdt:Transform="Insert">
|
<dependentAssembly xdt:Transform="Insert">
|
||||||
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
|
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-1.4.9.0" newVersion="1.4.9.0" />
|
<bindingRedirect oldVersion="0.0.0.0-1.4.9.5" newVersion="1.4.9.5" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly xdt:Transform="Insert">
|
<dependentAssembly xdt:Transform="Insert">
|
||||||
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
|
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
|
||||||
|
|||||||
@@ -34,10 +34,15 @@
|
|||||||
xdt:Transform="SetAttributes()" />
|
xdt:Transform="SetAttributes()" />
|
||||||
<add application="settings" alias="templates" title="Templates" type="Umbraco.Web.Trees.TemplatesTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="1"
|
<add application="settings" alias="templates" title="Templates" type="Umbraco.Web.Trees.TemplatesTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="1"
|
||||||
xdt:Locator="Match(application,alias)"
|
xdt:Locator="Match(application,alias)"
|
||||||
xdt:Transform="SetAttributes()" />
|
xdt:Transform="SetAttributes()" />
|
||||||
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTree, umbraco" sortOrder="2"
|
|
||||||
xdt:Locator="Match(application,alias)"
|
<add application="settings" alias="partialViews" type="Umbraco.Web.Trees.PartialViewsTree, umbraco"
|
||||||
xdt:Transform="SetAttributes()" />
|
xdt:Locator="Match(application,alias,type)"
|
||||||
|
xdt:Transform="Remove()" />
|
||||||
|
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTreeController, umbraco" sortOrder="2"
|
||||||
|
xdt:Locator="Match(application,alias)"
|
||||||
|
xdt:Transform="InsertIfMissing" />
|
||||||
|
|
||||||
<add application="settings" alias="scripts" title="Scripts" type="umbraco.loadScripts, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
|
<add application="settings" alias="scripts" title="Scripts" type="umbraco.loadScripts, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
|
||||||
xdt:Locator="Match(application,alias)"
|
xdt:Locator="Match(application,alias)"
|
||||||
xdt:Transform="SetAttributes()" />
|
xdt:Transform="SetAttributes()" />
|
||||||
@@ -84,9 +89,14 @@
|
|||||||
<add application="developer" alias="xslt" title="XSLT Files" type="umbraco.loadXslt, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="5"
|
<add application="developer" alias="xslt" title="XSLT Files" type="umbraco.loadXslt, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="5"
|
||||||
xdt:Locator="Match(application,alias)"
|
xdt:Locator="Match(application,alias)"
|
||||||
xdt:Transform="SetAttributes()" />
|
xdt:Transform="SetAttributes()" />
|
||||||
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder"
|
|
||||||
xdt:Locator="Match(application,alias)"
|
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco"
|
||||||
xdt:Transform="SetAttributes()" />
|
xdt:Locator="Match(application,alias,type)"
|
||||||
|
xdt:Transform="Remove()" />
|
||||||
|
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTreeController, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder"
|
||||||
|
xdt:Locator="Match(application,alias)"
|
||||||
|
xdt:Transform="InsertIfMissing" />
|
||||||
|
|
||||||
<add application="developer" alias="python"
|
<add application="developer" alias="python"
|
||||||
xdt:Locator="Match(application,alias)"
|
xdt:Locator="Match(application,alias)"
|
||||||
xdt:Transform="Remove" />
|
xdt:Transform="Remove" />
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||||
7.6.0
|
7.6.0
|
||||||
alpha074
|
beta06
|
||||||
|
|||||||
+1
-1
@@ -12,4 +12,4 @@ using System.Resources;
|
|||||||
[assembly: AssemblyVersion("1.0.*")]
|
[assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
[assembly: AssemblyFileVersion("7.6.0")]
|
[assembly: AssemblyFileVersion("7.6.0")]
|
||||||
[assembly: AssemblyInformationalVersion("7.6.0-alpha074")]
|
[assembly: AssemblyInformationalVersion("7.6.0-beta06")]
|
||||||
@@ -17,9 +17,12 @@ namespace Umbraco.Core
|
|||||||
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=null", RegexOptions.Compiled);
|
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=null");
|
||||||
private const string Log4NetReplacement = "log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
|
private const string Log4NetReplacement = "log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
|
||||||
|
|
||||||
|
private static readonly Regex HtmlAgilityAssemblyPattern = new Regex("HtmlAgilityPack, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=bd319b19eaf3b43a");
|
||||||
|
private const string HtmlAgilityReplacement = "HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
|
/// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -28,13 +31,18 @@ namespace Umbraco.Core
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||||
{
|
{
|
||||||
//log4net:
|
//log4net:
|
||||||
// Use regex to match and replace
|
|
||||||
if (Log4NetAssemblyPattern.IsMatch(args.Name) && args.Name != Log4NetReplacement)
|
if (Log4NetAssemblyPattern.IsMatch(args.Name) && args.Name != Log4NetReplacement)
|
||||||
{
|
{
|
||||||
return Assembly.Load(Log4NetAssemblyPattern.Replace(args.Name, Log4NetReplacement));
|
return Assembly.Load(Log4NetAssemblyPattern.Replace(args.Name, Log4NetReplacement));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//HtmlAgility:
|
||||||
|
if (HtmlAgilityAssemblyPattern.IsMatch(args.Name) && args.Name != HtmlAgilityReplacement)
|
||||||
|
{
|
||||||
|
return Assembly.Load(HtmlAgilityAssemblyPattern.Replace(args.Name, HtmlAgilityReplacement));
|
||||||
|
}
|
||||||
|
|
||||||
//AutoMapper:
|
//AutoMapper:
|
||||||
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
|
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
|
||||||
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
|
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ namespace Umbraco.Core.Cache
|
|||||||
|
|
||||||
public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider)
|
public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider)
|
||||||
{
|
{
|
||||||
|
if (innerProvider.GetType() == typeof(DeepCloneRuntimeCacheProvider))
|
||||||
|
throw new InvalidOperationException("A " + typeof(DeepCloneRuntimeCacheProvider) + " cannot wrap another instance of " + typeof(DeepCloneRuntimeCacheProvider));
|
||||||
|
|
||||||
InnerProvider = innerProvider;
|
InnerProvider = innerProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,9 +108,11 @@ namespace Umbraco.Core.Cache
|
|||||||
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
|
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
|
||||||
if (value == null) return null; // do not store null values (backward compat)
|
if (value == null) return null; // do not store null values (backward compat)
|
||||||
|
|
||||||
|
//Clone/reset to go into the cache
|
||||||
return CheckCloneableAndTracksChanges(value);
|
return CheckCloneableAndTracksChanges(value);
|
||||||
}, timeout, isSliding, priority, removedCallback, dependentFiles);
|
}, timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||||
|
|
||||||
|
//Clone/reset to go out of the cache
|
||||||
return CheckCloneableAndTracksChanges(cached);
|
return CheckCloneableAndTracksChanges(cached);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,14 @@ namespace Umbraco.Core.Configuration
|
|||||||
{
|
{
|
||||||
var appSettings = System.Configuration.ConfigurationManager.AppSettings;
|
var appSettings = System.Configuration.ConfigurationManager.AppSettings;
|
||||||
LogUncompletedScopes = string.Equals("true", appSettings["Umbraco.CoreDebug.LogUncompletedScopes"], StringComparison.OrdinalIgnoreCase);
|
LogUncompletedScopes = string.Equals("true", appSettings["Umbraco.CoreDebug.LogUncompletedScopes"], StringComparison.OrdinalIgnoreCase);
|
||||||
|
DumpOnTimeoutThreadAbort = string.Equals("true", appSettings["Umbraco.CoreDebug.DumpOnTimeoutThreadAbort"], StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
// when true, Scope logs the stack trace for any scope that gets disposed without being completed.
|
// when true, Scope logs the stack trace for any scope that gets disposed without being completed.
|
||||||
// this helps troubleshooting rogue scopes that we forget to complete
|
// this helps troubleshooting rogue scopes that we forget to complete
|
||||||
public bool LogUncompletedScopes { get; private set; }
|
public bool LogUncompletedScopes { get; private set; }
|
||||||
|
// when true, the Logger creates a minidump of w3wp in ~/App_Data/MiniDump whenever it logs
|
||||||
|
// an error due to a ThreadAbortException that is due to a timeout.
|
||||||
|
public bool DumpOnTimeoutThreadAbort { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
|
|||||||
/// Gets the version comment (like beta or RC).
|
/// Gets the version comment (like beta or RC).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The version comment.</value>
|
/// <value>The version comment.</value>
|
||||||
public static string CurrentComment { get { return "alpha074"; } }
|
public static string CurrentComment { get { return "beta06"; } }
|
||||||
|
|
||||||
// Get the version of the umbraco.dll by looking at a class in that dll
|
// Get the version of the umbraco.dll by looking at a class in that dll
|
||||||
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
|
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Umbraco.Core.IO;
|
||||||
|
|
||||||
|
namespace Umbraco.Core.Diagnostics
|
||||||
|
{
|
||||||
|
// taken from https://blogs.msdn.microsoft.com/dondu/2010/10/24/writing-minidumps-in-c/
|
||||||
|
// and https://blogs.msdn.microsoft.com/dondu/2010/10/31/writing-minidumps-from-exceptions-in-c/
|
||||||
|
// which itself got it from http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/
|
||||||
|
|
||||||
|
internal static class MiniDump
|
||||||
|
{
|
||||||
|
private static readonly object LockO = new object();
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum Option : uint
|
||||||
|
{
|
||||||
|
// From dbghelp.h:
|
||||||
|
Normal = 0x00000000,
|
||||||
|
WithDataSegs = 0x00000001,
|
||||||
|
WithFullMemory = 0x00000002,
|
||||||
|
WithHandleData = 0x00000004,
|
||||||
|
FilterMemory = 0x00000008,
|
||||||
|
ScanMemory = 0x00000010,
|
||||||
|
WithUnloadedModules = 0x00000020,
|
||||||
|
WithIndirectlyReferencedMemory = 0x00000040,
|
||||||
|
FilterModulePaths = 0x00000080,
|
||||||
|
WithProcessThreadData = 0x00000100,
|
||||||
|
WithPrivateReadWriteMemory = 0x00000200,
|
||||||
|
WithoutOptionalData = 0x00000400,
|
||||||
|
WithFullMemoryInfo = 0x00000800,
|
||||||
|
WithThreadInfo = 0x00001000,
|
||||||
|
WithCodeSegs = 0x00002000,
|
||||||
|
WithoutAuxiliaryState = 0x00004000,
|
||||||
|
WithFullAuxiliaryState = 0x00008000,
|
||||||
|
WithPrivateWriteCopyMemory = 0x00010000,
|
||||||
|
IgnoreInaccessibleMemory = 0x00020000,
|
||||||
|
ValidTypeFlags = 0x0003ffff,
|
||||||
|
}
|
||||||
|
|
||||||
|
//typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
|
||||||
|
// DWORD ThreadId;
|
||||||
|
// PEXCEPTION_POINTERS ExceptionPointers;
|
||||||
|
// BOOL ClientPointers;
|
||||||
|
//} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64!
|
||||||
|
public struct MiniDumpExceptionInformation
|
||||||
|
{
|
||||||
|
public uint ThreadId;
|
||||||
|
public IntPtr ExceptionPointers;
|
||||||
|
[MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public bool ClientPointers;
|
||||||
|
}
|
||||||
|
|
||||||
|
//BOOL
|
||||||
|
//WINAPI
|
||||||
|
//MiniDumpWriteDump(
|
||||||
|
// __in HANDLE hProcess,
|
||||||
|
// __in DWORD ProcessId,
|
||||||
|
// __in HANDLE hFile,
|
||||||
|
// __in MINIDUMP_TYPE DumpType,
|
||||||
|
// __in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||||
|
// __in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
||||||
|
// __in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam
|
||||||
|
// );
|
||||||
|
|
||||||
|
// Overload requiring MiniDumpExceptionInformation
|
||||||
|
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
|
||||||
|
private static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);
|
||||||
|
|
||||||
|
// Overload supporting MiniDumpExceptionInformation == NULL
|
||||||
|
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
|
||||||
|
private static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
|
||||||
|
private static extern uint GetCurrentThreadId();
|
||||||
|
|
||||||
|
private static bool Write(SafeHandle fileHandle, Option options, bool withException = false)
|
||||||
|
{
|
||||||
|
var currentProcess = Process.GetCurrentProcess();
|
||||||
|
var currentProcessHandle = currentProcess.Handle;
|
||||||
|
var currentProcessId = (uint)currentProcess.Id;
|
||||||
|
|
||||||
|
MiniDumpExceptionInformation exp;
|
||||||
|
|
||||||
|
exp.ThreadId = GetCurrentThreadId();
|
||||||
|
exp.ClientPointers = false;
|
||||||
|
exp.ExceptionPointers = IntPtr.Zero;
|
||||||
|
|
||||||
|
if (withException)
|
||||||
|
exp.ExceptionPointers = Marshal.GetExceptionPointers();
|
||||||
|
|
||||||
|
var bRet = exp.ExceptionPointers == IntPtr.Zero
|
||||||
|
? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)
|
||||||
|
: MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, ref exp, IntPtr.Zero, IntPtr.Zero);
|
||||||
|
|
||||||
|
return bRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Dump(Option options = Option.WithFullMemory, bool withException = false)
|
||||||
|
{
|
||||||
|
lock (LockO)
|
||||||
|
{
|
||||||
|
// work around "stack trace is not available while minidump debugging",
|
||||||
|
// by making sure a local var (that we can inspect) contains the stack trace.
|
||||||
|
// getting the call stack before it is unwound would require a special exception
|
||||||
|
// filter everywhere in our code = not!
|
||||||
|
var stacktrace = withException ? Environment.StackTrace : string.Empty;
|
||||||
|
|
||||||
|
var filepath = IOHelper.MapPath("~/App_Data/MiniDump");
|
||||||
|
if (Directory.Exists(filepath) == false)
|
||||||
|
Directory.CreateDirectory(filepath);
|
||||||
|
|
||||||
|
var filename = Path.Combine(filepath, string.Format("{0:yyyyMMddTHHmmss}.{1}.dmp", DateTime.UtcNow, Guid.NewGuid().ToString("N").Substring(0, 4)));
|
||||||
|
using (var stream = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Write))
|
||||||
|
{
|
||||||
|
return Write(stream.SafeFileHandle, options, withException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool OkToDump()
|
||||||
|
{
|
||||||
|
lock (LockO)
|
||||||
|
{
|
||||||
|
var filepath = IOHelper.MapPath("~/App_Data/MiniDump");
|
||||||
|
if (Directory.Exists(filepath) == false) return true;
|
||||||
|
var count = Directory.GetFiles(filepath, "*.dmp").Length;
|
||||||
|
return count < 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -295,22 +295,5 @@ namespace Umbraco.Core
|
|||||||
return list1Groups.Count == list2Groups.Count
|
return list1Groups.Count == list2Groups.Count
|
||||||
&& list1Groups.All(g => g.Count() == list2Groups[g.Key].Count());
|
&& list1Groups.All(g => g.Count() == list2Groups[g.Key].Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
///<summary>
|
|
||||||
/// Returns the items of the given enumerable as a pure enumerable.
|
|
||||||
/// <remarks>
|
|
||||||
/// When quering lists using methods such as <see cref="M:List.Where"/>, the result, despite appearing to look like and quack like an
|
|
||||||
/// <see cref="T:Enumerable{T}"/> the type is actually an instance of <see cref="T:System.Linq.Enumerable.WhereEnumerableIterator"/>
|
|
||||||
/// </remarks>
|
|
||||||
/// </summary>
|
|
||||||
///<param name="source">The item to find.</param>
|
|
||||||
///<returns>The index of the first matching item, or -1 if the item was not found.</returns>
|
|
||||||
internal static IEnumerable<T> Yield<T>(this IEnumerable<T> source)
|
|
||||||
{
|
|
||||||
foreach (var element in source)
|
|
||||||
{
|
|
||||||
yield return element;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,11 +218,11 @@ namespace Umbraco.Core.IO
|
|||||||
var normPath = NormPath(path);
|
var normPath = NormPath(path);
|
||||||
var shadows = Nodes.Where(kvp => IsChild(normPath, kvp.Key)).ToArray();
|
var shadows = Nodes.Where(kvp => IsChild(normPath, kvp.Key)).ToArray();
|
||||||
var files = filter != null ? _fs.GetFiles(path, filter) : _fs.GetFiles(path);
|
var files = filter != null ? _fs.GetFiles(path, filter) : _fs.GetFiles(path);
|
||||||
var regexFilter = FilterToRegex(filter);
|
var wildcard = filter == null ? null : new WildcardExpression(filter);
|
||||||
return files
|
return files
|
||||||
.Except(shadows.Where(kvp => (kvp.Value.IsFile && kvp.Value.IsDelete) || kvp.Value.IsDir)
|
.Except(shadows.Where(kvp => (kvp.Value.IsFile && kvp.Value.IsDelete) || kvp.Value.IsDir)
|
||||||
.Select(kvp => kvp.Key))
|
.Select(kvp => kvp.Key))
|
||||||
.Union(shadows.Where(kvp => kvp.Value.IsFile && kvp.Value.IsExist && FilterByRegex(kvp.Key, regexFilter)).Select(kvp => kvp.Key))
|
.Union(shadows.Where(kvp => kvp.Value.IsFile && kvp.Value.IsExist && (wildcard == null || wildcard.IsMatch(kvp.Key))).Select(kvp => kvp.Key))
|
||||||
.Distinct();
|
.Distinct();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,32 +326,65 @@ namespace Umbraco.Core.IO
|
|||||||
_sfs.AddFile(path, physicalPath, overrideIfExists, copy);
|
_sfs.AddFile(path, physicalPath, overrideIfExists, copy);
|
||||||
Nodes[normPath] = new ShadowNode(false, false);
|
Nodes[normPath] = new ShadowNode(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Helper function for filtering keys by Regex if a filter is specified.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input"></param>
|
|
||||||
/// <param name="regexFilter"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal static bool FilterByRegex(string input, string regexFilter)
|
|
||||||
{
|
|
||||||
if (regexFilter == null) return true;
|
|
||||||
return regexFilter != string.Empty && Regex.IsMatch(input, regexFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
// copied from System.Web.Util.Wildcard internal
|
||||||
/// Transforms a filter pattern into a Regex pattern
|
internal class WildcardExpression
|
||||||
/// </summary>
|
|
||||||
/// <param name="pattern"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <remarks>
|
|
||||||
/// Appending '$' only if not containing wildcard is stupid and broken.
|
|
||||||
/// It is however what seems to be what they're doing in .NET so we need to match the functionality.
|
|
||||||
/// </remarks>
|
|
||||||
internal static string FilterToRegex(string pattern)
|
|
||||||
{
|
{
|
||||||
if (pattern == null) return null;
|
private readonly string _pattern;
|
||||||
return "^" + Regex.Escape(pattern).Replace("\\*", ".*").Replace("\\?", ".") + (pattern.Contains("*") ? string.Empty : "$");
|
private readonly bool _caseInsensitive;
|
||||||
|
private Regex _regex;
|
||||||
|
|
||||||
|
private static Regex metaRegex = new Regex("[\\+\\{\\\\\\[\\|\\(\\)\\.\\^\\$]");
|
||||||
|
private static Regex questRegex = new Regex("\\?");
|
||||||
|
private static Regex starRegex = new Regex("\\*");
|
||||||
|
private static Regex commaRegex = new Regex(",");
|
||||||
|
private static Regex slashRegex = new Regex("(?=/)");
|
||||||
|
private static Regex backslashRegex = new Regex("(?=[\\\\:])");
|
||||||
|
|
||||||
|
public WildcardExpression(string pattern, bool caseInsensitive = true)
|
||||||
|
{
|
||||||
|
_pattern = pattern;
|
||||||
|
_caseInsensitive = caseInsensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureRegex(string pattern)
|
||||||
|
{
|
||||||
|
if (_regex != null) return;
|
||||||
|
|
||||||
|
var options = RegexOptions.None;
|
||||||
|
|
||||||
|
// match right-to-left (for speed) if the pattern starts with a *
|
||||||
|
|
||||||
|
if (pattern.Length > 0 && pattern[0] == '*')
|
||||||
|
options = RegexOptions.RightToLeft | RegexOptions.Singleline;
|
||||||
|
else
|
||||||
|
options = RegexOptions.Singleline;
|
||||||
|
|
||||||
|
// case insensitivity
|
||||||
|
|
||||||
|
if (_caseInsensitive)
|
||||||
|
options |= RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;
|
||||||
|
|
||||||
|
// Remove regex metacharacters
|
||||||
|
|
||||||
|
pattern = metaRegex.Replace(pattern, "\\$0");
|
||||||
|
|
||||||
|
// Replace wildcard metacharacters with regex codes
|
||||||
|
|
||||||
|
pattern = questRegex.Replace(pattern, ".");
|
||||||
|
pattern = starRegex.Replace(pattern, ".*");
|
||||||
|
pattern = commaRegex.Replace(pattern, "\\z|\\A");
|
||||||
|
|
||||||
|
// anchor the pattern at beginning and end, and return the regex
|
||||||
|
|
||||||
|
_regex = new Regex("\\A" + pattern + "\\z", options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsMatch(string input)
|
||||||
|
{
|
||||||
|
EnsureRegex(_pattern);
|
||||||
|
return _regex.IsMatch(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ using System.Threading;
|
|||||||
using System.Web;
|
using System.Web;
|
||||||
using log4net;
|
using log4net;
|
||||||
using log4net.Config;
|
using log4net.Config;
|
||||||
|
using Umbraco.Core.Configuration;
|
||||||
|
using Umbraco.Core.Diagnostics;
|
||||||
|
|
||||||
namespace Umbraco.Core.Logging
|
namespace Umbraco.Core.Logging
|
||||||
{
|
{
|
||||||
@@ -57,23 +59,55 @@ namespace Umbraco.Core.Logging
|
|||||||
internal ILog LoggerFor(object getTypeFromInstance)
|
internal ILog LoggerFor(object getTypeFromInstance)
|
||||||
{
|
{
|
||||||
if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance");
|
if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance");
|
||||||
|
|
||||||
return LogManager.GetLogger(getTypeFromInstance.GetType());
|
return LogManager.GetLogger(getTypeFromInstance.GetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Error(Type callingType, string message, Exception exception)
|
public void Error(Type callingType, string message, Exception exception)
|
||||||
{
|
{
|
||||||
var logger = LogManager.GetLogger(callingType);
|
var logger = LogManager.GetLogger(callingType);
|
||||||
if (logger == null) return;
|
if (logger == null) return;
|
||||||
|
|
||||||
|
var dump = false;
|
||||||
|
|
||||||
if (IsTimeoutThreadAbortException(exception))
|
if (IsTimeoutThreadAbortException(exception))
|
||||||
{
|
{
|
||||||
message += "\r\nThe thread has been aborted, because the request has timed out.";
|
message += "\r\nThe thread has been aborted, because the request has timed out.";
|
||||||
|
|
||||||
|
// dump if configured, or if stacktrace contains Monitor.ReliableEnter
|
||||||
|
dump = UmbracoConfig.For.CoreDebug().DumpOnTimeoutThreadAbort || IsMonitorEnterThreadAbortException(exception);
|
||||||
|
|
||||||
|
// dump if it is ok to dump (might have a cap on number of dump...)
|
||||||
|
dump &= MiniDump.OkToDump();
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Error(message, exception);
|
if (dump)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var dumped = MiniDump.Dump(withException: true);
|
||||||
|
message += dumped
|
||||||
|
? "\r\nA minidump was created in App_Data/MiniDump"
|
||||||
|
: "\r\nFailed to create a minidump";
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
message += string.Format("\r\nFailed to create a minidump ({0}: {1})", e.GetType().FullName, e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Error(message, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsMonitorEnterThreadAbortException(Exception exception)
|
||||||
|
{
|
||||||
|
var abort = exception as ThreadAbortException;
|
||||||
|
if (abort == null) return false;
|
||||||
|
|
||||||
|
var stacktrace = abort.StackTrace;
|
||||||
|
return stacktrace.Contains("System.Threading.Monitor.ReliableEnter");
|
||||||
|
}
|
||||||
|
|
||||||
private static bool IsTimeoutThreadAbortException(Exception exception)
|
private static bool IsTimeoutThreadAbortException(Exception exception)
|
||||||
{
|
{
|
||||||
var abort = exception as ThreadAbortException;
|
var abort = exception as ThreadAbortException;
|
||||||
@@ -105,7 +139,7 @@ namespace Umbraco.Core.Logging
|
|||||||
if (showHttpTrace && HttpContext.Current != null)
|
if (showHttpTrace && HttpContext.Current != null)
|
||||||
{
|
{
|
||||||
HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()));
|
HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
var logger = LogManager.GetLogger(callingType);
|
var logger = LogManager.GetLogger(callingType);
|
||||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||||
@@ -122,7 +156,7 @@ namespace Umbraco.Core.Logging
|
|||||||
var logger = LogManager.GetLogger(callingType);
|
var logger = LogManager.GetLogger(callingType);
|
||||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||||
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
|
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
|
||||||
logger.WarnFormat((message) + ". Exception: " + e, executedParams);
|
logger.WarnFormat((message) + ". Exception: " + e, executedParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using Umbraco.Core.Logging;
|
||||||
|
|
||||||
namespace Umbraco.Core.Models
|
namespace Umbraco.Core.Models
|
||||||
{
|
{
|
||||||
@@ -84,16 +86,64 @@ namespace Umbraco.Core.Models
|
|||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
|
|
||||||
private Type _runtimeType;
|
private Type _runtimeType;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the CLR type based on it's assembly name stored in the config
|
/// Returns the CLR type based on it's assembly name stored in the config
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Type GetRuntimeType()
|
public Type GetRuntimeType()
|
||||||
{
|
{
|
||||||
return _runtimeType ?? (_runtimeType = System.Type.GetType(Type));
|
if (_runtimeType != null)
|
||||||
}
|
return _runtimeType;
|
||||||
|
|
||||||
|
|
||||||
|
_runtimeType = TryGetType(Type);
|
||||||
|
return _runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to try to get and cache the tree type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
internal static Type TryGetType(string type)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ResolvedTypes.GetOrAdd(type, s =>
|
||||||
|
{
|
||||||
|
var result = System.Type.GetType(type);
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//we need to implement a bit of a hack here due to some trees being renamed and backwards compat
|
||||||
|
var parts = type.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (parts.Length == 2)
|
||||||
|
{
|
||||||
|
if (parts[1].Trim() == "umbraco" && parts[0].StartsWith("Umbraco.Web.Trees") && parts[0].EndsWith("Controller") == false)
|
||||||
|
{
|
||||||
|
//if it's one of our controllers but it's not suffixed with "Controller" then add it and try again
|
||||||
|
var tempType = parts[0] + "Controller, umbraco";
|
||||||
|
|
||||||
|
result = System.Type.GetType(tempType);
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("Could not resolve type");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
//swallow, this is our own exception, couldn't find the type
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly ConcurrentDictionary<string, Type> ResolvedTypes = new ConcurrentDictionary<string, Type>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,6 +274,9 @@ namespace Umbraco.Core.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasPublishedVersion { get { return PublishedVersionGuid != default(Guid); } }
|
public bool HasPublishedVersion { get { return PublishedVersionGuid != default(Guid); } }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
internal DateTime PublishedDate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Changes the Trashed state of the content object
|
/// Changes the Trashed state of the content object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -49,7 +49,10 @@ namespace Umbraco.Core.Models
|
|||||||
return path
|
return path
|
||||||
.Replace('\\', System.IO.Path.DirectorySeparatorChar)
|
.Replace('\\', System.IO.Path.DirectorySeparatorChar)
|
||||||
.Replace('/', System.IO.Path.DirectorySeparatorChar);
|
.Replace('/', System.IO.Path.DirectorySeparatorChar);
|
||||||
//.TrimStart(System.IO.Path.DirectorySeparatorChar);
|
|
||||||
|
//Don't strip the start - this was a bug fixed in 7.3, see ScriptRepositoryTests.PathTests
|
||||||
|
//.TrimStart(System.IO.Path.DirectorySeparatorChar)
|
||||||
|
//.TrimStart('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (contentType == null)
|
if (contentType == null)
|
||||||
throw new Exception(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
|
throw new InvalidOperationException(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
|
||||||
itemType.ToString().ToLower(), alias));
|
itemType.ToString().ToLower(), alias));
|
||||||
|
|
||||||
return new PublishedContentType(contentType);
|
return new PublishedContentType(contentType);
|
||||||
|
|||||||
@@ -19,5 +19,8 @@ namespace Umbraco.Core.Models.Rdbms
|
|||||||
|
|
||||||
[Column("newest")]
|
[Column("newest")]
|
||||||
public bool Newest { get; set; }
|
public bool Newest { get; set; }
|
||||||
|
|
||||||
|
[Column("updateDate")]
|
||||||
|
public DateTime VersionDate { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,6 +22,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
private readonly string _httpContextKey;
|
private readonly string _httpContextKey;
|
||||||
private readonly List<Type> _instanceTypes = new List<Type>();
|
private readonly List<Type> _instanceTypes = new List<Type>();
|
||||||
private IEnumerable<TResolved> _sortedValues;
|
private IEnumerable<TResolved> _sortedValues;
|
||||||
|
private readonly Func<HttpContextBase> _httpContextGetter;
|
||||||
|
|
||||||
private int _defaultPluginWeight = 100;
|
private int _defaultPluginWeight = 100;
|
||||||
|
|
||||||
@@ -42,12 +43,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
if (logger == null) throw new ArgumentNullException("logger");
|
if (logger == null) throw new ArgumentNullException("logger");
|
||||||
CanResolveBeforeFrozen = false;
|
CanResolveBeforeFrozen = false;
|
||||||
if (scope == ObjectLifetimeScope.HttpRequest)
|
if (scope == ObjectLifetimeScope.HttpRequest)
|
||||||
{
|
_httpContextGetter = () => new HttpContextWrapper(HttpContext.Current);
|
||||||
if (HttpContext.Current == null)
|
|
||||||
throw new InvalidOperationException("Use alternative constructor accepting a HttpContextBase object in order to set the lifetime scope to HttpRequest when HttpContext.Current is null");
|
|
||||||
|
|
||||||
CurrentHttpContext = new HttpContextWrapper(HttpContext.Current);
|
|
||||||
}
|
|
||||||
|
|
||||||
ServiceProvider = serviceProvider;
|
ServiceProvider = serviceProvider;
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
@@ -84,7 +80,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
LifetimeScope = ObjectLifetimeScope.HttpRequest;
|
LifetimeScope = ObjectLifetimeScope.HttpRequest;
|
||||||
_httpContextKey = GetType().FullName;
|
_httpContextKey = GetType().FullName;
|
||||||
ServiceProvider = serviceProvider;
|
ServiceProvider = serviceProvider;
|
||||||
CurrentHttpContext = httpContext;
|
_httpContextGetter = () => httpContext;
|
||||||
_instanceTypes = new List<Type>();
|
_instanceTypes = new List<Type>();
|
||||||
|
|
||||||
InitializeAppInstances();
|
InitializeAppInstances();
|
||||||
@@ -160,7 +156,16 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
/// Gets or sets the <see cref="HttpContextBase"/> used to initialize this object, if any.
|
/// Gets or sets the <see cref="HttpContextBase"/> used to initialize this object, if any.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>If not null, then <c>LifetimeScope</c> will be <c>ObjectLifetimeScope.HttpRequest</c>.</remarks>
|
/// <remarks>If not null, then <c>LifetimeScope</c> will be <c>ObjectLifetimeScope.HttpRequest</c>.</remarks>
|
||||||
protected HttpContextBase CurrentHttpContext { get; private set; }
|
protected HttpContextBase CurrentHttpContext
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var context = _httpContextGetter == null ? null : _httpContextGetter();
|
||||||
|
if (context == null)
|
||||||
|
throw new InvalidOperationException("Cannot use this resolver with lifetime 'HttpRequest' when there is no current HttpContext. Either use the ctor accepting an HttpContextBase, or use the resolver from within a request exclusively.");
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the service provider used to instantiate objects
|
/// Returns the service provider used to instantiate objects
|
||||||
@@ -196,7 +201,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the default type weight.
|
/// Gets or sets the default type weight.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>Determines the weight of types that do not have a <c>WeightAttribute</c> set on
|
/// <remarks>Determines the weight of types that do not have a <c>WeightAttribute</c> set on
|
||||||
/// them, when calling <c>GetSortedValues</c>.</remarks>
|
/// them, when calling <c>GetSortedValues</c>.</remarks>
|
||||||
protected virtual int DefaultPluginWeight
|
protected virtual int DefaultPluginWeight
|
||||||
{
|
{
|
||||||
@@ -276,7 +281,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
/// Removes a type.
|
/// Removes a type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The type to remove.</param>
|
/// <param name="value">The type to remove.</param>
|
||||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||||
/// the type is not a valid type for the resolver.</exception>
|
/// the type is not a valid type for the resolver.</exception>
|
||||||
public virtual void RemoveType(Type value)
|
public virtual void RemoveType(Type value)
|
||||||
{
|
{
|
||||||
@@ -296,7 +301,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
/// Removes a type.
|
/// Removes a type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type to remove.</typeparam>
|
/// <typeparam name="T">The type to remove.</typeparam>
|
||||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||||
/// the type is not a valid type for the resolver.</exception>
|
/// the type is not a valid type for the resolver.</exception>
|
||||||
public void RemoveType<T>()
|
public void RemoveType<T>()
|
||||||
where T : TResolved
|
where T : TResolved
|
||||||
@@ -309,7 +314,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="types">The types to add.</param>
|
/// <param name="types">The types to add.</param>
|
||||||
/// <remarks>The types are appended at the end of the list.</remarks>
|
/// <remarks>The types are appended at the end of the list.</remarks>
|
||||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||||
/// a type is not a valid type for the resolver, or a type is already in the collection of types.</exception>
|
/// a type is not a valid type for the resolver, or a type is already in the collection of types.</exception>
|
||||||
protected void AddTypes(IEnumerable<Type> types)
|
protected void AddTypes(IEnumerable<Type> types)
|
||||||
{
|
{
|
||||||
@@ -336,7 +341,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The type to add.</param>
|
/// <param name="value">The type to add.</param>
|
||||||
/// <remarks>The type is appended at the end of the list.</remarks>
|
/// <remarks>The type is appended at the end of the list.</remarks>
|
||||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||||
public virtual void AddType(Type value)
|
public virtual void AddType(Type value)
|
||||||
{
|
{
|
||||||
@@ -362,7 +367,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type to add.</typeparam>
|
/// <typeparam name="T">The type to add.</typeparam>
|
||||||
/// <remarks>The type is appended at the end of the list.</remarks>
|
/// <remarks>The type is appended at the end of the list.</remarks>
|
||||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||||
public void AddType<T>()
|
public void AddType<T>()
|
||||||
where T : TResolved
|
where T : TResolved
|
||||||
@@ -404,7 +409,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">The zero-based index at which the type should be inserted.</param>
|
/// <param name="index">The zero-based index at which the type should be inserted.</param>
|
||||||
/// <param name="value">The type to insert.</param>
|
/// <param name="value">The type to insert.</param>
|
||||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
|
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
|
||||||
public virtual void InsertType(int index, Type value)
|
public virtual void InsertType(int index, Type value)
|
||||||
@@ -430,7 +435,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
/// Inserts a type at the beginning of the list.
|
/// Inserts a type at the beginning of the list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The type to insert.</param>
|
/// <param name="value">The type to insert.</param>
|
||||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||||
public virtual void InsertType(Type value)
|
public virtual void InsertType(Type value)
|
||||||
{
|
{
|
||||||
@@ -464,7 +469,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="existingType">The existing type before which to insert.</param>
|
/// <param name="existingType">The existing type before which to insert.</param>
|
||||||
/// <param name="value">The type to insert.</param>
|
/// <param name="value">The type to insert.</param>
|
||||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||||
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
|
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
|
||||||
/// or the new type is already in the collection of types.</exception>
|
/// or the new type is already in the collection of types.</exception>
|
||||||
public virtual void InsertTypeBefore(Type existingType, Type value)
|
public virtual void InsertTypeBefore(Type existingType, Type value)
|
||||||
@@ -498,7 +503,7 @@ namespace Umbraco.Core.ObjectResolution
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TExisting">The existing type before which to insert.</typeparam>
|
/// <typeparam name="TExisting">The existing type before which to insert.</typeparam>
|
||||||
/// <typeparam name="T">The type to insert.</typeparam>
|
/// <typeparam name="T">The type to insert.</typeparam>
|
||||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||||
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
|
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
|
||||||
/// or the new type is already in the collection of types.</exception>
|
/// or the new type is already in the collection of types.</exception>
|
||||||
public void InsertTypeBefore<TExisting, T>()
|
public void InsertTypeBefore<TExisting, T>()
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ namespace Umbraco.Core.Persistence.Factories
|
|||||||
content.PublishedVersionGuid = publishedDto == null
|
content.PublishedVersionGuid = publishedDto == null
|
||||||
? (dto.DocumentPublishedReadOnlyDto == null ? default(Guid) : dto.DocumentPublishedReadOnlyDto.VersionId)
|
? (dto.DocumentPublishedReadOnlyDto == null ? default(Guid) : dto.DocumentPublishedReadOnlyDto.VersionId)
|
||||||
: publishedDto.VersionId;
|
: publishedDto.VersionId;
|
||||||
|
content.PublishedDate = publishedDto == null
|
||||||
|
? (dto.DocumentPublishedReadOnlyDto == null ? default(DateTime) : dto.DocumentPublishedReadOnlyDto.VersionDate)
|
||||||
|
: publishedDto.VersionDate;
|
||||||
|
|
||||||
//on initial construction we don't want to have dirty properties tracked
|
//on initial construction we don't want to have dirty properties tracked
|
||||||
// http://issues.umbraco.org/issue/U4-1946
|
// http://issues.umbraco.org/issue/U4-1946
|
||||||
|
|||||||
@@ -513,11 +513,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||||
{
|
{
|
||||||
VersionId = dto.VersionId,
|
VersionId = dto.VersionId,
|
||||||
|
VersionDate = dto.UpdateDate,
|
||||||
Newest = true,
|
Newest = true,
|
||||||
NodeId = dto.NodeId,
|
NodeId = dto.NodeId,
|
||||||
Published = true
|
Published = true
|
||||||
};
|
};
|
||||||
((Content)entity).PublishedVersionGuid = dto.VersionId;
|
((Content) entity).PublishedVersionGuid = dto.VersionId;
|
||||||
|
((Content) entity).PublishedDate = dto.UpdateDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.ResetDirtyProperties();
|
entity.ResetDirtyProperties();
|
||||||
@@ -688,22 +690,26 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||||
{
|
{
|
||||||
VersionId = dto.VersionId,
|
VersionId = dto.VersionId,
|
||||||
|
VersionDate = dto.UpdateDate,
|
||||||
Newest = true,
|
Newest = true,
|
||||||
NodeId = dto.NodeId,
|
NodeId = dto.NodeId,
|
||||||
Published = true
|
Published = true
|
||||||
};
|
};
|
||||||
((Content)entity).PublishedVersionGuid = dto.VersionId;
|
((Content) entity).PublishedVersionGuid = dto.VersionId;
|
||||||
|
((Content) entity).PublishedDate = dto.UpdateDate;
|
||||||
}
|
}
|
||||||
else if (publishedStateChanged)
|
else if (publishedStateChanged)
|
||||||
{
|
{
|
||||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||||
{
|
{
|
||||||
VersionId = default(Guid),
|
VersionId = default (Guid),
|
||||||
|
VersionDate = default (DateTime),
|
||||||
Newest = false,
|
Newest = false,
|
||||||
NodeId = dto.NodeId,
|
NodeId = dto.NodeId,
|
||||||
Published = false
|
Published = false
|
||||||
};
|
};
|
||||||
((Content)entity).PublishedVersionGuid = default(Guid);
|
((Content) entity).PublishedVersionGuid = default(Guid);
|
||||||
|
((Content) entity).PublishedDate = default (DateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.ResetDirtyProperties();
|
entity.ResetDirtyProperties();
|
||||||
@@ -975,7 +981,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
|||||||
}
|
}
|
||||||
|
|
||||||
//order by update date DESC, if there is corrupted published flags we only want the latest!
|
//order by update date DESC, if there is corrupted published flags we only want the latest!
|
||||||
var publishedSql = new Sql(@"SELECT cmsDocument.nodeId, cmsDocument.published, cmsDocument.versionId, cmsDocument.newest
|
var publishedSql = new Sql(@"SELECT cmsDocument.nodeId, cmsDocument.published, cmsDocument.versionId, cmsDocument.updateDate, cmsDocument.newest
|
||||||
FROM cmsDocument INNER JOIN cmsContentVersion ON cmsContentVersion.VersionId = cmsDocument.versionId
|
FROM cmsDocument INNER JOIN cmsContentVersion ON cmsContentVersion.VersionId = cmsDocument.versionId
|
||||||
WHERE cmsDocument.published = 1 AND cmsDocument.nodeId IN
|
WHERE cmsDocument.published = 1 AND cmsDocument.nodeId IN
|
||||||
(" + parsedOriginalSql + @")
|
(" + parsedOriginalSql + @")
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
|
|
||||||
var translator = new SqlTranslator<PropertyType>(sqlClause, query);
|
var translator = new SqlTranslator<PropertyType>(sqlClause, query);
|
||||||
var sql = translator.Translate()
|
var sql = translator.Translate()
|
||||||
.OrderBy<PropertyTypeDto>(x => x.PropertyTypeGroupId, SqlSyntax);
|
//must be sorted this way for the relator to work
|
||||||
|
.OrderBy<PropertyTypeGroupDto>(x => x.Id, SqlSyntax);
|
||||||
|
|
||||||
var dtos = Database.Fetch<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new GroupPropertyTypeRelator().Map, sql);
|
var dtos = Database.Fetch<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new GroupPropertyTypeRelator().Map, sql);
|
||||||
|
|
||||||
@@ -468,7 +469,8 @@ AND umbracoNode.id <> @id",
|
|||||||
.LeftJoin<DataTypeDto>()
|
.LeftJoin<DataTypeDto>()
|
||||||
.On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.DataTypeId)
|
.On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.DataTypeId)
|
||||||
.Where<PropertyTypeGroupDto>(x => x.ContentTypeNodeId == id)
|
.Where<PropertyTypeGroupDto>(x => x.ContentTypeNodeId == id)
|
||||||
.OrderBy<PropertyTypeGroupDto>(x => x.Id);
|
//must be sorted this way for the relator to work
|
||||||
|
.OrderBy<PropertyTypeGroupDto>(x => x.Id, SqlSyntax);
|
||||||
|
|
||||||
var dtos = Database.Fetch<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new GroupPropertyTypeRelator().Map, sql);
|
var dtos = Database.Fetch<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new GroupPropertyTypeRelator().Map, sql);
|
||||||
|
|
||||||
@@ -1250,5 +1252,19 @@ WHERE cmsContentType." + aliasColumn + @" LIKE @pattern",
|
|||||||
while (aliases.Contains(test = alias + i)) i++;
|
while (aliases.Contains(test = alias + i)) i++;
|
||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contentPath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool HasContainerInPath(string contentPath)
|
||||||
|
{
|
||||||
|
var ids = contentPath.Split(',').Select(int.Parse);
|
||||||
|
var sql = new Sql(@"SELECT COUNT(*) FROM cmsContentType
|
||||||
|
INNER JOIN cmsContent ON cmsContentType.nodeId=cmsContent.contentType
|
||||||
|
WHERE cmsContent.nodeId IN (@ids) AND cmsContentType.isContainer=@isContainer", new { ids, isContainer = true });
|
||||||
|
return Database.ExecuteScalar<int>(sql) > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,47 +276,33 @@ AND umbracoNode.id <> @id",
|
|||||||
|
|
||||||
public PreValueCollection GetPreValuesCollectionByDataTypeId(int dataTypeId)
|
public PreValueCollection GetPreValuesCollectionByDataTypeId(int dataTypeId)
|
||||||
{
|
{
|
||||||
var cached = IsolatedCache.GetCacheItemsByKeySearch<PreValueCollection>(GetPrefixedCacheKey(dataTypeId));
|
var collection = GetCachedPreValueCollection(dataTypeId);
|
||||||
if (cached != null && cached.Any())
|
return collection;
|
||||||
{
|
|
||||||
//return from the cache, ensure it's a cloned result
|
|
||||||
return (PreValueCollection)cached.First().DeepClone();
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetAndCachePreValueCollection(dataTypeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string GetCacheKeyRegex(int preValueId)
|
|
||||||
{
|
|
||||||
return CacheKeys.DataTypePreValuesCacheKey + @"[-\d]+-([\d]*,)*" + preValueId + @"(?!\d)[,\d$]*";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a specific PreValue by its Id
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="preValueId">Id of the PreValue to retrieve the value from</param>
|
||||||
|
/// <returns>PreValue as a string</returns>
|
||||||
public string GetPreValueAsString(int preValueId)
|
public string GetPreValueAsString(int preValueId)
|
||||||
{
|
{
|
||||||
//We need to see if we can find the cached PreValueCollection based on the cache key above
|
var collections = IsolatedCache.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + "_");
|
||||||
|
|
||||||
var cached = IsolatedCache.GetCacheItemsByKeyExpression<PreValueCollection>(GetCacheKeyRegex(preValueId));
|
var preValue = collections.SelectMany(x => x.FormatAsDictionary().Values).FirstOrDefault(x => x.Id == preValueId);
|
||||||
if (cached != null && cached.Any())
|
if (preValue != null)
|
||||||
{
|
return preValue.Value;
|
||||||
//return from the cache
|
|
||||||
var collection = cached.First();
|
|
||||||
var preVal = collection.FormatAsDictionary().Single(x => x.Value.Id == preValueId);
|
|
||||||
return preVal.Value.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
//go and find the data type id for the pre val id passed in
|
var dto = Database.FirstOrDefault<DataTypePreValueDto>("WHERE id = @preValueId", new { preValueId });
|
||||||
|
|
||||||
var dto = Database.FirstOrDefault<DataTypePreValueDto>("WHERE id = @preValueId", new { preValueId = preValueId });
|
|
||||||
if (dto == null)
|
if (dto == null)
|
||||||
{
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
|
||||||
// go cache the collection
|
|
||||||
var preVals = GetAndCachePreValueCollection(dto.DataTypeNodeId);
|
|
||||||
|
|
||||||
//return the single value for this id
|
var collection = GetCachedPreValueCollection(dto.DataTypeNodeId);
|
||||||
var pv = preVals.FormatAsDictionary().Single(x => x.Value.Id == preValueId);
|
if (collection == null)
|
||||||
return pv.Value.Value;
|
return string.Empty;
|
||||||
|
|
||||||
|
preValue = collection.FormatAsDictionary().Values.FirstOrDefault(x => x.Id == preValueId);
|
||||||
|
return preValue == null ? string.Empty : preValue.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddOrUpdatePreValues(int dataTypeId, IDictionary<string, PreValue> values)
|
public void AddOrUpdatePreValues(int dataTypeId, IDictionary<string, PreValue> values)
|
||||||
@@ -441,40 +427,28 @@ AND umbracoNode.id <> @id",
|
|||||||
|
|
||||||
sortOrder++;
|
sortOrder++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetPrefixedCacheKey(int dataTypeId)
|
private static string GetPrefixedCacheKey(int dataTypeId)
|
||||||
{
|
{
|
||||||
return CacheKeys.DataTypePreValuesCacheKey + dataTypeId + "-";
|
return CacheKeys.DataTypePreValuesCacheKey + "_" + dataTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PreValueCollection GetAndCachePreValueCollection(int dataTypeId)
|
private PreValueCollection GetCachedPreValueCollection(int datetypeId)
|
||||||
{
|
{
|
||||||
//go get the data
|
var key = GetPrefixedCacheKey(datetypeId);
|
||||||
var dtos = Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = dataTypeId });
|
return IsolatedCache.GetCacheItem<PreValueCollection>(key, () =>
|
||||||
var list = dtos.Select(x => new Tuple<PreValue, string, int>(new PreValue(x.Id, x.Value, x.SortOrder), x.Alias, x.SortOrder)).ToList();
|
{
|
||||||
var collection = PreValueConverter.ConvertToPreValuesCollection(list);
|
var dtos = Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = datetypeId });
|
||||||
|
var list = dtos.Select(x => new Tuple<PreValue, string, int>(new PreValue(x.Id, x.Value, x.SortOrder), x.Alias, x.SortOrder)).ToList();
|
||||||
//now create the cache key, this needs to include all pre-value ids so that we can use this cached item in the GetPreValuesAsString method
|
var collection = PreValueConverter.ConvertToPreValuesCollection(list);
|
||||||
//the key will be: "UmbracoPreValDATATYPEID-CSVOFPREVALIDS
|
return collection;
|
||||||
|
}, TimeSpan.FromMinutes(20), isSliding: true);
|
||||||
var key = GetPrefixedCacheKey(dataTypeId)
|
|
||||||
+ string.Join(",", collection.FormatAsDictionary().Select(x => x.Value.Id).ToArray());
|
|
||||||
|
|
||||||
//store into cache
|
|
||||||
IsolatedCache.InsertCacheItem(key, () => collection,
|
|
||||||
//30 mins
|
|
||||||
new TimeSpan(0, 0, 30),
|
|
||||||
//sliding is true
|
|
||||||
true);
|
|
||||||
|
|
||||||
return collection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EnsureUniqueNodeName(string nodeName, int id = 0)
|
private string EnsureUniqueNodeName(string nodeName, int id = 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
var sql = new Sql();
|
var sql = new Sql();
|
||||||
sql.Select("*")
|
sql.Select("*")
|
||||||
@@ -575,7 +549,7 @@ AND umbracoNode.id <> @id",
|
|||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT
|
//NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT
|
||||||
// in reality there is no need to check the uniqueness of this alias because the only way that this code executes is
|
// in reality there is no need to check the uniqueness of this alias because the only way that this code executes is
|
||||||
// based on an IDictionary<string, PreValue> dictionary being passed to this repository and a dictionary
|
// based on an IDictionary<string, PreValue> dictionary being passed to this repository and a dictionary
|
||||||
// must have unique aliases by definition, so there is no need for this additional check
|
// must have unique aliases by definition, so there is no need for this additional check
|
||||||
|
|
||||||
@@ -595,10 +569,10 @@ AND umbracoNode.id <> @id",
|
|||||||
{
|
{
|
||||||
throw new InvalidOperationException("Cannot update a pre value for a data type that has no identity");
|
throw new InvalidOperationException("Cannot update a pre value for a data type that has no identity");
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT
|
//NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT
|
||||||
// this causes issues when sorting the pre-values (http://issues.umbraco.org/issue/U4-5670) but in reality
|
// this causes issues when sorting the pre-values (http://issues.umbraco.org/issue/U4-5670) but in reality
|
||||||
// there is no need to check the uniqueness of this alias because the only way that this code executes is
|
// there is no need to check the uniqueness of this alias because the only way that this code executes is
|
||||||
// based on an IDictionary<string, PreValue> dictionary being passed to this repository and a dictionary
|
// based on an IDictionary<string, PreValue> dictionary being passed to this repository and a dictionary
|
||||||
// must have unique aliases by definition, so there is no need for this additional check
|
// must have unique aliases by definition, so there is no need for this additional check
|
||||||
|
|
||||||
@@ -613,7 +587,7 @@ AND umbracoNode.id <> @id",
|
|||||||
Database.Update(dto);
|
Database.Update(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class PreValueConverter
|
internal static class PreValueConverter
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
{
|
{
|
||||||
var sql = GetBaseQuery(false)
|
var sql = GetBaseQuery(false)
|
||||||
.Where(GetBaseWhereClause(), new { Id = id })
|
.Where(GetBaseWhereClause(), new { Id = id })
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||||
|
|
||||||
var dto = Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql).FirstOrDefault();
|
var dto = Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql).FirstOrDefault();
|
||||||
@@ -64,6 +65,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
sql.Where("cmsDictionary.pk in (@ids)", new { ids = ids });
|
sql.Where("cmsDictionary.pk in (@ids)", new { ids = ids });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
|
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||||
|
|
||||||
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
|
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
|
||||||
.Select(dto => ConvertFromDto(dto));
|
.Select(dto => ConvertFromDto(dto));
|
||||||
}
|
}
|
||||||
@@ -73,6 +77,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
var sqlClause = GetBaseQuery(false);
|
var sqlClause = GetBaseQuery(false);
|
||||||
var translator = new SqlTranslator<IDictionaryItem>(sqlClause, query);
|
var translator = new SqlTranslator<IDictionaryItem>(sqlClause, query);
|
||||||
var sql = translator.Translate();
|
var sql = translator.Translate();
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||||
|
|
||||||
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
|
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
|
||||||
@@ -94,9 +99,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
sql.Select("*")
|
sql.Select("*")
|
||||||
.From<DictionaryDto>(SqlSyntax)
|
.From<DictionaryDto>(SqlSyntax)
|
||||||
.LeftJoin<LanguageTextDto>(SqlSyntax)
|
.LeftJoin<LanguageTextDto>(SqlSyntax)
|
||||||
.On<DictionaryDto, LanguageTextDto>(SqlSyntax, left => left.UniqueId, right => right.UniqueId);
|
.On<DictionaryDto, LanguageTextDto>(SqlSyntax, left => left.UniqueId, right => right.UniqueId);
|
||||||
}
|
}
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
@@ -270,6 +275,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
|
|
||||||
var translator = new SqlTranslator<IDictionaryItem>(sqlClause, Query<IDictionaryItem>.Builder);
|
var translator = new SqlTranslator<IDictionaryItem>(sqlClause, Query<IDictionaryItem>.Builder);
|
||||||
var sql = translator.Translate();
|
var sql = translator.Translate();
|
||||||
|
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||||
|
|
||||||
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
|
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
|
||||||
@@ -297,6 +304,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
|
|
||||||
protected override IEnumerable<DictionaryDto> PerformFetch(Sql sql)
|
protected override IEnumerable<DictionaryDto> PerformFetch(Sql sql)
|
||||||
{
|
{
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
|
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||||
|
|
||||||
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql);
|
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,6 +359,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
|
|
||||||
protected override IEnumerable<DictionaryDto> PerformFetch(Sql sql)
|
protected override IEnumerable<DictionaryDto> PerformFetch(Sql sql)
|
||||||
{
|
{
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
|
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||||
|
|
||||||
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql);
|
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
{
|
{
|
||||||
public interface IContentTypeRepository : IContentTypeCompositionRepository<IContentType>
|
public interface IContentTypeRepository : IContentTypeCompositionRepository<IContentType>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contentPath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool HasContainerInPath(string contentPath);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all entities of the specified <see cref="PropertyType"/> query
|
/// Gets all entities of the specified <see cref="PropertyType"/> query
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
|
|
||||||
private IMacro GetBySql(Sql sql)
|
private IMacro GetBySql(Sql sql)
|
||||||
{
|
{
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
|
sql.OrderBy<MacroDto>(x => x.Id, SqlSyntax);
|
||||||
|
|
||||||
var macroDto = Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql).FirstOrDefault();
|
var macroDto = Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql).FirstOrDefault();
|
||||||
if (macroDto == null)
|
if (macroDto == null)
|
||||||
return null;
|
return null;
|
||||||
@@ -68,7 +71,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
|
|
||||||
private IEnumerable<IMacro> GetAllNoIds()
|
private IEnumerable<IMacro> GetAllNoIds()
|
||||||
{
|
{
|
||||||
var sql = GetBaseQuery(false);
|
var sql = GetBaseQuery(false)
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
|
.OrderBy<MacroDto>(x => x.Id, SqlSyntax);
|
||||||
|
|
||||||
return ConvertFromDtos(Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql))
|
return ConvertFromDtos(Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql))
|
||||||
.ToArray();// we don't want to re-iterate again!
|
.ToArray();// we don't want to re-iterate again!
|
||||||
}
|
}
|
||||||
@@ -92,6 +98,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
var translator = new SqlTranslator<IMacro>(sqlClause, query);
|
var translator = new SqlTranslator<IMacro>(sqlClause, query);
|
||||||
var sql = translator.Translate();
|
var sql = translator.Translate();
|
||||||
|
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
|
sql.OrderBy<MacroDto>(x => x.Id, SqlSyntax);
|
||||||
|
|
||||||
var dtos = Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql);
|
var dtos = Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql);
|
||||||
|
|
||||||
foreach (var dto in dtos)
|
foreach (var dto in dtos)
|
||||||
@@ -114,13 +123,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Sql GetBaseQuery()
|
private Sql GetBaseQuery()
|
||||||
{
|
{
|
||||||
var sql = new Sql();
|
var sql = new Sql();
|
||||||
sql.Select("*")
|
sql.Select("*")
|
||||||
.From<MacroDto>()
|
.From<MacroDto>()
|
||||||
.LeftJoin<MacroPropertyDto>()
|
.LeftJoin<MacroPropertyDto>()
|
||||||
.On<MacroDto, MacroPropertyDto>(left => left.Id, right => right.Macro);
|
.On<MacroDto, MacroPropertyDto>(left => left.Id, right => right.Macro);
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
var statement = string.Join(" OR ", ids.Select(x => string.Format("umbracoNode.id='{0}'", x)));
|
var statement = string.Join(" OR ", ids.Select(x => string.Format("umbracoNode.id='{0}'", x)));
|
||||||
sql.Where(statement);
|
sql.Where(statement);
|
||||||
}
|
}
|
||||||
sql.OrderByDescending<NodeDto>(x => x.NodeId, SqlSyntax);
|
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
|
sql.OrderBy<MemberTypeReadOnlyDto>(x => x.UniqueId, SqlSyntax);
|
||||||
|
|
||||||
var dtos =
|
var dtos =
|
||||||
Database.Fetch<MemberTypeReadOnlyDto, PropertyTypeReadOnlyDto, PropertyTypeGroupReadOnlyDto, MemberTypeReadOnlyDto>(
|
Database.Fetch<MemberTypeReadOnlyDto, PropertyTypeReadOnlyDto, PropertyTypeGroupReadOnlyDto, MemberTypeReadOnlyDto>(
|
||||||
@@ -62,7 +64,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
var subquery = translator.Translate();
|
var subquery = translator.Translate();
|
||||||
var sql = GetBaseQuery(false)
|
var sql = GetBaseQuery(false)
|
||||||
.Append(new Sql("WHERE umbracoNode.id IN (" + subquery.SQL + ")", subquery.Arguments))
|
.Append(new Sql("WHERE umbracoNode.id IN (" + subquery.SQL + ")", subquery.Arguments))
|
||||||
.OrderBy<NodeDto>(x => x.SortOrder, SqlSyntax);
|
//must be sorted this way for the relator to work
|
||||||
|
.OrderBy<MemberTypeReadOnlyDto>(x => x.UniqueId, SqlSyntax);
|
||||||
|
|
||||||
var dtos =
|
var dtos =
|
||||||
Database.Fetch<MemberTypeReadOnlyDto, PropertyTypeReadOnlyDto, PropertyTypeGroupReadOnlyDto, MemberTypeReadOnlyDto>(
|
Database.Fetch<MemberTypeReadOnlyDto, PropertyTypeReadOnlyDto, PropertyTypeGroupReadOnlyDto, MemberTypeReadOnlyDto>(
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
}
|
}
|
||||||
|
|
||||||
var factory = new PublicAccessEntryFactory();
|
var factory = new PublicAccessEntryFactory();
|
||||||
|
|
||||||
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
|
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
|
||||||
|
sql.OrderBy<AccessDto>(dto => dto.Id, SqlSyntax);
|
||||||
|
|
||||||
var dtos = Database.Fetch<AccessDto, AccessRuleDto, AccessDto>(new AccessRulesRelator().Map, sql);
|
var dtos = Database.Fetch<AccessDto, AccessRuleDto, AccessDto>(new AccessRulesRelator().Map, sql);
|
||||||
return dtos.Select(factory.BuildEntity);
|
return dtos.Select(factory.BuildEntity);
|
||||||
}
|
}
|
||||||
@@ -52,7 +55,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
var sql = translator.Translate();
|
var sql = translator.Translate();
|
||||||
|
|
||||||
var factory = new PublicAccessEntryFactory();
|
var factory = new PublicAccessEntryFactory();
|
||||||
|
|
||||||
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
|
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
|
||||||
|
sql.OrderBy<AccessDto>(dto => dto.Id, SqlSyntax);
|
||||||
|
|
||||||
var dtos = Database.Fetch<AccessDto, AccessRuleDto, AccessDto>(new AccessRulesRelator().Map, sql);
|
var dtos = Database.Fetch<AccessDto, AccessRuleDto, AccessDto>(new AccessRulesRelator().Map, sql);
|
||||||
return dtos.Select(factory.BuildEntity);
|
return dtos.Select(factory.BuildEntity);
|
||||||
}
|
}
|
||||||
@@ -63,9 +69,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
sql.Select("*")
|
sql.Select("*")
|
||||||
.From<AccessDto>(SqlSyntax)
|
.From<AccessDto>(SqlSyntax)
|
||||||
.LeftJoin<AccessRuleDto>(SqlSyntax)
|
.LeftJoin<AccessRuleDto>(SqlSyntax)
|
||||||
.On<AccessDto, AccessRuleDto>(SqlSyntax, left => left.Id, right => right.AccessId)
|
.On<AccessDto, AccessRuleDto>(SqlSyntax, left => left.Id, right => right.AccessId);
|
||||||
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
|
|
||||||
.OrderBy<AccessDto>(dto => dto.Id, SqlSyntax);
|
|
||||||
|
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
{
|
{
|
||||||
var sql = GetBaseQuery(false);
|
var sql = GetBaseQuery(false);
|
||||||
sql.Where(GetBaseWhereClause(), new { Id = id });
|
sql.Where(GetBaseWhereClause(), new { Id = id });
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
|
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
|
||||||
|
|
||||||
var dto = Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql).FirstOrDefault();
|
var dto = Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql).FirstOrDefault();
|
||||||
|
|
||||||
@@ -60,7 +62,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
{
|
{
|
||||||
sql.Where("umbracoUser.id in (@ids)", new {ids = ids});
|
sql.Where("umbracoUser.id in (@ids)", new {ids = ids});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
|
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
|
||||||
|
|
||||||
return ConvertFromDtos(Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql))
|
return ConvertFromDtos(Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql))
|
||||||
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
|
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
|
||||||
}
|
}
|
||||||
@@ -71,6 +76,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
var translator = new SqlTranslator<IUser>(sqlClause, query);
|
var translator = new SqlTranslator<IUser>(sqlClause, query);
|
||||||
var sql = translator.Translate();
|
var sql = translator.Translate();
|
||||||
|
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
|
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
|
||||||
|
|
||||||
var dtos = Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql)
|
var dtos = Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql)
|
||||||
.DistinctBy(x => x.Id);
|
.DistinctBy(x => x.Id);
|
||||||
|
|
||||||
@@ -96,13 +104,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Sql GetBaseQuery(string columns)
|
private Sql GetBaseQuery(string columns)
|
||||||
{
|
{
|
||||||
var sql = new Sql();
|
var sql = new Sql();
|
||||||
sql.Select(columns)
|
sql.Select(columns)
|
||||||
.From<UserDto>()
|
.From<UserDto>()
|
||||||
.LeftJoin<User2AppDto>()
|
.LeftJoin<User2AppDto>()
|
||||||
.On<UserDto, User2AppDto>(left => left.Id, right => right.UserId);
|
.On<UserDto, User2AppDto>(left => left.Id, right => right.UserId);
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,6 +308,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
var innerSql = GetBaseQuery("umbracoUser.id");
|
var innerSql = GetBaseQuery("umbracoUser.id");
|
||||||
innerSql.Where("umbracoUser2app.app = " + SqlSyntax.GetQuotedValue(sectionAlias));
|
innerSql.Where("umbracoUser2app.app = " + SqlSyntax.GetQuotedValue(sectionAlias));
|
||||||
sql.Where(string.Format("umbracoUser.id IN ({0})", innerSql.SQL));
|
sql.Where(string.Format("umbracoUser.id IN ({0})", innerSql.SQL));
|
||||||
|
//must be sorted this way for the relator to work
|
||||||
|
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
|
||||||
|
|
||||||
return ConvertFromDtos(Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql));
|
return ConvertFromDtos(Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,12 @@ namespace Umbraco.Core.Persistence
|
|||||||
_cacheHelper.IsolatedRuntimeCache.CacheFactory = type =>
|
_cacheHelper.IsolatedRuntimeCache.CacheFactory = type =>
|
||||||
{
|
{
|
||||||
var cache = origFactory(type);
|
var cache = origFactory(type);
|
||||||
return new DeepCloneRuntimeCacheProvider(cache);
|
|
||||||
|
//if the result is already a DeepCloneRuntimeCacheProvider then return it, otherwise
|
||||||
|
//wrap the result with a DeepCloneRuntimeCacheProvider
|
||||||
|
return cache is DeepCloneRuntimeCacheProvider
|
||||||
|
? cache
|
||||||
|
: new DeepCloneRuntimeCacheProvider(cache);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,5 +47,9 @@ using System.Security.Permissions;
|
|||||||
[assembly: InternalsVisibleTo("Umbraco.Deploy.UI")]
|
[assembly: InternalsVisibleTo("Umbraco.Deploy.UI")]
|
||||||
[assembly: InternalsVisibleTo("Umbraco.Deploy.Cloud")]
|
[assembly: InternalsVisibleTo("Umbraco.Deploy.Cloud")]
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleTo("Umbraco.Forms.Core")]
|
||||||
|
[assembly: InternalsVisibleTo("Umbraco.Forms.Core.Providers")]
|
||||||
|
[assembly: InternalsVisibleTo("Umbraco.Forms.Web")]
|
||||||
|
|
||||||
//allow this to be mocked in our unit tests
|
//allow this to be mocked in our unit tests
|
||||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Umbraco.Core.Configuration;
|
||||||
|
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||||
using Umbraco.Core.Logging;
|
using Umbraco.Core.Logging;
|
||||||
using Umbraco.Core.Manifest;
|
using Umbraco.Core.Manifest;
|
||||||
using Umbraco.Core.ObjectResolution;
|
using Umbraco.Core.ObjectResolution;
|
||||||
@@ -17,11 +19,13 @@ namespace Umbraco.Core.PropertyEditors
|
|||||||
internal class ParameterEditorResolver : LazyManyObjectsResolverBase<ParameterEditorResolver, IParameterEditor>
|
internal class ParameterEditorResolver : LazyManyObjectsResolverBase<ParameterEditorResolver, IParameterEditor>
|
||||||
{
|
{
|
||||||
private readonly ManifestBuilder _builder;
|
private readonly ManifestBuilder _builder;
|
||||||
|
private readonly IContentSection _contentSection;
|
||||||
|
|
||||||
public ParameterEditorResolver(IServiceProvider serviceProvider, ILogger logger, Func<IEnumerable<Type>> typeListProducerList, ManifestBuilder builder)
|
public ParameterEditorResolver(IServiceProvider serviceProvider, ILogger logger, Func<IEnumerable<Type>> typeListProducerList, ManifestBuilder builder)
|
||||||
: base(serviceProvider, logger, typeListProducerList, ObjectLifetimeScope.Application)
|
: base(serviceProvider, logger, typeListProducerList, ObjectLifetimeScope.Application)
|
||||||
{
|
{
|
||||||
_builder = builder;
|
_builder = builder;
|
||||||
|
_contentSection = UmbracoConfig.For.UmbracoSettings().Content;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -31,20 +35,27 @@ namespace Umbraco.Core.PropertyEditors
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
//This will by default include all property editors and parameter editors but we need to filter this
|
// all property editors and parameter editors
|
||||||
//list to ensure that none of the property editors that do not have the IsParameterEditor flag set to true
|
// except property editors where !IsParameterEditor
|
||||||
//are filtered.
|
var values = Values
|
||||||
var filtered = Values.Select(x => x as PropertyEditor)
|
.Where(x => x is PropertyEditor == false || ((PropertyEditor) x).IsParameterEditor);
|
||||||
.WhereNotNull()
|
|
||||||
.Where(x => x.IsParameterEditor == false);
|
// union all manifest parameter editors
|
||||||
|
values = values
|
||||||
return Values
|
.Union(_builder.ParameterEditors);
|
||||||
//exclude the non parameter editor c# property editors
|
|
||||||
.Except(filtered)
|
// union all manifest property editors where IsParameterEditor
|
||||||
//include the manifest parameter editors
|
values = values
|
||||||
.Union(_builder.ParameterEditors)
|
|
||||||
//include the manifest prop editors that are parameter editors
|
|
||||||
.Union(_builder.PropertyEditors.Where(x => x.IsParameterEditor));
|
.Union(_builder.PropertyEditors.Where(x => x.IsParameterEditor));
|
||||||
|
|
||||||
|
if (_contentSection.ShowDeprecatedPropertyEditors == false)
|
||||||
|
{
|
||||||
|
// except deprecated property editors
|
||||||
|
values = values
|
||||||
|
.Where(x => x is PropertyEditor == false || ((PropertyEditor) x).IsDeprecated == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Umbraco.Core.Configuration;
|
using Umbraco.Core.Configuration;
|
||||||
using Umbraco.Core.Models;
|
using Umbraco.Core.Models;
|
||||||
@@ -88,13 +89,26 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
private bool IsRangeDataType(int dataTypeId)
|
private bool IsRangeDataType(int dataTypeId)
|
||||||
{
|
{
|
||||||
// ** This must be cached (U4-8862) **
|
// GetPreValuesCollectionByDataTypeId is cached at repository level;
|
||||||
var enableRange =
|
// still, the collection is deep-cloned so this is kinda expensive,
|
||||||
_dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId)
|
// better to cache here + trigger refresh in DataTypeCacheRefresher
|
||||||
.PreValuesAsDictionary.FirstOrDefault(
|
|
||||||
x => string.Equals(x.Key, "enableRange", StringComparison.InvariantCultureIgnoreCase)).Value;
|
|
||||||
|
|
||||||
return enableRange != null && enableRange.Value.TryConvertTo<bool>().Result;
|
return Storages.GetOrAdd(dataTypeId, id =>
|
||||||
|
{
|
||||||
|
var preValue = _dataTypeService.GetPreValuesCollectionByDataTypeId(id)
|
||||||
|
.PreValuesAsDictionary
|
||||||
|
.FirstOrDefault(x => string.Equals(x.Key, "enableRange", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
.Value;
|
||||||
|
|
||||||
|
return preValue != null && preValue.Value.TryConvertTo<bool>().Result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly ConcurrentDictionary<int, bool> Storages = new ConcurrentDictionary<int, bool>();
|
||||||
|
|
||||||
|
internal static void ClearCaches()
|
||||||
|
{
|
||||||
|
Storages.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Umbraco.Core.Configuration;
|
using Umbraco.Core.Configuration;
|
||||||
|
using Umbraco.Core.Events;
|
||||||
|
using Umbraco.Core.Models;
|
||||||
using Umbraco.Core.Models.PublishedContent;
|
using Umbraco.Core.Models.PublishedContent;
|
||||||
using Umbraco.Core.Services;
|
using Umbraco.Core.Services;
|
||||||
|
|
||||||
@@ -74,18 +77,26 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
private bool JsonStorageType(int dataTypeId)
|
private bool JsonStorageType(int dataTypeId)
|
||||||
{
|
{
|
||||||
// ** This must be cached (U4-8862) **
|
// GetPreValuesCollectionByDataTypeId is cached at repository level;
|
||||||
var storageType =
|
// still, the collection is deep-cloned so this is kinda expensive,
|
||||||
_dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId)
|
// better to cache here + trigger refresh in DataTypeCacheRefresher
|
||||||
.PreValuesAsDictionary.FirstOrDefault(
|
|
||||||
x => string.Equals(x.Key, "storageType", StringComparison.InvariantCultureIgnoreCase)).Value;
|
|
||||||
|
|
||||||
if (storageType != null && storageType.Value.InvariantEquals("Json"))
|
return Storages.GetOrAdd(dataTypeId, id =>
|
||||||
{
|
{
|
||||||
return true;
|
var preValue = _dataTypeService.GetPreValuesCollectionByDataTypeId(id)
|
||||||
}
|
.PreValuesAsDictionary
|
||||||
|
.FirstOrDefault(x => string.Equals(x.Key, "storageType", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
.Value;
|
||||||
|
|
||||||
return false;
|
return preValue != null && preValue.Value.InvariantEquals("json");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly ConcurrentDictionary<int, bool> Storages = new ConcurrentDictionary<int, bool>();
|
||||||
|
|
||||||
|
internal static void ClearCaches()
|
||||||
|
{
|
||||||
|
Storages.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Umbraco.Core.Events;
|
using Umbraco.Core.Events;
|
||||||
using Umbraco.Core.Models;
|
using Umbraco.Core.Models;
|
||||||
using Umbraco.Core.Services;
|
using Umbraco.Core.Services;
|
||||||
@@ -12,7 +13,8 @@ namespace Umbraco.Core.Publishing
|
|||||||
{
|
{
|
||||||
public PublishStatus(IContent content, PublishStatusType statusType, EventMessages eventMessages)
|
public PublishStatus(IContent content, PublishStatusType statusType, EventMessages eventMessages)
|
||||||
: base(content, statusType, eventMessages)
|
: base(content, statusType, eventMessages)
|
||||||
{
|
{
|
||||||
|
InvalidProperties = Enumerable.Empty<Property>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -20,8 +22,7 @@ namespace Umbraco.Core.Publishing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public PublishStatus(IContent content, EventMessages eventMessages)
|
public PublishStatus(IContent content, EventMessages eventMessages)
|
||||||
: this(content, PublishStatusType.Success, eventMessages)
|
: this(content, PublishStatusType.Success, eventMessages)
|
||||||
{
|
{ }
|
||||||
}
|
|
||||||
|
|
||||||
public IContent ContentItem
|
public IContent ContentItem
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace Umbraco.Core.Publishing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="uow"></param>
|
/// <param name="uow"></param>
|
||||||
/// <param name="content"><see cref="IContent"/> to publish</param>
|
/// <param name="content"><see cref="IContent"/> to publish</param>
|
||||||
/// <param name="userId">Id of the User issueing the publish operation</param>
|
/// <param name="userId">Id of the User issueing the publish operation</param>
|
||||||
Attempt<PublishStatus> IPublishingStrategy2.Publish(IScopeUnitOfWork uow, IContent content, int userId)
|
Attempt<PublishStatus> IPublishingStrategy2.Publish(IScopeUnitOfWork uow, IContent content, int userId)
|
||||||
{
|
{
|
||||||
var evtMsgs = _eventMessagesFactory.Get();
|
var evtMsgs = _eventMessagesFactory.Get();
|
||||||
@@ -124,26 +124,26 @@ namespace Umbraco.Core.Publishing
|
|||||||
/// By default this is set to true which means that it will publish any content item in the list that is completely unpublished and
|
/// By default this is set to true which means that it will publish any content item in the list that is completely unpublished and
|
||||||
/// not visible on the front-end. If set to false, this will only publish content that is live on the front-end but has new versions
|
/// not visible on the front-end. If set to false, this will only publish content that is live on the front-end but has new versions
|
||||||
/// that have yet to be published.
|
/// that have yet to be published.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
///
|
///
|
||||||
/// This method becomes complex once we start to be able to cancel events or stop publishing a content item in any way because if a
|
/// This method becomes complex once we start to be able to cancel events or stop publishing a content item in any way because if a
|
||||||
/// content item is not published then it's children shouldn't be published either. This rule will apply for the following conditions:
|
/// content item is not published then it's children shouldn't be published either. This rule will apply for the following conditions:
|
||||||
/// * If a document fails to be published, do not proceed to publish it's children if:
|
/// * If a document fails to be published, do not proceed to publish it's children if:
|
||||||
/// ** The document does not have a publish version
|
/// ** The document does not have a publish version
|
||||||
/// ** The document does have a published version but the includeUnpublishedDocuments = false
|
/// ** The document does have a published version but the includeUnpublishedDocuments = false
|
||||||
///
|
///
|
||||||
/// In order to do this, we will order the content by level and begin by publishing each item at that level, then proceed to the next
|
/// In order to do this, we will order the content by level and begin by publishing each item at that level, then proceed to the next
|
||||||
/// level and so on. If we detect that the above rule applies when the document publishing is cancelled we'll add it to the list of
|
/// level and so on. If we detect that the above rule applies when the document publishing is cancelled we'll add it to the list of
|
||||||
/// parentsIdsCancelled so that it's children don't get published.
|
/// parentsIdsCancelled so that it's children don't get published.
|
||||||
///
|
///
|
||||||
/// Its important to note that all 'root' documents included in the list *will* be published regardless of the rules mentioned
|
/// Its important to note that all 'root' documents included in the list *will* be published regardless of the rules mentioned
|
||||||
/// above (unless it is invalid)!! By 'root' documents we are referring to documents in the list with the minimum value for their 'level'.
|
/// above (unless it is invalid)!! By 'root' documents we are referring to documents in the list with the minimum value for their 'level'.
|
||||||
/// In most cases the 'root' documents will only be one document since under normal circumstance we only publish one document and
|
/// In most cases the 'root' documents will only be one document since under normal circumstance we only publish one document and
|
||||||
/// its children. The reason we have to do this is because if a user is publishing a document and it's children, it is implied that
|
/// its children. The reason we have to do this is because if a user is publishing a document and it's children, it is implied that
|
||||||
/// the user definitely wants to publish it even if it has never been published before.
|
/// the user definitely wants to publish it even if it has never been published before.
|
||||||
///
|
///
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
IEnumerable<Attempt<PublishStatus>> IPublishingStrategy2.PublishWithChildren(IScopeUnitOfWork uow,
|
IEnumerable<Attempt<PublishStatus>> IPublishingStrategy2.PublishWithChildren(IScopeUnitOfWork uow,
|
||||||
IEnumerable<IContent> content, int userId, bool includeUnpublishedDocuments)
|
IEnumerable<IContent> content, int userId, bool includeUnpublishedDocuments)
|
||||||
@@ -157,7 +157,7 @@ namespace Umbraco.Core.Publishing
|
|||||||
|
|
||||||
//group by levels and iterate over the sorted ascending level.
|
//group by levels and iterate over the sorted ascending level.
|
||||||
//TODO: This will cause all queries to execute, they will not be lazy but I'm not really sure being lazy actually made
|
//TODO: This will cause all queries to execute, they will not be lazy but I'm not really sure being lazy actually made
|
||||||
// much difference because we iterate over them all anyways?? Morten?
|
// much difference because we iterate over them all anyways?? Morten?
|
||||||
// Because we're grouping I think this will execute all the queries anyways so need to fetch it all first.
|
// Because we're grouping I think this will execute all the queries anyways so need to fetch it all first.
|
||||||
var fetchedContent = content.ToArray();
|
var fetchedContent = content.ToArray();
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ namespace Umbraco.Core.Publishing
|
|||||||
var levelGroups = fetchedContent.GroupBy(x => x.Level);
|
var levelGroups = fetchedContent.GroupBy(x => x.Level);
|
||||||
foreach (var level in levelGroups.OrderBy(x => x.Key))
|
foreach (var level in levelGroups.OrderBy(x => x.Key))
|
||||||
{
|
{
|
||||||
//set the first level flag, used to ensure that all documents at the first level will
|
//set the first level flag, used to ensure that all documents at the first level will
|
||||||
//be published regardless of the rules mentioned in the remarks.
|
//be published regardless of the rules mentioned in the remarks.
|
||||||
if (!firstLevel.HasValue)
|
if (!firstLevel.HasValue)
|
||||||
{
|
{
|
||||||
@@ -224,7 +224,10 @@ namespace Umbraco.Core.Publishing
|
|||||||
_logger.Info<PublishingStrategy>(
|
_logger.Info<PublishingStrategy>(
|
||||||
string.Format("Content '{0}' with Id '{1}' will not be published because some of it's content is not passing validation rules.",
|
string.Format("Content '{0}' with Id '{1}' will not be published because some of it's content is not passing validation rules.",
|
||||||
item.Name, item.Id));
|
item.Name, item.Id));
|
||||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedContentInvalid, evtMsgs)));
|
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedContentInvalid, evtMsgs)
|
||||||
|
{
|
||||||
|
InvalidProperties = ((ContentBase)item).LastInvalidProperties
|
||||||
|
}));
|
||||||
|
|
||||||
//Does this document apply to our rule to cancel it's children being published?
|
//Does this document apply to our rule to cancel it's children being published?
|
||||||
CheckCancellingOfChildPublishing(item, parentsIdsCancelled, includeUnpublishedDocuments);
|
CheckCancellingOfChildPublishing(item, parentsIdsCancelled, includeUnpublishedDocuments);
|
||||||
@@ -296,11 +299,11 @@ namespace Umbraco.Core.Publishing
|
|||||||
/// <param name="includeUnpublishedDocuments"></param>
|
/// <param name="includeUnpublishedDocuments"></param>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// See remarks on method: PublishWithChildrenInternal
|
/// See remarks on method: PublishWithChildrenInternal
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
private void CheckCancellingOfChildPublishing(IContent content, List<int> parentsIdsCancelled, bool includeUnpublishedDocuments)
|
private void CheckCancellingOfChildPublishing(IContent content, List<int> parentsIdsCancelled, bool includeUnpublishedDocuments)
|
||||||
{
|
{
|
||||||
//Does this document apply to our rule to cancel it's children being published?
|
//Does this document apply to our rule to cancel it's children being published?
|
||||||
//TODO: We're going back to the service layer here... not sure how to avoid this? And this will add extra overhead to
|
//TODO: We're going back to the service layer here... not sure how to avoid this? And this will add extra overhead to
|
||||||
// any document that fails to publish...
|
// any document that fails to publish...
|
||||||
var hasPublishedVersion = ApplicationContext.Current.Services.ContentService.HasPublishedVersion(content.Id);
|
var hasPublishedVersion = ApplicationContext.Current.Services.ContentService.HasPublishedVersion(content.Id);
|
||||||
|
|
||||||
|
|||||||
@@ -326,7 +326,8 @@ namespace Umbraco.Core.Security
|
|||||||
|
|
||||||
//Special case to allow changing password without validating existing credentials
|
//Special case to allow changing password without validating existing credentials
|
||||||
//This is used during installation only
|
//This is used during installation only
|
||||||
if (AllowManuallyChangingPassword == false && ApplicationContext.Current.IsConfigured == false && oldPassword == "default")
|
if (AllowManuallyChangingPassword == false && ApplicationContext.Current != null
|
||||||
|
&& ApplicationContext.Current.IsConfigured == false && oldPassword == "default")
|
||||||
{
|
{
|
||||||
return PerformChangePassword(username, oldPassword, newPassword);
|
return PerformChangePassword(username, oldPassword, newPassword);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -358,9 +358,8 @@ namespace Umbraco.Core.Services
|
|||||||
{
|
{
|
||||||
var applicationAlias = (string)addElement.Attribute("application");
|
var applicationAlias = (string)addElement.Attribute("application");
|
||||||
var type = (string)addElement.Attribute("type");
|
var type = (string)addElement.Attribute("type");
|
||||||
var assembly = (string)addElement.Attribute("assembly");
|
|
||||||
|
var clrType = ApplicationTree.TryGetType(type);
|
||||||
var clrType = Type.GetType(type);
|
|
||||||
if (clrType == null)
|
if (clrType == null)
|
||||||
{
|
{
|
||||||
_logger.Warn<ApplicationTreeService>("The tree definition: " + addElement.ToString() + " could not be resolved to a .Net object type");
|
_logger.Warn<ApplicationTreeService>("The tree definition: " + addElement.ToString() + " could not be resolved to a .Net object type");
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Umbraco.Core.Logging;
|
|||||||
using Umbraco.Core.Models;
|
using Umbraco.Core.Models;
|
||||||
using Umbraco.Core.Models.EntityBase;
|
using Umbraco.Core.Models.EntityBase;
|
||||||
using Umbraco.Core.Persistence;
|
using Umbraco.Core.Persistence;
|
||||||
|
using Umbraco.Core.Persistence.Repositories;
|
||||||
using Umbraco.Core.Persistence.UnitOfWork;
|
using Umbraco.Core.Persistence.UnitOfWork;
|
||||||
|
|
||||||
namespace Umbraco.Core.Services
|
namespace Umbraco.Core.Services
|
||||||
@@ -74,5 +75,20 @@ namespace Umbraco.Core.Services
|
|||||||
{
|
{
|
||||||
return Enumerable.Empty<IContentTypeBase>();
|
return Enumerable.Empty<IContentTypeBase>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contentPath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool HasContainerInPath(string contentPath)
|
||||||
|
{
|
||||||
|
using (var uow = UowProvider.GetUnitOfWork())
|
||||||
|
{
|
||||||
|
// can use same repo for both content and media
|
||||||
|
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
|
||||||
|
return repository.HasContainerInPath(contentPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ namespace Umbraco.Core.Services
|
|||||||
{
|
{
|
||||||
var result = _runtimeCache.GetCacheItem<int?>(CacheKeys.IdToKeyCacheKey + key, () =>
|
var result = _runtimeCache.GetCacheItem<int?>(CacheKeys.IdToKeyCacheKey + key, () =>
|
||||||
{
|
{
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
switch (umbracoObjectType)
|
switch (umbracoObjectType)
|
||||||
{
|
{
|
||||||
@@ -92,7 +92,6 @@ namespace Umbraco.Core.Services
|
|||||||
case UmbracoObjectTypes.Member:
|
case UmbracoObjectTypes.Member:
|
||||||
case UmbracoObjectTypes.DataType:
|
case UmbracoObjectTypes.DataType:
|
||||||
case UmbracoObjectTypes.DocumentTypeContainer:
|
case UmbracoObjectTypes.DocumentTypeContainer:
|
||||||
uow.Commit();
|
|
||||||
return uow.Database.ExecuteScalar<int?>(new Sql().Select("id").From<NodeDto>().Where<NodeDto>(dto => dto.UniqueId == key));
|
return uow.Database.ExecuteScalar<int?>(new Sql().Select("id").From<NodeDto>().Where<NodeDto>(dto => dto.UniqueId == key));
|
||||||
case UmbracoObjectTypes.RecycleBin:
|
case UmbracoObjectTypes.RecycleBin:
|
||||||
case UmbracoObjectTypes.Stylesheet:
|
case UmbracoObjectTypes.Stylesheet:
|
||||||
@@ -119,7 +118,7 @@ namespace Umbraco.Core.Services
|
|||||||
{
|
{
|
||||||
var result = _runtimeCache.GetCacheItem<Guid?>(CacheKeys.KeyToIdCacheKey + id, () =>
|
var result = _runtimeCache.GetCacheItem<Guid?>(CacheKeys.KeyToIdCacheKey + id, () =>
|
||||||
{
|
{
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
switch (umbracoObjectType)
|
switch (umbracoObjectType)
|
||||||
{
|
{
|
||||||
@@ -131,7 +130,6 @@ namespace Umbraco.Core.Services
|
|||||||
case UmbracoObjectTypes.DocumentType:
|
case UmbracoObjectTypes.DocumentType:
|
||||||
case UmbracoObjectTypes.Member:
|
case UmbracoObjectTypes.Member:
|
||||||
case UmbracoObjectTypes.DataType:
|
case UmbracoObjectTypes.DataType:
|
||||||
uow.Commit();
|
|
||||||
return uow.Database.ExecuteScalar<Guid?>(new Sql().Select("uniqueID").From<NodeDto>().Where<NodeDto>(dto => dto.NodeId == id));
|
return uow.Database.ExecuteScalar<Guid?>(new Sql().Select("uniqueID").From<NodeDto>().Where<NodeDto>(dto => dto.NodeId == id));
|
||||||
case UmbracoObjectTypes.RecycleBin:
|
case UmbracoObjectTypes.RecycleBin:
|
||||||
case UmbracoObjectTypes.Stylesheet:
|
case UmbracoObjectTypes.Stylesheet:
|
||||||
@@ -185,11 +183,10 @@ namespace Umbraco.Core.Services
|
|||||||
{
|
{
|
||||||
if (loadBaseType)
|
if (loadBaseType)
|
||||||
{
|
{
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var ret = repository.Get(id);
|
var ret = repository.Get(id);
|
||||||
uow.Commit();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,11 +204,10 @@ namespace Umbraco.Core.Services
|
|||||||
if (loadBaseType)
|
if (loadBaseType)
|
||||||
{
|
{
|
||||||
var objectTypeId = umbracoObjectType.GetGuid();
|
var objectTypeId = umbracoObjectType.GetGuid();
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var ret = repository.GetByKey(key, objectTypeId);
|
var ret = repository.GetByKey(key, objectTypeId);
|
||||||
uow.Commit();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,11 +237,10 @@ namespace Umbraco.Core.Services
|
|||||||
if (loadBaseType)
|
if (loadBaseType)
|
||||||
{
|
{
|
||||||
var objectTypeId = umbracoObjectType.GetGuid();
|
var objectTypeId = umbracoObjectType.GetGuid();
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var ret = repository.Get(id, objectTypeId);
|
var ret = repository.Get(id, objectTypeId);
|
||||||
uow.Commit();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,11 +271,10 @@ namespace Umbraco.Core.Services
|
|||||||
{
|
{
|
||||||
if (loadBaseType)
|
if (loadBaseType)
|
||||||
{
|
{
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var ret = repository.Get(id);
|
var ret = repository.Get(id);
|
||||||
uow.Commit();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -303,7 +297,7 @@ namespace Umbraco.Core.Services
|
|||||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||||
public virtual IUmbracoEntity GetParent(int id)
|
public virtual IUmbracoEntity GetParent(int id)
|
||||||
{
|
{
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var entity = repository.Get(id);
|
var entity = repository.Get(id);
|
||||||
@@ -311,7 +305,6 @@ namespace Umbraco.Core.Services
|
|||||||
if (entity.ParentId == -1 || entity.ParentId == -20 || entity.ParentId == -21)
|
if (entity.ParentId == -1 || entity.ParentId == -20 || entity.ParentId == -21)
|
||||||
return null;
|
return null;
|
||||||
var ret = repository.Get(entity.ParentId);
|
var ret = repository.Get(entity.ParentId);
|
||||||
uow.Commit();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,7 +317,7 @@ namespace Umbraco.Core.Services
|
|||||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||||
public virtual IUmbracoEntity GetParent(int id, UmbracoObjectTypes umbracoObjectType)
|
public virtual IUmbracoEntity GetParent(int id, UmbracoObjectTypes umbracoObjectType)
|
||||||
{
|
{
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var entity = repository.Get(id);
|
var entity = repository.Get(id);
|
||||||
@@ -334,7 +327,6 @@ namespace Umbraco.Core.Services
|
|||||||
var objectTypeId = umbracoObjectType.GetGuid();
|
var objectTypeId = umbracoObjectType.GetGuid();
|
||||||
|
|
||||||
var ret = repository.Get(entity.ParentId, objectTypeId);
|
var ret = repository.Get(entity.ParentId, objectTypeId);
|
||||||
uow.Commit();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,13 +338,12 @@ namespace Umbraco.Core.Services
|
|||||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||||
public virtual IEnumerable<IUmbracoEntity> GetChildren(int parentId)
|
public virtual IEnumerable<IUmbracoEntity> GetChildren(int parentId)
|
||||||
{
|
{
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId);
|
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId);
|
||||||
|
|
||||||
var contents = repository.GetByQuery(query);
|
var contents = repository.GetByQuery(query);
|
||||||
uow.Commit();
|
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,13 +357,12 @@ namespace Umbraco.Core.Services
|
|||||||
public virtual IEnumerable<IUmbracoEntity> GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType)
|
public virtual IEnumerable<IUmbracoEntity> GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType)
|
||||||
{
|
{
|
||||||
var objectTypeId = umbracoObjectType.GetGuid();
|
var objectTypeId = umbracoObjectType.GetGuid();
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId);
|
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId);
|
||||||
|
|
||||||
var contents = repository.GetByQuery(query, objectTypeId);
|
var contents = repository.GetByQuery(query, objectTypeId);
|
||||||
uow.Commit();
|
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,7 +383,7 @@ namespace Umbraco.Core.Services
|
|||||||
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "")
|
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "")
|
||||||
{
|
{
|
||||||
var objectTypeId = umbracoObjectType.GetGuid();
|
var objectTypeId = umbracoObjectType.GetGuid();
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId && x.Trashed == false);
|
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId && x.Trashed == false);
|
||||||
@@ -405,7 +395,6 @@ namespace Umbraco.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
||||||
uow.Commit();
|
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,7 +415,7 @@ namespace Umbraco.Core.Services
|
|||||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "")
|
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "")
|
||||||
{
|
{
|
||||||
var objectTypeId = umbracoObjectType.GetGuid();
|
var objectTypeId = umbracoObjectType.GetGuid();
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
|
|
||||||
@@ -442,7 +431,6 @@ namespace Umbraco.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
||||||
uow.Commit();
|
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,7 +451,7 @@ namespace Umbraco.Core.Services
|
|||||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "", bool includeTrashed = true)
|
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "", bool includeTrashed = true)
|
||||||
{
|
{
|
||||||
var objectTypeId = umbracoObjectType.GetGuid();
|
var objectTypeId = umbracoObjectType.GetGuid();
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
|
|
||||||
@@ -481,7 +469,6 @@ namespace Umbraco.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
||||||
uow.Commit();
|
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,7 +480,7 @@ namespace Umbraco.Core.Services
|
|||||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||||
public virtual IEnumerable<IUmbracoEntity> GetDescendents(int id)
|
public virtual IEnumerable<IUmbracoEntity> GetDescendents(int id)
|
||||||
{
|
{
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var entity = repository.Get(id);
|
var entity = repository.Get(id);
|
||||||
@@ -501,7 +488,6 @@ namespace Umbraco.Core.Services
|
|||||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.Path.StartsWith(pathMatch) && x.Id != id);
|
var query = Query<IUmbracoEntity>.Builder.Where(x => x.Path.StartsWith(pathMatch) && x.Id != id);
|
||||||
|
|
||||||
var entities = repository.GetByQuery(query);
|
var entities = repository.GetByQuery(query);
|
||||||
uow.Commit();
|
|
||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -515,14 +501,13 @@ namespace Umbraco.Core.Services
|
|||||||
public virtual IEnumerable<IUmbracoEntity> GetDescendents(int id, UmbracoObjectTypes umbracoObjectType)
|
public virtual IEnumerable<IUmbracoEntity> GetDescendents(int id, UmbracoObjectTypes umbracoObjectType)
|
||||||
{
|
{
|
||||||
var objectTypeId = umbracoObjectType.GetGuid();
|
var objectTypeId = umbracoObjectType.GetGuid();
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var entity = repository.Get(id);
|
var entity = repository.Get(id);
|
||||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.Path.StartsWith(entity.Path) && x.Id != id);
|
var query = Query<IUmbracoEntity>.Builder.Where(x => x.Path.StartsWith(entity.Path) && x.Id != id);
|
||||||
|
|
||||||
var entities = repository.GetByQuery(query, objectTypeId);
|
var entities = repository.GetByQuery(query, objectTypeId);
|
||||||
uow.Commit();
|
|
||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -541,11 +526,10 @@ namespace Umbraco.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
var objectTypeId = umbracoObjectType.GetGuid();
|
var objectTypeId = umbracoObjectType.GetGuid();
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var entities = repository.GetByQuery(_rootEntityQuery, objectTypeId);
|
var entities = repository.GetByQuery(_rootEntityQuery, objectTypeId);
|
||||||
uow.Commit();
|
|
||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -585,11 +569,10 @@ namespace Umbraco.Core.Services
|
|||||||
});
|
});
|
||||||
|
|
||||||
var objectTypeId = umbracoObjectType.GetGuid();
|
var objectTypeId = umbracoObjectType.GetGuid();
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var ret = repository.GetAll(objectTypeId, ids);
|
var ret = repository.GetAll(objectTypeId, ids);
|
||||||
uow.Commit();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -605,11 +588,10 @@ namespace Umbraco.Core.Services
|
|||||||
});
|
});
|
||||||
|
|
||||||
var objectTypeId = umbracoObjectType.GetGuid();
|
var objectTypeId = umbracoObjectType.GetGuid();
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var ret = repository.GetAll(objectTypeId, keys);
|
var ret = repository.GetAll(objectTypeId, keys);
|
||||||
uow.Commit();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -631,11 +613,10 @@ namespace Umbraco.Core.Services
|
|||||||
("The passed in type is not supported");
|
("The passed in type is not supported");
|
||||||
});
|
});
|
||||||
|
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var ret = repository.GetAll(objectTypeId, ids);
|
var ret = repository.GetAll(objectTypeId, ids);
|
||||||
uow.Commit();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -721,22 +702,20 @@ namespace Umbraco.Core.Services
|
|||||||
|
|
||||||
public bool Exists(Guid key)
|
public bool Exists(Guid key)
|
||||||
{
|
{
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var exists = repository.Exists(key);
|
var exists = repository.Exists(key);
|
||||||
uow.Commit();
|
|
||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Exists(int id)
|
public bool Exists(int id)
|
||||||
{
|
{
|
||||||
using (var uow = UowProvider.GetUnitOfWork())
|
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||||
{
|
{
|
||||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||||
var exists = repository.Exists(id);
|
var exists = repository.Exists(id);
|
||||||
uow.Commit();
|
|
||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -868,7 +868,7 @@ namespace Umbraco.Core.Services
|
|||||||
if (partialView == null)
|
if (partialView == null)
|
||||||
{
|
{
|
||||||
uow.Commit();
|
uow.Commit();
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uow.Events.DispatchCancelable(DeletingPartialView, this, new DeleteEventArgs<IPartialView>(partialView)))
|
if (uow.Events.DispatchCancelable(DeletingPartialView, this, new DeleteEventArgs<IPartialView>(partialView)))
|
||||||
|
|||||||
@@ -11,6 +11,13 @@ namespace Umbraco.Core.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IContentTypeService : IService
|
public interface IContentTypeService : IService
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contentPath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool HasContainerInPath(string contentPath);
|
||||||
|
|
||||||
int CountContentTypes();
|
int CountContentTypes();
|
||||||
int CountMediaTypes();
|
int CountMediaTypes();
|
||||||
|
|
||||||
|
|||||||
@@ -199,6 +199,7 @@
|
|||||||
<Compile Include="Configuration\BaseRest\ExtensionElementCollection.cs" />
|
<Compile Include="Configuration\BaseRest\ExtensionElementCollection.cs" />
|
||||||
<Compile Include="Configuration\BaseRest\MethodElement.cs" />
|
<Compile Include="Configuration\BaseRest\MethodElement.cs" />
|
||||||
<Compile Include="Configuration\ContentXmlStorage.cs" />
|
<Compile Include="Configuration\ContentXmlStorage.cs" />
|
||||||
|
<Compile Include="Configuration\CoreDebug.cs" />
|
||||||
<Compile Include="Configuration\Dashboard\AccessElement.cs" />
|
<Compile Include="Configuration\Dashboard\AccessElement.cs" />
|
||||||
<Compile Include="Configuration\Dashboard\AccessItem.cs" />
|
<Compile Include="Configuration\Dashboard\AccessItem.cs" />
|
||||||
<Compile Include="Configuration\Dashboard\AccessType.cs" />
|
<Compile Include="Configuration\Dashboard\AccessType.cs" />
|
||||||
@@ -219,7 +220,6 @@
|
|||||||
<Compile Include="Configuration\Dashboard\SectionElement.cs" />
|
<Compile Include="Configuration\Dashboard\SectionElement.cs" />
|
||||||
<Compile Include="Configuration\Dashboard\TabCollection.cs" />
|
<Compile Include="Configuration\Dashboard\TabCollection.cs" />
|
||||||
<Compile Include="Configuration\Dashboard\TabElement.cs" />
|
<Compile Include="Configuration\Dashboard\TabElement.cs" />
|
||||||
<Compile Include="Configuration\CoreDebug.cs" />
|
|
||||||
<Compile Include="Configuration\FileSystemProviderElement.cs" />
|
<Compile Include="Configuration\FileSystemProviderElement.cs" />
|
||||||
<Compile Include="Configuration\FileSystemProviderElementCollection.cs" />
|
<Compile Include="Configuration\FileSystemProviderElementCollection.cs" />
|
||||||
<Compile Include="Configuration\FileSystemProvidersSection.cs" />
|
<Compile Include="Configuration\FileSystemProvidersSection.cs" />
|
||||||
@@ -323,6 +323,7 @@
|
|||||||
<Compile Include="DateTimeExtensions.cs" />
|
<Compile Include="DateTimeExtensions.cs" />
|
||||||
<Compile Include="DecimalExtensions.cs" />
|
<Compile Include="DecimalExtensions.cs" />
|
||||||
<Compile Include="DelegateExtensions.cs" />
|
<Compile Include="DelegateExtensions.cs" />
|
||||||
|
<Compile Include="Diagnostics\MiniDump.cs" />
|
||||||
<Compile Include="Deploy\ArtifactBase.cs" />
|
<Compile Include="Deploy\ArtifactBase.cs" />
|
||||||
<Compile Include="Deploy\ArtifactDependency.cs" />
|
<Compile Include="Deploy\ArtifactDependency.cs" />
|
||||||
<Compile Include="Deploy\ArtifactDependencyCollection.cs" />
|
<Compile Include="Deploy\ArtifactDependencyCollection.cs" />
|
||||||
|
|||||||
@@ -805,101 +805,6 @@ namespace Umbraco.Tests.IO
|
|||||||
Assert.AreEqual(3, sfsFiles.Length);
|
Assert.AreEqual(3, sfsFiles.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
[Ignore("Does not work on all environments, Directory.GetFiles is broken.")]
|
|
||||||
public void ShadowGetFilesUsingWildcardAndSingleCharacterFilter()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var path = IOHelper.MapPath("FileSysTests");
|
|
||||||
Directory.CreateDirectory(path);
|
|
||||||
Directory.CreateDirectory(path + "/ShadowTests");
|
|
||||||
Directory.CreateDirectory(path + "/ShadowSystem");
|
|
||||||
|
|
||||||
var fs = new PhysicalFileSystem(path + "/ShadowTests/", "ignore");
|
|
||||||
var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "ignore");
|
|
||||||
var ss = new ShadowFileSystem(fs, sfs);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
File.WriteAllText(path + "/ShadowTests/f2.txt", "foo");
|
|
||||||
File.WriteAllText(path + "/ShadowTests/f2.doc", "foo");
|
|
||||||
File.WriteAllText(path + "/ShadowTests/f2.docx", "foo");
|
|
||||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
|
||||||
ss.AddFile("f1.txt", ms);
|
|
||||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
|
||||||
ss.AddFile("f1.doc", ms);
|
|
||||||
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
|
|
||||||
ss.AddFile("f1.docx", ms);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
// ensure we get 6 files from the shadow
|
|
||||||
var getFiles = ss.GetFiles(string.Empty);
|
|
||||||
Assert.AreEqual(6, getFiles.Count());
|
|
||||||
var getFilesWithWildcardSinglecharFilter = ss.GetFiles(string.Empty, "*.d?c");
|
|
||||||
|
|
||||||
Assert.AreEqual(4, getFilesWithWildcardSinglecharFilter.Count());
|
|
||||||
var getFilesWithWildcardSinglecharFilter2 = ss.GetFiles(string.Empty, "*.d?cx");
|
|
||||||
Assert.AreEqual(2, getFilesWithWildcardSinglecharFilter2.Count());
|
|
||||||
|
|
||||||
var fsFiles = fs.GetFiles(string.Empty).ToArray();
|
|
||||||
Assert.AreEqual(3, fsFiles.Length);
|
|
||||||
var sfsFiles = sfs.GetFiles(string.Empty).ToArray();
|
|
||||||
Assert.AreEqual(3, sfsFiles.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
[Ignore("Does not work on all environments, Directory.GetFiles is broken.")]
|
|
||||||
public void ShadowFileSystemFilterIsAsBrokenAsRealFileSystemFilter()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var path = IOHelper.MapPath("FileSysTests");
|
|
||||||
Directory.CreateDirectory(path);
|
|
||||||
Directory.CreateDirectory(path + "/filter");
|
|
||||||
// create files on disk and create a "fake" list of files to verify filters against
|
|
||||||
File.WriteAllText(path + "/filter/f1.txt", "foo");
|
|
||||||
File.WriteAllText(path + "/filter/f1.doc", "foo");
|
|
||||||
File.WriteAllText(path + "/filter/f1.docx", "foo");
|
|
||||||
var files = new string[]
|
|
||||||
{
|
|
||||||
"f1.txt",
|
|
||||||
"f1.doc",
|
|
||||||
"f1.docx",
|
|
||||||
};
|
|
||||||
var filter1 = "";
|
|
||||||
var filter2 = "*";
|
|
||||||
var filter3 = "*.doc";
|
|
||||||
var filter4 = "*.d?c";
|
|
||||||
var filter5 = "f1.doc";
|
|
||||||
var filter6 = "f1.d?c";
|
|
||||||
var filter7 = "**.d?c";
|
|
||||||
var filter8 = "f*.doc";
|
|
||||||
|
|
||||||
// Act & Assert
|
|
||||||
var result1Disk = Directory.GetFiles(path + "/filter/", filter1).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
|
||||||
var result1Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter1))).OrderBy(x => x).ToArray();
|
|
||||||
Assert.AreEqual(result1Disk, result1Fake);
|
|
||||||
var result2Disk = Directory.GetFiles(path + "/filter/", filter2).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
|
||||||
var result2Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter2))).OrderBy(x => x).ToArray();
|
|
||||||
Assert.AreEqual(result2Disk, result2Fake);
|
|
||||||
var result3Disk = Directory.GetFiles(path + "/filter/", filter3).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
|
||||||
var result3Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter3))).OrderBy(x => x).ToArray();
|
|
||||||
Assert.AreEqual(result3Disk, result3Fake);
|
|
||||||
var result4Disk = Directory.GetFiles(path + "/filter/", filter4).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
|
||||||
var result4Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter4))).OrderBy(x => x).ToArray();
|
|
||||||
Assert.AreEqual(result4Disk, result4Fake);
|
|
||||||
var result5Disk = Directory.GetFiles(path + "/filter/", filter5).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
|
||||||
var result5Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter5))).OrderBy(x => x).ToArray();
|
|
||||||
Assert.AreEqual(result5Disk, result5Fake);
|
|
||||||
var result6Disk = Directory.GetFiles(path + "/filter/", filter6).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
|
||||||
var result6Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter6))).OrderBy(x => x).ToArray();
|
|
||||||
Assert.AreEqual(result6Disk, result6Fake);
|
|
||||||
var result7Disk = Directory.GetFiles(path + "/filter/", filter7).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
|
||||||
var result7Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter7))).OrderBy(x => x).ToArray();
|
|
||||||
Assert.AreEqual(result7Disk, result7Fake);
|
|
||||||
var result8Disk = Directory.GetFiles(path + "/filter/", filter8).Select(Path.GetFileName).OrderBy(x => x).ToArray();
|
|
||||||
var result8Fake = files.Where(x => ShadowFileSystem.FilterByRegex(x, ShadowFileSystem.FilterToRegex(filter8))).OrderBy(x => x).ToArray();
|
|
||||||
Assert.AreEqual(result8Disk, result8Fake);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the full paths of the files on the disk.
|
/// Returns the full paths of the files on the disk.
|
||||||
/// Note that this will be the *actual* path of the file, meaning a file existing on the initialized FS
|
/// Note that this will be the *actual* path of the file, meaning a file existing on the initialized FS
|
||||||
|
|||||||
@@ -46,23 +46,6 @@ namespace Umbraco.Tests.Persistence.Repositories
|
|||||||
return new EntityContainerRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of<ILogger>(), SqlSyntax, Constants.ObjectTypes.DataTypeContainerGuid);
|
return new EntityContainerRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of<ILogger>(), SqlSyntax, Constants.ObjectTypes.DataTypeContainerGuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("UmbracoPreVal87-21,3,48", 3, true)]
|
|
||||||
[TestCase("UmbracoPreVal87-21,33,48", 3, false)]
|
|
||||||
[TestCase("UmbracoPreVal87-21,33,48", 33, true)]
|
|
||||||
[TestCase("UmbracoPreVal87-21,3,48", 33, false)]
|
|
||||||
[TestCase("UmbracoPreVal87-21,3,48", 21, true)]
|
|
||||||
[TestCase("UmbracoPreVal87-21,3,48", 48, true)]
|
|
||||||
[TestCase("UmbracoPreVal87-22,33,48", 2, false)]
|
|
||||||
[TestCase("UmbracoPreVal87-22,33,48", 22, true)]
|
|
||||||
[TestCase("UmbracoPreVal87-22,33,44", 4, false)]
|
|
||||||
[TestCase("UmbracoPreVal87-22,33,44", 44, true)]
|
|
||||||
[TestCase("UmbracoPreVal87-22,333,44", 33, false)]
|
|
||||||
[TestCase("UmbracoPreVal87-22,333,44", 333, true)]
|
|
||||||
public void Pre_Value_Cache_Key_Tests(string cacheKey, int preValueId, bool outcome)
|
|
||||||
{
|
|
||||||
Assert.AreEqual(outcome, Regex.IsMatch(cacheKey, DataTypeDefinitionRepository.GetCacheKeyRegex(preValueId)));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Can_Move()
|
public void Can_Move()
|
||||||
{
|
{
|
||||||
@@ -537,7 +520,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
|||||||
}
|
}
|
||||||
|
|
||||||
var cached = cache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>().Result
|
var cached = cache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>().Result
|
||||||
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-");
|
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + "_" + dtd.Id);
|
||||||
|
|
||||||
Assert.IsNotNull(cached);
|
Assert.IsNotNull(cached);
|
||||||
Assert.AreEqual(1, cached.Count());
|
Assert.AreEqual(1, cached.Count());
|
||||||
@@ -581,7 +564,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
|||||||
}
|
}
|
||||||
|
|
||||||
var cached = cache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>().Result
|
var cached = cache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>().Result
|
||||||
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-");
|
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + "_" + dtd.Id);
|
||||||
|
|
||||||
Assert.IsNotNull(cached);
|
Assert.IsNotNull(cached);
|
||||||
Assert.AreEqual(1, cached.Count());
|
Assert.AreEqual(1, cached.Count());
|
||||||
|
|||||||
@@ -237,6 +237,14 @@ namespace Umbraco.Tests.Persistence.Repositories
|
|||||||
Assert.AreEqual("test-path-1.js", script.Path);
|
Assert.AreEqual("test-path-1.js", script.Path);
|
||||||
Assert.AreEqual("/scripts/test-path-1.js", script.VirtualPath);
|
Assert.AreEqual("/scripts/test-path-1.js", script.VirtualPath);
|
||||||
|
|
||||||
|
//ensure you can prefix the same path as the root path name
|
||||||
|
script = new Script("scripts/path-2/test-path-2.js") { Content = "// script" };
|
||||||
|
repository.AddOrUpdate(script);
|
||||||
|
unitOfWork.Commit();
|
||||||
|
Assert.IsTrue(_fileSystem.FileExists("scripts/path-2/test-path-2.js"));
|
||||||
|
Assert.AreEqual("scripts\\path-2\\test-path-2.js", script.Path);
|
||||||
|
Assert.AreEqual("/scripts/scripts/path-2/test-path-2.js", script.VirtualPath);
|
||||||
|
|
||||||
script = new Script("path-2/test-path-2.js") { Content = "// script" };
|
script = new Script("path-2/test-path-2.js") { Content = "// script" };
|
||||||
repository.AddOrUpdate(script);
|
repository.AddOrUpdate(script);
|
||||||
unitOfWork.Commit();
|
unitOfWork.Commit();
|
||||||
|
|||||||
@@ -58,8 +58,8 @@
|
|||||||
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
|
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Examine, Version=0.1.81.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Examine.0.1.81\lib\net45\Examine.dll</HintPath>
|
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<packages>
|
<packages>
|
||||||
<package id="AspNetWebApi.SelfHost" version="4.0.20710.0" targetFramework="net45" />
|
<package id="AspNetWebApi.SelfHost" version="4.0.20710.0" targetFramework="net45" />
|
||||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||||
<package id="Examine" version="0.1.81" targetFramework="net45" />
|
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||||
<package id="log4net" version="2.0.5" targetFramework="net45" />
|
<package id="log4net" version="2.0.5" targetFramework="net45" />
|
||||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
|
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
|
||||||
|
|||||||
@@ -191,27 +191,34 @@ tinymce.PluginManager.add('umbracolink', function(editor) {
|
|||||||
callback: function (data) {
|
callback: function (data) {
|
||||||
if (data) {
|
if (data) {
|
||||||
var href = data.url;
|
var href = data.url;
|
||||||
|
// We want to use the Udi. If it is set, we use it, else fallback to id, and finally to null
|
||||||
|
var hasUdi = data.udi ? true : false;
|
||||||
|
var id = hasUdi ? data.udi : (data.id ? data.id : null);
|
||||||
|
|
||||||
|
//Create a json obj used to create the attributes for the tag
|
||||||
|
function createElemAttributes() {
|
||||||
|
var a = {
|
||||||
|
href: href,
|
||||||
|
title: data.name,
|
||||||
|
target: data.target ? data.target : null,
|
||||||
|
rel: data.rel ? data.rel : null
|
||||||
|
};
|
||||||
|
if (hasUdi) {
|
||||||
|
a["data-udi"] = data.udi;
|
||||||
|
}
|
||||||
|
else if (data.id) {
|
||||||
|
a["data-id"] = data.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function insertLink() {
|
function insertLink() {
|
||||||
if (anchorElm) {
|
if (anchorElm) {
|
||||||
dom.setAttribs(anchorElm, {
|
dom.setAttribs(anchorElm, createElemAttributes());
|
||||||
href: href,
|
|
||||||
title: data.name,
|
|
||||||
target: data.target ? data.target : null,
|
|
||||||
rel: data.rel ? data.rel : null,
|
|
||||||
'data-id': data.id ? data.id : null
|
|
||||||
});
|
|
||||||
|
|
||||||
selection.select(anchorElm);
|
selection.select(anchorElm);
|
||||||
editor.execCommand('mceEndTyping');
|
editor.execCommand('mceEndTyping');
|
||||||
} else {
|
} else {
|
||||||
editor.execCommand('mceInsertLink', false, {
|
editor.execCommand('mceInsertLink', false, createElemAttributes());
|
||||||
href: href,
|
|
||||||
title: data.name,
|
|
||||||
target: data.target ? data.target : null,
|
|
||||||
rel: data.rel ? data.rel : null,
|
|
||||||
'data-id': data.id ? data.id : null
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,15 +228,11 @@ tinymce.PluginManager.add('umbracolink', function(editor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if we have an id, it must be a locallink:id, aslong as the isMedia flag is not set
|
//if we have an id, it must be a locallink:id, aslong as the isMedia flag is not set
|
||||||
if(data.id && (angular.isUndefined(data.isMedia) || !data.isMedia)){
|
if (id && (angular.isUndefined(data.isMedia) || !data.isMedia)){
|
||||||
if (target.udi) {
|
|
||||||
href = "/{localLink:" + target.udi + "}";
|
href = "/{localLink:" + id + "}";
|
||||||
}
|
|
||||||
else {
|
insertLink();
|
||||||
//This shouldn't happen! but just in case we'll leave this here
|
|
||||||
href = "/{localLink:" + target.id + "}";
|
|
||||||
}
|
|
||||||
insertLink();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -163,13 +163,13 @@ angular.module('umbraco.directives')
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ignore clicks on dialog from old dialog service
|
// ignore clicks on dialog from old dialog service
|
||||||
var oldDialog = $(el).parents("#old-dialog-service");
|
var oldDialog = $(event.target).parents("#old-dialog-service");
|
||||||
if (oldDialog.length === 1) {
|
if (oldDialog.length === 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore clicks in tinyMCE dropdown(floatpanel)
|
// ignore clicks in tinyMCE dropdown(floatpanel)
|
||||||
var floatpanel = $(el).parents(".mce-floatpanel");
|
var floatpanel = $(event.target).closest(".mce-floatpanel");
|
||||||
if (floatpanel.length === 1) {
|
if (floatpanel.length === 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -108,8 +108,10 @@ angular.module("umbraco.directives")
|
|||||||
$image.load(function(){
|
$image.load(function(){
|
||||||
$timeout(function(){
|
$timeout(function(){
|
||||||
setDimensions();
|
setDimensions();
|
||||||
scope.loaded = true;
|
scope.loaded = true;
|
||||||
scope.onImageLoaded();
|
if (scope.onImageLoaded) {
|
||||||
|
scope.onImageLoaded();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -17,6 +17,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
|||||||
hideheader: '@',
|
hideheader: '@',
|
||||||
cachekey: '@',
|
cachekey: '@',
|
||||||
isdialog: '@',
|
isdialog: '@',
|
||||||
|
onlyinitialized: '@',
|
||||||
//Custom query string arguments to pass in to the tree as a string, example: "startnodeid=123&something=value"
|
//Custom query string arguments to pass in to the tree as a string, example: "startnodeid=123&something=value"
|
||||||
customtreeparams: '@',
|
customtreeparams: '@',
|
||||||
eventhandler: '=',
|
eventhandler: '=',
|
||||||
@@ -252,7 +253,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
|||||||
deleteAnimations = false;
|
deleteAnimations = false;
|
||||||
|
|
||||||
//default args
|
//default args
|
||||||
var args = { section: scope.section, tree: scope.treealias, cacheKey: scope.cachekey, isDialog: scope.isdialog ? scope.isdialog : false };
|
var args = { section: scope.section, tree: scope.treealias, cacheKey: scope.cachekey, isDialog: scope.isdialog ? scope.isdialog : false, onlyinitialized: scope.onlyinitialized };
|
||||||
|
|
||||||
//add the extra query string params if specified
|
//add the extra query string params if specified
|
||||||
if (scope.customtreeparams) {
|
if (scope.customtreeparams) {
|
||||||
@@ -305,7 +306,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
|||||||
scope.selectEnabledNodeClass = function (node) {
|
scope.selectEnabledNodeClass = function (node) {
|
||||||
return node ?
|
return node ?
|
||||||
node.selected ?
|
node.selected ?
|
||||||
'icon umb-tree-icon sprTree icon-check blue temporary' :
|
'icon umb-tree-icon sprTree icon-check green temporary' :
|
||||||
'' :
|
'' :
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|||||||
+2
-1
@@ -87,7 +87,8 @@ Use this directive to generate a list of folders presented as a flexbox grid.
|
|||||||
|
|
||||||
scope.clickFolder = function(folder, $event, $index) {
|
scope.clickFolder = function(folder, $event, $index) {
|
||||||
if(scope.onClick) {
|
if(scope.onClick) {
|
||||||
scope.onClick(folder, $event, $index);
|
scope.onClick(folder, $event, $index);
|
||||||
|
$event.stopPropagation();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -247,6 +247,7 @@ Use this directive to generate a thumbnail grid of media items.
|
|||||||
scope.clickItem = function(item, $event, $index) {
|
scope.clickItem = function(item, $event, $index) {
|
||||||
if (scope.onClick) {
|
if (scope.onClick) {
|
||||||
scope.onClick(item, $event, $index);
|
scope.onClick(item, $event, $index);
|
||||||
|
$event.stopPropagation();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -1,7 +1,7 @@
|
|||||||
(function () {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function MiniListViewDirective(entityResource) {
|
function MiniListViewDirective(entityResource, iconHelper) {
|
||||||
|
|
||||||
function link(scope, el, attr, ctrl) {
|
function link(scope, el, attr, ctrl) {
|
||||||
|
|
||||||
@@ -19,6 +19,11 @@
|
|||||||
|
|
||||||
function open(node) {
|
function open(node) {
|
||||||
|
|
||||||
|
// convert legacy icon for node
|
||||||
|
if(node && node.icon) {
|
||||||
|
node.icon = iconHelper.convertFromLegacyIcon(node.icon);
|
||||||
|
}
|
||||||
|
|
||||||
goingForward = true;
|
goingForward = true;
|
||||||
|
|
||||||
var miniListView = {
|
var miniListView = {
|
||||||
@@ -58,6 +63,11 @@
|
|||||||
// update children
|
// update children
|
||||||
miniListView.children = data.items;
|
miniListView.children = data.items;
|
||||||
_.each(miniListView.children, function(c) {
|
_.each(miniListView.children, function(c) {
|
||||||
|
// convert legacy icon for node
|
||||||
|
if(c.icon) {
|
||||||
|
c.icon = iconHelper.convertFromLegacyIcon(c.icon);
|
||||||
|
}
|
||||||
|
// set published state for content
|
||||||
if (c.metaData) {
|
if (c.metaData) {
|
||||||
c.hasChildren = c.metaData.HasChildren;
|
c.hasChildren = c.metaData.HasChildren;
|
||||||
if(scope.entityType === "Document") {
|
if(scope.entityType === "Document") {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
(function () {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function TableDirective() {
|
function TableDirective(iconHelper) {
|
||||||
|
|
||||||
function link(scope, el, attr, ctrl) {
|
function link(scope, el, attr, ctrl) {
|
||||||
|
|
||||||
@@ -43,6 +43,10 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
scope.getIcon = function (entry) {
|
||||||
|
return iconHelper.convertFromLegacyIcon(entry.icon);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var directive = {
|
var directive = {
|
||||||
|
|||||||
+10
-8
@@ -9,7 +9,7 @@ function valServerField(serverValidationManager) {
|
|||||||
return {
|
return {
|
||||||
require: 'ngModel',
|
require: 'ngModel',
|
||||||
restrict: "A",
|
restrict: "A",
|
||||||
link: function (scope, element, attr, ctrl) {
|
link: function (scope, element, attr, ngModel) {
|
||||||
|
|
||||||
var fieldName = null;
|
var fieldName = null;
|
||||||
var eventBindings = [];
|
var eventBindings = [];
|
||||||
@@ -23,23 +23,25 @@ function valServerField(serverValidationManager) {
|
|||||||
// resubmitted. So once a field is changed that has a server error assigned to it
|
// resubmitted. So once a field is changed that has a server error assigned to it
|
||||||
// we need to re-validate it for the server side validator so the user can resubmit
|
// we need to re-validate it for the server side validator so the user can resubmit
|
||||||
// the form. Of course normal client-side validators will continue to execute.
|
// the form. Of course normal client-side validators will continue to execute.
|
||||||
eventBindings.push(scope.$watch('ngModel', function(newValue){
|
eventBindings.push(scope.$watch(function() {
|
||||||
if (ctrl.$invalid) {
|
return ngModel.$modelValue;
|
||||||
ctrl.$setValidity('valServerField', true);
|
}, function(newValue){
|
||||||
|
if (ngModel.$invalid) {
|
||||||
|
ngModel.$setValidity('valServerField', true);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
//subscribe to the server validation changes
|
//subscribe to the server validation changes
|
||||||
serverValidationManager.subscribe(null, fieldName, function (isValid, fieldErrors, allErrors) {
|
serverValidationManager.subscribe(null, fieldName, function (isValid, fieldErrors, allErrors) {
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
ctrl.$setValidity('valServerField', false);
|
ngModel.$setValidity('valServerField', false);
|
||||||
//assign an error msg property to the current validator
|
//assign an error msg property to the current validator
|
||||||
ctrl.errorMsg = fieldErrors[0].errorMsg;
|
ngModel.errorMsg = fieldErrors[0].errorMsg;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ctrl.$setValidity('valServerField', true);
|
ngModel.$setValidity('valServerField', true);
|
||||||
//reset the error message
|
//reset the error message
|
||||||
ctrl.errorMsg = "";
|
ngModel.errorMsg = "";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -343,8 +343,13 @@ angular.module('umbraco.mocks').
|
|||||||
{
|
{
|
||||||
results.push(decodeURIComponent(match[1].replace(/\+/g, " ")));
|
results.push(decodeURIComponent(match[1].replace(/\+/g, " ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
},
|
||||||
|
|
||||||
|
getObjectPropertyFromJsonString: function(data, name) {
|
||||||
|
var obj = JSON.parse(data);
|
||||||
|
return obj[name];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}]);
|
}]);
|
||||||
|
|||||||
@@ -21,8 +21,27 @@ angular.module('umbraco.mocks').
|
|||||||
if (!mocksUtils.checkAuth()) {
|
if (!mocksUtils.checkAuth()) {
|
||||||
return [401, null, null];
|
return [401, null, null];
|
||||||
}
|
}
|
||||||
|
|
||||||
var ids = mocksUtils.getParametersByName(data, "ids") || [1234, 23324, 2323, 23424];
|
var ids = mocksUtils.getParametersByName(data, "ids") || [1234, 23324, 2323, 23424];
|
||||||
|
|
||||||
|
var nodes = [];
|
||||||
|
|
||||||
|
$(ids).each(function (i, id) {
|
||||||
|
var _id = parseInt(id, 10);
|
||||||
|
nodes.push(mocksUtils.getMockEntity(_id));
|
||||||
|
});
|
||||||
|
|
||||||
|
return [200, nodes, null];
|
||||||
|
}
|
||||||
|
|
||||||
|
function returnEntitybyIdsPost(method, url, data, headers) {
|
||||||
|
|
||||||
|
if (!mocksUtils.checkAuth()) {
|
||||||
|
return [401, null, null];
|
||||||
|
}
|
||||||
|
|
||||||
|
var ids = mocksUtils.getObjectPropertyFromJsonString(data, "ids") || [1234, 23324, 2323, 23424];
|
||||||
|
|
||||||
var nodes = [];
|
var nodes = [];
|
||||||
|
|
||||||
$(ids).each(function (i, id) {
|
$(ids).each(function (i, id) {
|
||||||
@@ -50,6 +69,10 @@ angular.module('umbraco.mocks').
|
|||||||
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetByIds'))
|
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetByIds'))
|
||||||
.respond(returnEntitybyIds);
|
.respond(returnEntitybyIds);
|
||||||
|
|
||||||
|
$httpBackend
|
||||||
|
.whenPOST(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetByIds'))
|
||||||
|
.respond(returnEntitybyIdsPost);
|
||||||
|
|
||||||
$httpBackend
|
$httpBackend
|
||||||
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetAncestors'))
|
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetAncestors'))
|
||||||
.respond(returnEntitybyIds);
|
.respond(returnEntitybyIds);
|
||||||
|
|||||||
@@ -199,11 +199,17 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
getScaffold: function (type, id, snippetName) {
|
getScaffold: function (type, id, snippetName) {
|
||||||
|
|
||||||
|
var queryString = "?type=" + type + "&id=" + id;
|
||||||
|
if (snippetName) {
|
||||||
|
queryString += "&snippetName=" + snippetName;
|
||||||
|
}
|
||||||
|
|
||||||
return umbRequestHelper.resourcePromise(
|
return umbRequestHelper.resourcePromise(
|
||||||
$http.get(
|
$http.get(
|
||||||
umbRequestHelper.getApiUrl(
|
umbRequestHelper.getApiUrl(
|
||||||
"codeFileApiBaseUrl",
|
"codeFileApiBaseUrl",
|
||||||
"GetScaffold?type=" + type + "&id=" + id + "&snippetName=" + snippetName)),
|
"GetScaffold" + queryString)),
|
||||||
"Failed to get scaffold for" + type);
|
"Failed to get scaffold for" + type);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
* @ngdoc service
|
* @ngdoc service
|
||||||
* @name umbraco.resources.macroResource
|
* @name umbraco.resources.macroResource
|
||||||
* @description Deals with data for macros
|
* @description Deals with data for macros
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
function macroResource($q, $http, umbRequestHelper) {
|
function macroResource($q, $http, umbRequestHelper) {
|
||||||
|
|
||||||
//the factory object returned
|
//the factory object returned
|
||||||
return {
|
return {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
* @name umbraco.resources.macroResource#getMacroParameters
|
* @name umbraco.resources.macroResource#getMacroParameters
|
||||||
@@ -20,7 +20,7 @@ function macroResource($q, $http, umbRequestHelper) {
|
|||||||
* @param {int} macroId The macro id to get parameters for
|
* @param {int} macroId The macro id to get parameters for
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
getMacroParameters: function (macroId) {
|
getMacroParameters: function (macroId) {
|
||||||
return umbRequestHelper.resourcePromise(
|
return umbRequestHelper.resourcePromise(
|
||||||
$http.get(
|
$http.get(
|
||||||
umbRequestHelper.getApiUrl(
|
umbRequestHelper.getApiUrl(
|
||||||
@@ -29,7 +29,7 @@ function macroResource($q, $http, umbRequestHelper) {
|
|||||||
[{ macroId: macroId }])),
|
[{ macroId: macroId }])),
|
||||||
'Failed to retrieve macro parameters for macro with id ' + macroId);
|
'Failed to retrieve macro parameters for macro with id ' + macroId);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
* @name umbraco.resources.macroResource#getMacroResult
|
* @name umbraco.resources.macroResource#getMacroResult
|
||||||
@@ -55,6 +55,27 @@ function macroResource($q, $http, umbRequestHelper) {
|
|||||||
macroParams: macroParamDictionary
|
macroParams: macroParamDictionary
|
||||||
}),
|
}),
|
||||||
'Failed to retrieve macro result for macro with alias ' + macroAlias);
|
'Failed to retrieve macro result for macro with alias ' + macroAlias);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {} filename
|
||||||
|
* @returns {}
|
||||||
|
*/
|
||||||
|
createPartialViewMacroWithFile: function(parent, filename) {
|
||||||
|
|
||||||
|
return umbRequestHelper.resourcePromise(
|
||||||
|
$http.post(
|
||||||
|
umbRequestHelper.getApiUrl(
|
||||||
|
"macroApiBaseUrl",
|
||||||
|
"CreatePartialViewMacroWithFile"), {
|
||||||
|
parent: parent,
|
||||||
|
filename: filename
|
||||||
|
}
|
||||||
|
),
|
||||||
|
'Failed to create macro "' + filename + '"'
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,10 +51,15 @@ function treeResource($q, $http, umbRequestHelper) {
|
|||||||
if (!options.isDialog) {
|
if (!options.isDialog) {
|
||||||
options.isDialog = false;
|
options.isDialog = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//create the query string for the tree request, these are the mandatory options:
|
//create the query string for the tree request, these are the mandatory options:
|
||||||
var query = "application=" + options.section + "&tree=" + options.tree + "&isDialog=" + options.isDialog;
|
var query = "application=" + options.section + "&tree=" + options.tree + "&isDialog=" + options.isDialog;
|
||||||
|
|
||||||
|
//if you need to load a not initialized tree set this value to false - default is true
|
||||||
|
if (options.onlyinitialized) {
|
||||||
|
query += "&onlyInitialized=" + options.onlyinitialized;
|
||||||
|
}
|
||||||
|
|
||||||
//the options can contain extra query string parameters
|
//the options can contain extra query string parameters
|
||||||
if (options.queryString) {
|
if (options.queryString) {
|
||||||
query += "&" + options.queryString;
|
query += "&" + options.queryString;
|
||||||
|
|||||||
@@ -522,6 +522,26 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc function
|
||||||
|
* @name umbraco.services.contentEditingHelper#redirectToRenamedContent
|
||||||
|
* @methodOf umbraco.services.contentEditingHelper
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* For some editors like scripts or entites that have names as ids, these names can change and we need to redirect
|
||||||
|
* to their new paths, this is helper method to do that.
|
||||||
|
*/
|
||||||
|
redirectToRenamedContent: function (id) {
|
||||||
|
//clear the query strings
|
||||||
|
$location.search("");
|
||||||
|
//change to new path
|
||||||
|
$location.path("/" + $routeParams.section + "/" + $routeParams.tree + "/" + $routeParams.method + "/" + id);
|
||||||
|
//don't add a browser history for this
|
||||||
|
$location.replace();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function entityHelper() {
|
||||||
|
|
||||||
|
function getEntityTypeFromSection(section) {
|
||||||
|
if (section === "member") {
|
||||||
|
return "Member";
|
||||||
|
}
|
||||||
|
else if (section === "media") {
|
||||||
|
return "Media";
|
||||||
|
} else {
|
||||||
|
return "Document";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////
|
||||||
|
|
||||||
|
var service = {
|
||||||
|
getEntityTypeFromSection: getEntityTypeFromSection
|
||||||
|
};
|
||||||
|
|
||||||
|
return service;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
angular.module('umbraco.services').factory('entityHelper', entityHelper);
|
||||||
|
|
||||||
|
})();
|
||||||
@@ -21,7 +21,9 @@ function mediaTypeHelper(mediaTypeResource, $q) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getAllowedImagetypes: function (mediaId){
|
getAllowedImagetypes: function (mediaId){
|
||||||
|
|
||||||
|
//TODO: This is horribly inneficient - why make one request per type!?
|
||||||
|
|
||||||
// Get All allowedTypes
|
// Get All allowedTypes
|
||||||
return mediaTypeResource.getAllowedTypes(mediaId)
|
return mediaTypeResource.getAllowedTypes(mediaId)
|
||||||
.then(function(types){
|
.then(function(types){
|
||||||
|
|||||||
@@ -8,8 +8,15 @@
|
|||||||
return "@Umbraco.GetDictionaryValue(\"" + nodeName + "\")";
|
return "@Umbraco.GetDictionaryValue(\"" + nodeName + "\")";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInsertPartialSnippet(nodeName) {
|
function getInsertPartialSnippet(parentId, nodeName) {
|
||||||
return "@Html.Partial(\"" + nodeName + "\")";
|
|
||||||
|
var partialViewName = nodeName.replace(".cshtml", "");
|
||||||
|
|
||||||
|
if(parentId) {
|
||||||
|
partialViewName = parentId + "/" + partialViewName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "@Html.Partial(\"" + partialViewName + "\")";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getQuerySnippet(queryExpression) {
|
function getQuerySnippet(queryExpression) {
|
||||||
|
|||||||
@@ -95,11 +95,20 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
|||||||
|
|
||||||
if(selectedElm.nodeName === 'IMG'){
|
if(selectedElm.nodeName === 'IMG'){
|
||||||
var img = $(selectedElm);
|
var img = $(selectedElm);
|
||||||
|
|
||||||
|
var hasUdi = img.attr("data-udi") ? true : false;
|
||||||
|
|
||||||
currentTarget = {
|
currentTarget = {
|
||||||
altText: img.attr("alt"),
|
altText: img.attr("alt"),
|
||||||
url: img.attr("src"),
|
url: img.attr("src")
|
||||||
id: img.attr("rel")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (hasUdi) {
|
||||||
|
currentTarget["udi"] = img.attr("data-udi");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentTarget["id"] = img.attr("rel");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
userService.getCurrentUser().then(function(userData) {
|
userService.getCurrentUser().then(function(userData) {
|
||||||
@@ -115,13 +124,23 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
|||||||
insertMediaInEditor: function(editor, img) {
|
insertMediaInEditor: function(editor, img) {
|
||||||
if(img) {
|
if(img) {
|
||||||
|
|
||||||
|
var hasUdi = img.udi ? true : false;
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
alt: img.altText || "",
|
alt: img.altText || "",
|
||||||
src: (img.url) ? img.url : "nothing.jpg",
|
src: (img.url) ? img.url : "nothing.jpg",
|
||||||
rel: img.id,
|
|
||||||
'data-id': img.id,
|
|
||||||
id: '__mcenew'
|
id: '__mcenew'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (hasUdi) {
|
||||||
|
data["data-udi"] = img.udi;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//Considering these fixed because UDI will now be used and thus
|
||||||
|
// we have no need for rel http://issues.umbraco.org/issue/U4-6228, http://issues.umbraco.org/issue/U4-6595
|
||||||
|
data["rel"] = img.id;
|
||||||
|
data["data-id"] = img.id;
|
||||||
|
}
|
||||||
|
|
||||||
editor.insertContent(editor.dom.createHTML('img', data));
|
editor.insertContent(editor.dom.createHTML('img', data));
|
||||||
|
|
||||||
@@ -725,27 +744,36 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
|||||||
insertLinkInEditor: function(editor, target, anchorElm) {
|
insertLinkInEditor: function(editor, target, anchorElm) {
|
||||||
|
|
||||||
var href = target.url;
|
var href = target.url;
|
||||||
|
// We want to use the Udi. If it is set, we use it, else fallback to id, and finally to null
|
||||||
|
var hasUdi = target.udi ? true : false;
|
||||||
|
var id = hasUdi ? target.udi : (target.id ? target.id : null);
|
||||||
|
|
||||||
|
//Create a json obj used to create the attributes for the tag
|
||||||
|
function createElemAttributes() {
|
||||||
|
var a = {
|
||||||
|
href: href,
|
||||||
|
title: target.name,
|
||||||
|
target: target.target ? target.target : null,
|
||||||
|
rel: target.rel ? target.rel : null
|
||||||
|
};
|
||||||
|
if (hasUdi) {
|
||||||
|
a["data-udi"] = target.udi;
|
||||||
|
}
|
||||||
|
else if (target.id) {
|
||||||
|
a["data-id"] = target.id;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
function insertLink() {
|
function insertLink() {
|
||||||
if (anchorElm) {
|
if (anchorElm) {
|
||||||
editor.dom.setAttribs(anchorElm, {
|
editor.dom.setAttribs(anchorElm, createElemAttributes());
|
||||||
href: href,
|
|
||||||
title: target.name,
|
|
||||||
target: target.target ? target.target : null,
|
|
||||||
rel: target.rel ? target.rel : null,
|
|
||||||
'data-id': target.id ? target.id : null
|
|
||||||
});
|
|
||||||
|
|
||||||
editor.selection.select(anchorElm);
|
editor.selection.select(anchorElm);
|
||||||
editor.execCommand('mceEndTyping');
|
editor.execCommand('mceEndTyping');
|
||||||
} else {
|
}
|
||||||
editor.execCommand('mceInsertLink', false, {
|
else {
|
||||||
href: href,
|
editor.execCommand('mceInsertLink', false, createElemAttributes());
|
||||||
title: target.name,
|
|
||||||
target: target.target ? target.target : null,
|
|
||||||
rel: target.rel ? target.rel : null,
|
|
||||||
'data-id': target.id ? target.id : null
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -755,14 +783,9 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if we have an id, it must be a locallink:id, aslong as the isMedia flag is not set
|
//if we have an id, it must be a locallink:id, aslong as the isMedia flag is not set
|
||||||
if(target.id && (angular.isUndefined(target.isMedia) || !target.isMedia)){
|
if(id && (angular.isUndefined(target.isMedia) || !target.isMedia)){
|
||||||
if (target.udi) {
|
|
||||||
href = "/{localLink:" + target.udi + "}";
|
href = "/{localLink:" + id + "}";
|
||||||
}
|
|
||||||
else {
|
|
||||||
//This shouldn't happen! but just in case we'll leave this here
|
|
||||||
href = "/{localLink:" + target.id + "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
insertLink();
|
insertLink();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
//page specific styles
|
//page specific styles
|
||||||
@import "pages/document-type-editor.less";
|
@import "pages/document-type-editor.less";
|
||||||
@import "pages/login.less";
|
@import "pages/login.less";
|
||||||
|
@import "pages/welcome-dashboard.less";
|
||||||
|
|
||||||
|
|
||||||
//used for property editors
|
//used for property editors
|
||||||
|
|||||||
@@ -138,16 +138,6 @@ input.umb-group-builder__group-title-input {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
position: relative;
|
|
||||||
top: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input.umb-group-builder__group-sort-value {
|
|
||||||
font-size: 12px;
|
|
||||||
padding: 0px 0 0px 5px;
|
|
||||||
width: 40px;
|
|
||||||
margin-bottom: 0;
|
|
||||||
border-color: @gray-8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- PROPERTIES ---------- */
|
/* ---------- PROPERTIES ---------- */
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
// Title
|
||||||
|
.welcome-dashboard__intro {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__title {
|
||||||
|
font-size: 30px;
|
||||||
|
color: @gray-2;
|
||||||
|
line-height: 1.3em;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 750px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__intro-text {
|
||||||
|
font-size: 18px;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 750px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
line-height: 1.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info box
|
||||||
|
.welcome-dashboard__info-box-boxes {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__info-box {
|
||||||
|
background-color: @turquoise-washed;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
padding: 25px;
|
||||||
|
text-decoration: none;
|
||||||
|
display: block;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__info-box:hover {
|
||||||
|
border: 2px solid @turquoise;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-color 150ms ease-in-out;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__info-box:active,
|
||||||
|
.welcome-dashboard__info-box:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.welcome-dashboard__info-box-title {
|
||||||
|
color: @turquoise-d1;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__info-box-description {
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Articles
|
||||||
|
.welcome-dashboard__cards {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__card {
|
||||||
|
background-color: @gray-10;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__card-image-wrapper {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
max-height: 225px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__card-image {
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__card-image-wrapper + .welcome-dashboard__card-content {
|
||||||
|
padding-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__card-content {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__card-title {
|
||||||
|
color: @gray-2;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
line-height: 1.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-dashboard__card-teaser {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.umb-editor-tiny {
|
.umb-editor-tiny {
|
||||||
width: 50px;
|
width: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.umb-editor-small {
|
.umb-editor-small {
|
||||||
|
|||||||
@@ -22,17 +22,19 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
|
|||||||
$scope.target = dialogOptions.currentTarget;
|
$scope.target = dialogOptions.currentTarget;
|
||||||
|
|
||||||
//if we have a node ID, we fetch the current node to build the form data
|
//if we have a node ID, we fetch the current node to build the form data
|
||||||
if ($scope.target.id) {
|
if ($scope.target.id || $scope.target.udi) {
|
||||||
|
|
||||||
|
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id;
|
||||||
|
|
||||||
if (!$scope.target.path) {
|
if (!$scope.target.path) {
|
||||||
entityResource.getPath($scope.target.id, "Document").then(function (path) {
|
entityResource.getPath(id, "Document").then(function (path) {
|
||||||
$scope.target.path = path;
|
$scope.target.path = path;
|
||||||
//now sync the tree to this path
|
//now sync the tree to this path
|
||||||
$scope.dialogTreeEventHandler.syncTree({ path: $scope.target.path, tree: "content" });
|
$scope.dialogTreeEventHandler.syncTree({ path: $scope.target.path, tree: "content" });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
contentResource.getNiceUrl($scope.target.id).then(function (url) {
|
contentResource.getNiceUrl(id).then(function (url) {
|
||||||
$scope.target.url = url;
|
$scope.target.url = url;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -59,7 +61,8 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
|
|||||||
|
|
||||||
$scope.currentNode = args.node;
|
$scope.currentNode = args.node;
|
||||||
$scope.currentNode.selected = true;
|
$scope.currentNode.selected = true;
|
||||||
$scope.target.id = args.node.id;
|
$scope.target.id = args.node.id;
|
||||||
|
$scope.target.udi = args.node.udi;
|
||||||
$scope.target.name = args.node.name;
|
$scope.target.name = args.node.name;
|
||||||
|
|
||||||
if (args.node.id < 0) {
|
if (args.node.id < 0) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
(function() {
|
(function() {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function CopyOverlay($scope, localizationService, eventsService) {
|
function CopyOverlay($scope, localizationService, eventsService, entityHelper) {
|
||||||
|
|
||||||
var vm = this;
|
var vm = this;
|
||||||
|
|
||||||
@@ -32,54 +32,30 @@
|
|||||||
selectedSearchResults: []
|
selectedSearchResults: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// get entity type based on the section
|
||||||
|
$scope.entityType = entityHelper.getEntityTypeFromSection(dialogOptions.section);
|
||||||
|
|
||||||
function nodeSelectHandler(ev, args) {
|
function nodeSelectHandler(ev, args) {
|
||||||
args.event.preventDefault();
|
if(args && args.event) {
|
||||||
args.event.stopPropagation();
|
args.event.preventDefault();
|
||||||
|
args.event.stopPropagation();
|
||||||
if (args.node.metaData.listViewNode) {
|
|
||||||
//check if list view 'search' node was selected
|
|
||||||
|
|
||||||
vm.searchInfo.showSearch = true;
|
|
||||||
vm.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
|
||||||
vm.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//eventsService.emit("editors.content.copyController.select", args);
|
|
||||||
|
|
||||||
if ($scope.model.target) {
|
|
||||||
//un-select if there's a current one selected
|
|
||||||
$scope.model.target.selected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.model.target = args.node;
|
|
||||||
$scope.model.target.selected = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//eventsService.emit("editors.content.copyController.select", args);
|
||||||
|
|
||||||
|
if ($scope.model.target) {
|
||||||
|
//un-select if there's a current one selected
|
||||||
|
$scope.model.target.selected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.model.target = args.node;
|
||||||
|
$scope.model.target.selected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeExpandedHandler(ev, args) {
|
function nodeExpandedHandler(ev, args) {
|
||||||
if (angular.isArray(args.children)) {
|
// open mini list view for list views
|
||||||
|
if (args.node.metaData.isContainer) {
|
||||||
//iterate children
|
openMiniListView(args.node);
|
||||||
_.each(args.children, function (child) {
|
|
||||||
//check if any of the items are list views, if so we need to add a custom
|
|
||||||
// child: A node to activate the search
|
|
||||||
if (child.metaData.isContainer) {
|
|
||||||
child.hasChildren = true;
|
|
||||||
child.children = [
|
|
||||||
{
|
|
||||||
level: child.level + 1,
|
|
||||||
hasChildren: false,
|
|
||||||
name: searchText,
|
|
||||||
metaData: {
|
|
||||||
listViewNode: child,
|
|
||||||
},
|
|
||||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
|
||||||
cssClasses: ["not-published"]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +86,20 @@
|
|||||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mini list view
|
||||||
|
$scope.selectListViewNode = function (node) {
|
||||||
|
node.selected = node.selected === true ? false : true;
|
||||||
|
nodeSelectHandler({}, { node: node });
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.closeMiniListView = function () {
|
||||||
|
$scope.miniListView = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
function openMiniListView(node) {
|
||||||
|
$scope.miniListView = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +1,47 @@
|
|||||||
<div ng-controller="Umbraco.Overlays.CopyOverlay as vm">
|
<div ng-controller="Umbraco.Overlays.CopyOverlay as vm">
|
||||||
|
|
||||||
<div class="umb-control-group">
|
<div ng-hide="miniListView">
|
||||||
<umb-tree-search-box
|
<div class="umb-control-group">
|
||||||
hide-search-callback="vm.hideSearch"
|
<umb-tree-search-box
|
||||||
search-callback="vm.onSearchResults"
|
hide-search-callback="vm.hideSearch"
|
||||||
search-from-id="{{vm.searchInfo.searchFromId}}"
|
search-callback="vm.onSearchResults"
|
||||||
search-from-name="{{vm.searchInfo.searchFromName}}"
|
search-from-id="{{vm.searchInfo.searchFromId}}"
|
||||||
show-search="{{vm.searchInfo.showSearch}}"
|
search-from-name="{{vm.searchInfo.searchFromName}}"
|
||||||
section="{{model.section}}">
|
show-search="{{vm.searchInfo.showSearch}}"
|
||||||
</umb-tree-search-box>
|
section="{{model.section}}">
|
||||||
</div>
|
</umb-tree-search-box>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="umb-control-group" ng-show="vm.searchInfo.showSearch">
|
<div class="umb-control-group" ng-show="vm.searchInfo.showSearch">
|
||||||
<umb-tree-search-results
|
<umb-tree-search-results
|
||||||
ng-if="vm.searchInfo.showSearch"
|
ng-if="vm.searchInfo.showSearch"
|
||||||
results="vm.searchInfo.results"
|
results="vm.searchInfo.results"
|
||||||
select-result-callback="vm.selectResult">
|
select-result-callback="vm.selectResult">
|
||||||
</umb-tree-search-results>
|
</umb-tree-search-results>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="umb-control-group -no-border" ng-hide="vm.searchInfo.showSearch">
|
||||||
|
<umb-tree
|
||||||
|
section="{{model.section}}"
|
||||||
|
hideheader="false"
|
||||||
|
hideoptions="true"
|
||||||
|
isdialog="true"
|
||||||
|
eventhandler="dialogTreeEventHandler"
|
||||||
|
enablelistviewexpand="true"
|
||||||
|
enablecheckboxes="true">
|
||||||
|
</umb-tree>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="umb-control-group -no-border" ng-hide="vm.searchInfo.showSearch">
|
|
||||||
<umb-tree
|
|
||||||
section="{{model.section}}"
|
|
||||||
hideheader="false"
|
|
||||||
hideoptions="true"
|
|
||||||
isdialog="true"
|
|
||||||
eventhandler="dialogTreeEventHandler"
|
|
||||||
enablecheckboxes="true">
|
|
||||||
</umb-tree>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div ng-if="miniListView" class="umb-control-group">
|
||||||
|
<umb-mini-list-view
|
||||||
|
node="miniListView"
|
||||||
|
entity-type="{{entityType}}"
|
||||||
|
on-select="selectListViewNode(node)"
|
||||||
|
on-close="closeMiniListView()">
|
||||||
|
</umb-mini-list-view>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="umb-control-group -no-border">
|
<div class="umb-control-group -no-border">
|
||||||
<label>
|
<label>
|
||||||
|
|||||||
@@ -104,13 +104,18 @@
|
|||||||
function openPartialOverlay() {
|
function openPartialOverlay() {
|
||||||
vm.partialItemOverlay = {
|
vm.partialItemOverlay = {
|
||||||
view: "treepicker",
|
view: "treepicker",
|
||||||
section: "settings",
|
section: "settings",
|
||||||
treeAlias: "partialViews",
|
treeAlias: "partialViews",
|
||||||
entityType: "partialView",
|
entityType: "partialView",
|
||||||
multiPicker: false,
|
multiPicker: false,
|
||||||
show: true,
|
filter: function(i) {
|
||||||
|
if(i.name.indexOf(".cshtml") === -1 && i.name.indexOf(".vbhtml") === -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filterCssClass: "not-allowed",
|
||||||
title: localizationService.localize("template_insertPartialView"),
|
title: localizationService.localize("template_insertPartialView"),
|
||||||
|
show: true,
|
||||||
select: function(node){
|
select: function(node){
|
||||||
|
|
||||||
$scope.model.insert = {
|
$scope.model.insert = {
|
||||||
|
|||||||
+44
-54
@@ -47,69 +47,44 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
|
|||||||
}
|
}
|
||||||
|
|
||||||
function nodeSelectHandler(ev, args) {
|
function nodeSelectHandler(ev, args) {
|
||||||
args.event.preventDefault();
|
|
||||||
args.event.stopPropagation();
|
|
||||||
|
|
||||||
if (args.node.metaData.listViewNode) {
|
if(args && args.event) {
|
||||||
//check if list view 'search' node was selected
|
args.event.preventDefault();
|
||||||
|
args.event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
$scope.searchInfo.showSearch = true;
|
eventsService.emit("dialogs.linkPicker.select", args);
|
||||||
$scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
|
||||||
$scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
eventsService.emit("dialogs.linkPicker.select", args);
|
|
||||||
|
|
||||||
if ($scope.currentNode) {
|
if ($scope.currentNode) {
|
||||||
//un-select if there's a current one selected
|
//un-select if there's a current one selected
|
||||||
$scope.currentNode.selected = false;
|
$scope.currentNode.selected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.currentNode = args.node;
|
$scope.currentNode = args.node;
|
||||||
$scope.currentNode.selected = true;
|
$scope.currentNode.selected = true;
|
||||||
$scope.model.target.id = args.node.id;
|
$scope.model.target.id = args.node.id;
|
||||||
$scope.model.target.udi = args.node.udi;
|
$scope.model.target.udi = args.node.udi;
|
||||||
$scope.model.target.name = args.node.name;
|
$scope.model.target.name = args.node.name;
|
||||||
|
|
||||||
if (args.node.id < 0) {
|
if (args.node.id < 0) {
|
||||||
$scope.model.target.url = "/";
|
$scope.model.target.url = "/";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
contentResource.getNiceUrl(args.node.id).then(function (url) {
|
contentResource.getNiceUrl(args.node.id).then(function (url) {
|
||||||
$scope.model.target.url = url;
|
$scope.model.target.url = url;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!angular.isUndefined($scope.model.target.isMedia)) {
|
if (!angular.isUndefined($scope.model.target.isMedia)) {
|
||||||
delete $scope.model.target.isMedia;
|
delete $scope.model.target.isMedia;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeExpandedHandler(ev, args) {
|
function nodeExpandedHandler(ev, args) {
|
||||||
if (angular.isArray(args.children)) {
|
// open mini list view for list views
|
||||||
|
if (args.node.metaData.isContainer) {
|
||||||
//iterate children
|
openMiniListView(args.node);
|
||||||
_.each(args.children, function (child) {
|
}
|
||||||
//check if any of the items are list views, if so we need to add a custom
|
|
||||||
// child: A node to activate the search
|
|
||||||
if (child.metaData.isContainer) {
|
|
||||||
child.hasChildren = true;
|
|
||||||
child.children = [
|
|
||||||
{
|
|
||||||
level: child.level + 1,
|
|
||||||
hasChildren: false,
|
|
||||||
name: searchText,
|
|
||||||
metaData: {
|
|
||||||
listViewNode: child,
|
|
||||||
},
|
|
||||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
|
||||||
cssClasses: ["not-published"]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.switchToMediaPicker = function () {
|
$scope.switchToMediaPicker = function () {
|
||||||
@@ -160,4 +135,19 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
|
|||||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mini list view
|
||||||
|
$scope.selectListViewNode = function (node) {
|
||||||
|
node.selected = node.selected === true ? false : true;
|
||||||
|
nodeSelectHandler({}, { node: node });
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.closeMiniListView = function () {
|
||||||
|
$scope.miniListView = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
function openMiniListView(node) {
|
||||||
|
$scope.miniListView = node;
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,34 +28,45 @@
|
|||||||
<localize key="defaultdialogs_linkToPage">Link to page</localize>
|
<localize key="defaultdialogs_linkToPage">Link to page</localize>
|
||||||
</h5>
|
</h5>
|
||||||
|
|
||||||
<umb-tree-search-box
|
<div ng-hide="miniListView">
|
||||||
hide-search-callback="hideSearch"
|
<umb-tree-search-box
|
||||||
search-callback="onSearchResults"
|
hide-search-callback="hideSearch"
|
||||||
search-from-id="{{searchInfo.searchFromId}}"
|
search-callback="onSearchResults"
|
||||||
search-from-name="{{searchInfo.searchFromName}}"
|
search-from-id="{{searchInfo.searchFromId}}"
|
||||||
show-search="{{searchInfo.showSearch}}"
|
search-from-name="{{searchInfo.searchFromName}}"
|
||||||
section="{{section}}">
|
show-search="{{searchInfo.showSearch}}"
|
||||||
</umb-tree-search-box>
|
section="{{section}}">
|
||||||
|
</umb-tree-search-box>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<umb-tree-search-results
|
<umb-tree-search-results
|
||||||
ng-if="searchInfo.showSearch"
|
ng-if="searchInfo.showSearch"
|
||||||
results="searchInfo.results"
|
results="searchInfo.results"
|
||||||
select-result-callback="selectResult">
|
select-result-callback="selectResult">
|
||||||
</umb-tree-search-results>
|
</umb-tree-search-results>
|
||||||
|
|
||||||
<div ng-hide="searchInfo.showSearch">
|
<div ng-hide="searchInfo.showSearch">
|
||||||
<umb-tree
|
<umb-tree
|
||||||
section="content"
|
section="content"
|
||||||
hideheader="true"
|
hideheader="true"
|
||||||
hideoptions="true"
|
hideoptions="true"
|
||||||
eventhandler="dialogTreeEventHandler"
|
eventhandler="dialogTreeEventHandler"
|
||||||
isdialog="true"
|
enablelistviewexpand="true"
|
||||||
enablecheckboxes="true">
|
isdialog="true"
|
||||||
</umb-tree>
|
enablecheckboxes="true">
|
||||||
|
</umb-tree>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<umb-mini-list-view
|
||||||
|
ng-if="miniListView"
|
||||||
|
node="miniListView"
|
||||||
|
entity-type="Document"
|
||||||
|
on-select="selectListViewNode(node)"
|
||||||
|
on-close="closeMiniListView()">
|
||||||
|
</umb-mini-list-view>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="umb-control-group">
|
<div class="umb-control-group">
|
||||||
|
|||||||
+49
-23
@@ -119,7 +119,7 @@ angular.module("umbraco")
|
|||||||
localStorageService.set("umbLastOpenedMediaNodeId", folder.id);
|
localStorageService.set("umbLastOpenedMediaNodeId", folder.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.clickHandler = function(image, event, index) {
|
$scope.clickHandler = function (image, event, index) {
|
||||||
if (image.isFolder) {
|
if (image.isFolder) {
|
||||||
if ($scope.disableFolderSelect) {
|
if ($scope.disableFolderSelect) {
|
||||||
$scope.gotoFolder(image);
|
$scope.gotoFolder(image);
|
||||||
@@ -179,27 +179,49 @@ angular.module("umbraco")
|
|||||||
$scope.activeDrag = false;
|
$scope.activeDrag = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function ensureWithinStartNode(node) {
|
||||||
|
// make sure that last opened node is on the same path as start node
|
||||||
|
var nodePath = node.path.split(",");
|
||||||
|
|
||||||
|
if (nodePath.indexOf($scope.startNodeId.toString()) !== -1) {
|
||||||
|
$scope.gotoFolder({ id: $scope.lastOpenedNode, name: "Media", icon: "icon-folder" });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gotoStartNode(err) {
|
||||||
|
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||||
|
}
|
||||||
|
|
||||||
//default root item
|
//default root item
|
||||||
if (!$scope.target) {
|
if (!$scope.target) {
|
||||||
if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
|
if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
|
||||||
entityResource.getById($scope.lastOpenedNode, "media")
|
entityResource.getById($scope.lastOpenedNode, "media")
|
||||||
.then(function(node) {
|
.then(ensureWithinStartNode, gotoStartNode);
|
||||||
// make sure that las opened node is on the same path as start node
|
|
||||||
var nodePath = node.path.split(",");
|
|
||||||
|
|
||||||
if (nodePath.indexOf($scope.startNodeId.toString()) !== -1) {
|
|
||||||
$scope
|
|
||||||
.gotoFolder({ id: $scope.lastOpenedNode, name: "Media", icon: "icon-folder" });
|
|
||||||
} else {
|
|
||||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function(err) {
|
|
||||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
gotoStartNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//if a target is specified, go look it up - generally this target will just contain ids not the actual full
|
||||||
|
//media object so we need to look it up
|
||||||
|
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
|
||||||
|
var altText = $scope.target.altText;
|
||||||
|
mediaResource.getById(id)
|
||||||
|
.then(function (node) {
|
||||||
|
$scope.target = node;
|
||||||
|
if (ensureWithinStartNode(node)) {
|
||||||
|
selectImage(node);
|
||||||
|
$scope.target.url = mediaHelper.resolveFile(node);
|
||||||
|
$scope.target.altText = altText;
|
||||||
|
$scope.openDetailsDialog();
|
||||||
|
}
|
||||||
|
}, gotoStartNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.openDetailsDialog = function() {
|
$scope.openDetailsDialog = function() {
|
||||||
@@ -308,15 +330,19 @@ angular.module("umbraco")
|
|||||||
var folderImage = $scope.images[folderImageIndex];
|
var folderImage = $scope.images[folderImageIndex];
|
||||||
var imageIsSelected = false;
|
var imageIsSelected = false;
|
||||||
|
|
||||||
for (var selectedImageIndex = 0;
|
if ($scope.model && angular.isArray($scope.model.selectedImages)) {
|
||||||
selectedImageIndex < $scope.model.selectedImages.length;
|
for (var selectedImageIndex = 0;
|
||||||
selectedImageIndex++) {
|
selectedImageIndex < $scope.model.selectedImages.length;
|
||||||
var selectedImage = $scope.model.selectedImages[selectedImageIndex];
|
selectedImageIndex++) {
|
||||||
|
var selectedImage = $scope.model.selectedImages[selectedImageIndex];
|
||||||
|
|
||||||
if (folderImage.key === selectedImage.key) {
|
if (folderImage.key === selectedImage.key) {
|
||||||
imageIsSelected = true;
|
imageIsSelected = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (imageIsSelected) {
|
if (imageIsSelected) {
|
||||||
folderImage.selected = true;
|
folderImage.selected = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
(function() {
|
(function() {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function MoveOverlay($scope, localizationService, eventsService) {
|
function MoveOverlay($scope, localizationService, eventsService, entityHelper) {
|
||||||
|
|
||||||
var vm = this;
|
var vm = this;
|
||||||
|
|
||||||
@@ -32,54 +32,32 @@
|
|||||||
selectedSearchResults: []
|
selectedSearchResults: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// get entity type based on the section
|
||||||
|
$scope.entityType = entityHelper.getEntityTypeFromSection(dialogOptions.section);
|
||||||
|
|
||||||
function nodeSelectHandler(ev, args) {
|
function nodeSelectHandler(ev, args) {
|
||||||
args.event.preventDefault();
|
|
||||||
args.event.stopPropagation();
|
|
||||||
|
|
||||||
if (args.node.metaData.listViewNode) {
|
if(args && args.event) {
|
||||||
//check if list view 'search' node was selected
|
args.event.preventDefault();
|
||||||
|
args.event.stopPropagation();
|
||||||
vm.searchInfo.showSearch = true;
|
|
||||||
vm.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
|
||||||
vm.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
//eventsService.emit("editors.content.copyController.select", args);
|
|
||||||
|
|
||||||
if ($scope.model.target) {
|
//eventsService.emit("editors.content.copyController.select", args);
|
||||||
//un-select if there's a current one selected
|
|
||||||
$scope.model.target.selected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.model.target = args.node;
|
if ($scope.model.target) {
|
||||||
$scope.model.target.selected = true;
|
//un-select if there's a current one selected
|
||||||
|
$scope.model.target.selected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.model.target = args.node;
|
||||||
|
$scope.model.target.selected = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeExpandedHandler(ev, args) {
|
function nodeExpandedHandler(ev, args) {
|
||||||
if (angular.isArray(args.children)) {
|
// open mini list view for list views
|
||||||
|
if (args.node.metaData.isContainer) {
|
||||||
//iterate children
|
openMiniListView(args.node);
|
||||||
_.each(args.children, function (child) {
|
|
||||||
//check if any of the items are list views, if so we need to add a custom
|
|
||||||
// child: A node to activate the search
|
|
||||||
if (child.metaData.isContainer) {
|
|
||||||
child.hasChildren = true;
|
|
||||||
child.children = [
|
|
||||||
{
|
|
||||||
level: child.level + 1,
|
|
||||||
hasChildren: false,
|
|
||||||
name: searchText,
|
|
||||||
metaData: {
|
|
||||||
listViewNode: child,
|
|
||||||
},
|
|
||||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
|
||||||
cssClasses: ["not-published"]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +88,19 @@
|
|||||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mini list view
|
||||||
|
$scope.selectListViewNode = function (node) {
|
||||||
|
node.selected = node.selected === true ? false : true;
|
||||||
|
nodeSelectHandler({}, { node: node });
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.closeMiniListView = function () {
|
||||||
|
$scope.miniListView = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
function openMiniListView(node) {
|
||||||
|
$scope.miniListView = node;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,43 @@
|
|||||||
<div ng-controller="Umbraco.Overlays.MoveOverlay as vm">
|
<div ng-controller="Umbraco.Overlays.MoveOverlay as vm">
|
||||||
|
<div ng-hide="miniListView">
|
||||||
|
<div class="umb-control-group">
|
||||||
|
<umb-tree-search-box
|
||||||
|
hide-search-callback="vm.hideSearch"
|
||||||
|
search-callback="vm.onSearchResults"
|
||||||
|
search-from-id="{{vm.searchInfo.searchFromId}}"
|
||||||
|
search-from-name="{{vm.searchInfo.searchFromName}}"
|
||||||
|
show-search="{{vm.searchInfo.showSearch}}"
|
||||||
|
section="{{model.section}}">
|
||||||
|
</umb-tree-search-box>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="umb-control-group">
|
<div class="umb-control-group" ng-show="vm.searchInfo.showSearch">
|
||||||
<umb-tree-search-box
|
<umb-tree-search-results
|
||||||
hide-search-callback="vm.hideSearch"
|
ng-if="vm.searchInfo.showSearch"
|
||||||
search-callback="vm.onSearchResults"
|
results="vm.searchInfo.results"
|
||||||
search-from-id="{{vm.searchInfo.searchFromId}}"
|
select-result-callback="vm.selectResult">
|
||||||
search-from-name="{{vm.searchInfo.searchFromName}}"
|
</umb-tree-search-results>
|
||||||
show-search="{{vm.searchInfo.showSearch}}"
|
</div>
|
||||||
section="{{model.section}}">
|
|
||||||
</umb-tree-search-box>
|
<div class="umb-control-group -no-border" ng-hide="vm.searchInfo.showSearch">
|
||||||
|
<umb-tree
|
||||||
|
section="{{model.section}}"
|
||||||
|
hideheader="false"
|
||||||
|
hideoptions="true"
|
||||||
|
isdialog="true"
|
||||||
|
eventhandler="dialogTreeEventHandler"
|
||||||
|
enablelistviewexpand="true"
|
||||||
|
enablecheckboxes="true">
|
||||||
|
</umb-tree>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="umb-control-group" ng-show="vm.searchInfo.showSearch">
|
<umb-mini-list-view
|
||||||
<umb-tree-search-results
|
ng-if="miniListView"
|
||||||
ng-if="vm.searchInfo.showSearch"
|
node="miniListView"
|
||||||
results="vm.searchInfo.results"
|
entity-type="{{entityType}}"
|
||||||
select-result-callback="vm.selectResult">
|
on-select="selectListViewNode(node)"
|
||||||
</umb-tree-search-results>
|
on-close="closeMiniListView()">
|
||||||
</div>
|
</umb-mini-list-view>
|
||||||
|
|
||||||
<div class="umb-control-group -no-border" ng-hide="vm.searchInfo.showSearch">
|
|
||||||
<umb-tree
|
|
||||||
section="{{model.section}}"
|
|
||||||
hideheader="false"
|
|
||||||
hideoptions="true"
|
|
||||||
isdialog="true"
|
|
||||||
eventhandler="dialogTreeEventHandler"
|
|
||||||
enablecheckboxes="true">
|
|
||||||
</umb-tree>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+8
-3
@@ -122,9 +122,14 @@
|
|||||||
query.filters.push({});
|
query.filters.push({});
|
||||||
}
|
}
|
||||||
|
|
||||||
function trashFilter(query) {
|
function trashFilter(query, filter) {
|
||||||
query.filters.splice(query, 1);
|
for (var i = 0; i < query.filters.length; i++)
|
||||||
|
{
|
||||||
|
if (query.filters[i] == filter)
|
||||||
|
{
|
||||||
|
query.filters.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
//if we remove the last one, add a new one to generate ui for it.
|
//if we remove the last one, add a new one to generate ui for it.
|
||||||
if (query.filters.length == 0) {
|
if (query.filters.length == 0) {
|
||||||
query.filters.push({});
|
query.filters.push({});
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
<i class="icon-add"></i>
|
<i class="icon-add"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href ng-click="vm.trashFilter(vm.query)">
|
<a href ng-click="vm.trashFilter(vm.query, filter)">
|
||||||
<i class="icon-trash"></i>
|
<i class="icon-trash"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|||||||
+2
@@ -10,6 +10,8 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
|
|||||||
$scope.treeAlias = dialogOptions.treeAlias;
|
$scope.treeAlias = dialogOptions.treeAlias;
|
||||||
$scope.multiPicker = dialogOptions.multiPicker;
|
$scope.multiPicker = dialogOptions.multiPicker;
|
||||||
$scope.hideHeader = true;
|
$scope.hideHeader = true;
|
||||||
|
// if you need to load a not initialized tree set this value to false - default is true
|
||||||
|
$scope.onlyInitialized = dialogOptions.onlyInitialized;
|
||||||
$scope.searchInfo = {
|
$scope.searchInfo = {
|
||||||
searchFromId: dialogOptions.startNodeId,
|
searchFromId: dialogOptions.startNodeId,
|
||||||
searchFromName: null,
|
searchFromName: null,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
hideheader="{{hideHeader}}"
|
hideheader="{{hideHeader}}"
|
||||||
hideoptions="true"
|
hideoptions="true"
|
||||||
isdialog="true"
|
isdialog="true"
|
||||||
|
onlyinitialized="{{onlyInitialized}}"
|
||||||
customtreeparams="{{customTreeParams}}"
|
customtreeparams="{{customTreeParams}}"
|
||||||
eventhandler="dialogTreeEventHandler"
|
eventhandler="dialogTreeEventHandler"
|
||||||
enablelistviewsearch="true"
|
enablelistviewsearch="true"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<a class="icon icon-arrow-left" ng-if="showSearch == 'true'" title="Back" ng-click="hideSearch()"></a>
|
<a class="icon icon-arrow-left" ng-if="showSearch == 'true'" title="Back" ng-click="hideSearch()"></a>
|
||||||
<input type="text"
|
<input type="text"
|
||||||
ng-model="term"
|
ng-model="term"
|
||||||
class="umb-search-field search-query"
|
class="umb-search-field search-query -full-width-input"
|
||||||
placeholder="{{searchPlaceholderText}}"
|
placeholder="{{searchPlaceholderText}}"
|
||||||
focus-when="{{showSearch}}">
|
focus-when="{{showSearch}}">
|
||||||
<h4 ng-if="showSearch && searchFromName">
|
<h4 ng-if="showSearch && searchFromName">
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
|
|
||||||
<ng-form name="groupSortOrderForm">
|
<ng-form name="groupSortOrderForm">
|
||||||
<div class="umb-group-builder__group-sort-order" ng-if="sortingMode">
|
<div class="umb-group-builder__group-sort-order" ng-if="sortingMode">
|
||||||
<input name="groupSortOrder" type="number" class="umb-group-builder__group-sort-value" ng-model="tab.sortOrder" ng-disabled="tab.inherited" on-blur="changeSortOrderValue(tab)" required />
|
<input name="groupSortOrder" type="number" class="umb-editor-tiny" style="margin-bottom: 0;" ng-model="tab.sortOrder" ng-disabled="tab.inherited" on-blur="changeSortOrderValue(tab)" required />
|
||||||
<div class="umb-validation-label -arrow-left" ng-if="groupSortOrderForm.groupSortOrder.$error.required && tab.showSortOrderMissing"><localize key="required"></localize></div>
|
<div class="umb-validation-label -arrow-left" ng-if="groupSortOrderForm.groupSortOrder.$error.required && tab.showSortOrderMissing"><localize key="required"></localize></div>
|
||||||
<div class="umb-validation-label -arrow-left" ng-if="!tab.showSortOrderMissing" val-msg-for="groupSortOrder" val-toggle-msg="required"><localize key="required"></localize></div>
|
<div class="umb-validation-label -arrow-left" ng-if="!tab.showSortOrderMissing" val-msg-for="groupSortOrder" val-toggle-msg="required"><localize key="required"></localize></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,54 +22,29 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
|
|||||||
var node = dialogOptions.currentNode;
|
var node = dialogOptions.currentNode;
|
||||||
|
|
||||||
function nodeSelectHandler(ev, args) {
|
function nodeSelectHandler(ev, args) {
|
||||||
args.event.preventDefault();
|
|
||||||
args.event.stopPropagation();
|
|
||||||
|
|
||||||
if (args.node.metaData.listViewNode) {
|
if(args && args.event) {
|
||||||
//check if list view 'search' node was selected
|
args.event.preventDefault();
|
||||||
|
args.event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
$scope.searchInfo.showSearch = true;
|
eventsService.emit("editors.content.copyController.select", args);
|
||||||
$scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
|
||||||
$scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
eventsService.emit("editors.content.copyController.select", args);
|
|
||||||
|
|
||||||
if ($scope.target) {
|
if ($scope.target) {
|
||||||
//un-select if there's a current one selected
|
//un-select if there's a current one selected
|
||||||
$scope.target.selected = false;
|
$scope.target.selected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.target = args.node;
|
$scope.target = args.node;
|
||||||
$scope.target.selected = true;
|
$scope.target.selected = true;
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeExpandedHandler(ev, args) {
|
function nodeExpandedHandler(ev, args) {
|
||||||
if (angular.isArray(args.children)) {
|
// open mini list view for list views
|
||||||
|
if (args.node.metaData.isContainer) {
|
||||||
//iterate children
|
openMiniListView(args.node);
|
||||||
_.each(args.children, function (child) {
|
}
|
||||||
//check if any of the items are list views, if so we need to add a custom
|
|
||||||
// child: A node to activate the search
|
|
||||||
if (child.metaData.isContainer) {
|
|
||||||
child.hasChildren = true;
|
|
||||||
child.children = [
|
|
||||||
{
|
|
||||||
level: child.level + 1,
|
|
||||||
hasChildren: false,
|
|
||||||
name: searchText,
|
|
||||||
metaData: {
|
|
||||||
listViewNode: child,
|
|
||||||
},
|
|
||||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
|
||||||
cssClasses: ["not-published"]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.hideSearch = function () {
|
$scope.hideSearch = function () {
|
||||||
@@ -136,4 +111,19 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
|
|||||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mini list view
|
||||||
|
$scope.selectListViewNode = function (node) {
|
||||||
|
node.selected = node.selected === true ? false : true;
|
||||||
|
nodeSelectHandler({}, { node: node });
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.closeMiniListView = function () {
|
||||||
|
$scope.miniListView = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
function openMiniListView(node) {
|
||||||
|
$scope.miniListView = node;
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,53 +20,29 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.MoveController",
|
|||||||
var node = dialogOptions.currentNode;
|
var node = dialogOptions.currentNode;
|
||||||
|
|
||||||
function nodeSelectHandler(ev, args) {
|
function nodeSelectHandler(ev, args) {
|
||||||
args.event.preventDefault();
|
|
||||||
args.event.stopPropagation();
|
|
||||||
|
|
||||||
if (args.node.metaData.listViewNode) {
|
if(args && args.event) {
|
||||||
//check if list view 'search' node was selected
|
args.event.preventDefault();
|
||||||
|
args.event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
$scope.searchInfo.showSearch = true;
|
eventsService.emit("editors.content.moveController.select", args);
|
||||||
$scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
|
||||||
$scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
eventsService.emit("editors.content.moveController.select", args);
|
|
||||||
|
|
||||||
if ($scope.target) {
|
if ($scope.target) {
|
||||||
//un-select if there's a current one selected
|
//un-select if there's a current one selected
|
||||||
$scope.target.selected = false;
|
$scope.target.selected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.target = args.node;
|
||||||
|
$scope.target.selected = true;
|
||||||
|
|
||||||
$scope.target = args.node;
|
|
||||||
$scope.target.selected = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeExpandedHandler(ev, args) {
|
function nodeExpandedHandler(ev, args) {
|
||||||
if (angular.isArray(args.children)) {
|
// open mini list view for list views
|
||||||
|
if (args.node.metaData.isContainer) {
|
||||||
//iterate children
|
openMiniListView(args.node);
|
||||||
_.each(args.children, function (child) {
|
}
|
||||||
//check if any of the items are list views, if so we need to add a custom
|
|
||||||
// child: A node to activate the search
|
|
||||||
if (child.metaData.isContainer) {
|
|
||||||
child.hasChildren = true;
|
|
||||||
child.children = [
|
|
||||||
{
|
|
||||||
level: child.level + 1,
|
|
||||||
hasChildren: false,
|
|
||||||
name: searchText,
|
|
||||||
metaData: {
|
|
||||||
listViewNode: child,
|
|
||||||
},
|
|
||||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
|
||||||
cssClasses: ["not-published"]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.hideSearch = function () {
|
$scope.hideSearch = function () {
|
||||||
@@ -136,4 +112,19 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.MoveController",
|
|||||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mini list view
|
||||||
|
$scope.selectListViewNode = function (node) {
|
||||||
|
node.selected = node.selected === true ? false : true;
|
||||||
|
nodeSelectHandler({}, { node: node });
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.closeMiniListView = function () {
|
||||||
|
$scope.miniListView = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
function openMiniListView(node) {
|
||||||
|
$scope.miniListView = node;
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -1,6 +1,22 @@
|
|||||||
<div ng-controller="Umbraco.Editors.Content.CopyController">
|
<div ng-controller="Umbraco.Editors.Content.CopyController">
|
||||||
<div class="umb-dialog-body form-horizontal">
|
<div class="umb-dialog-body form-horizontal" ng-cloak>
|
||||||
<div class="umb-pane">
|
<div class="umb-pane">
|
||||||
|
|
||||||
|
<div ng-show="error">
|
||||||
|
<div class="alert alert-error">
|
||||||
|
<div><strong>{{error.errorMsg}}</strong></div>
|
||||||
|
<div>{{error.data.message}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-show="success">
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<strong>{{currentNode.name}}</strong> was copied to
|
||||||
|
<strong>{{target.name}}</strong>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p class="abstract" ng-hide="success">
|
<p class="abstract" ng-hide="success">
|
||||||
Choose where to copy <strong>{{currentNode.name}}</strong> to in the tree structure below
|
Choose where to copy <strong>{{currentNode.name}}</strong> to in the tree structure below
|
||||||
</p>
|
</p>
|
||||||
@@ -9,52 +25,51 @@
|
|||||||
<div class="umb-loader"></div>
|
<div class="umb-loader"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-show="error">
|
|
||||||
<h5 class="text-error">{{error.errorMsg}}</h5>
|
|
||||||
<p class="text-error">{{error.data.message}}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-success" ng-show="success">
|
|
||||||
<p>
|
|
||||||
<strong>{{currentNode.name}}</strong> was copied to
|
|
||||||
<strong>{{target.name}}</strong>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-hide="success">
|
<div ng-hide="success">
|
||||||
|
|
||||||
<umb-tree-search-box hide-search-callback="hideSearch"
|
<div ng-hide="miniListView">
|
||||||
search-callback="onSearchResults"
|
<umb-tree-search-box
|
||||||
search-from-id="{{searchInfo.searchFromId}}"
|
hide-search-callback="hideSearch"
|
||||||
search-from-name="{{searchInfo.searchFromName}}"
|
search-callback="onSearchResults"
|
||||||
show-search="{{searchInfo.showSearch}}"
|
search-from-id="{{searchInfo.searchFromId}}"
|
||||||
section="{{section}}">
|
search-from-name="{{searchInfo.searchFromName}}"
|
||||||
</umb-tree-search-box>
|
show-search="{{searchInfo.showSearch}}"
|
||||||
|
section="{{section}}">
|
||||||
|
</umb-tree-search-box>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<umb-tree-search-results ng-if="searchInfo.showSearch"
|
<umb-tree-search-results
|
||||||
results="searchInfo.results"
|
ng-if="searchInfo.showSearch"
|
||||||
select-result-callback="selectResult">
|
results="searchInfo.results"
|
||||||
</umb-tree-search-results>
|
select-result-callback="selectResult">
|
||||||
|
</umb-tree-search-results>
|
||||||
|
|
||||||
<div ng-hide="searchInfo.showSearch">
|
<div ng-hide="searchInfo.showSearch">
|
||||||
<umb-tree section="content"
|
<umb-tree
|
||||||
hideheader="false"
|
section="content"
|
||||||
hideoptions="true"
|
hideheader="false"
|
||||||
isdialog="true"
|
hideoptions="true"
|
||||||
eventhandler="dialogTreeEventHandler"
|
isdialog="true"
|
||||||
enablecheckboxes="true">
|
eventhandler="dialogTreeEventHandler"
|
||||||
</umb-tree>
|
enablelistviewexpand="true"
|
||||||
|
enablecheckboxes="true">
|
||||||
|
</umb-tree>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<umb-mini-list-view
|
||||||
|
ng-if="miniListView"
|
||||||
|
node="miniListView"
|
||||||
|
entity-type="Document"
|
||||||
|
on-select="selectListViewNode(node)"
|
||||||
|
on-close="closeMiniListView()">
|
||||||
|
</umb-mini-list-view>
|
||||||
|
|
||||||
<umb-pane>
|
<umb-pane>
|
||||||
<umb-control-group localize="label" label="@defaultdialogs_relateToOriginalLabel">
|
<umb-control-group localize="label" label="@defaultdialogs_relateToOriginalLabel">
|
||||||
<input type="checkbox" ng-model="$parent.$parent.relateToOriginal"/>
|
<input type="checkbox" ng-model="$parent.$parent.relateToOriginal"/>
|
||||||
</umb-control-group>
|
</umb-control-group>
|
||||||
|
|
||||||
</umb-pane>
|
</umb-pane>
|
||||||
|
|
||||||
<umb-pane>
|
<umb-pane>
|
||||||
|
|||||||
@@ -1,7 +1,21 @@
|
|||||||
<div ng-controller="Umbraco.Editors.Content.MoveController">
|
<div ng-controller="Umbraco.Editors.Content.MoveController">
|
||||||
<div class="umb-dialog-body">
|
<div class="umb-dialog-body" ng-cloak>
|
||||||
<div class="umb-pane">
|
<div class="umb-pane">
|
||||||
|
|
||||||
|
<div ng-show="error">
|
||||||
|
<div class="alert alert-error">
|
||||||
|
<div><strong>{{error.errorMsg}}</strong></div>
|
||||||
|
<div>{{error.data.message}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-show="success">
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<strong>{{currentNode.name}}</strong> was moved underneath <strong>{{target.name}}</strong>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p class="abstract" ng-hide="success">
|
<p class="abstract" ng-hide="success">
|
||||||
<localize key="actions_chooseWhereToMove">Choose where to move</localize>
|
<localize key="actions_chooseWhereToMove">Choose where to move</localize>
|
||||||
<strong>{{currentNode.name}}</strong>
|
<strong>{{currentNode.name}}</strong>
|
||||||
@@ -12,43 +26,47 @@
|
|||||||
<div class="umb-loader"></div>
|
<div class="umb-loader"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-show="error">
|
|
||||||
<h5 class="text-error">{{error.errorMsg}}</h5>
|
|
||||||
<p class="text-error">{{error.data.message}}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-show="success">
|
|
||||||
<h5 class="text-success"><strong>{{currentNode.name}}</strong> was moved underneath <strong>{{target.name}}</strong></h5>
|
|
||||||
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-hide="success">
|
<div ng-hide="success">
|
||||||
|
|
||||||
<umb-tree-search-box hide-search-callback="hideSearch"
|
<div ng-hide="miniListView">
|
||||||
search-callback="onSearchResults"
|
<umb-tree-search-box
|
||||||
search-from-id="{{searchInfo.searchFromId}}"
|
hide-search-callback="hideSearch"
|
||||||
search-from-name="{{searchInfo.searchFromName}}"
|
search-callback="onSearchResults"
|
||||||
show-search="{{searchInfo.showSearch}}"
|
search-from-id="{{searchInfo.searchFromId}}"
|
||||||
section="{{section}}">
|
search-from-name="{{searchInfo.searchFromName}}"
|
||||||
</umb-tree-search-box>
|
show-search="{{searchInfo.showSearch}}"
|
||||||
|
section="{{section}}">
|
||||||
|
</umb-tree-search-box>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<umb-tree-search-results ng-if="searchInfo.showSearch"
|
<umb-tree-search-results
|
||||||
results="searchInfo.results"
|
ng-if="searchInfo.showSearch"
|
||||||
select-result-callback="selectResult">
|
results="searchInfo.results"
|
||||||
</umb-tree-search-results>
|
select-result-callback="selectResult">
|
||||||
|
</umb-tree-search-results>
|
||||||
|
|
||||||
<div ng-hide="searchInfo.showSearch">
|
<div ng-hide="searchInfo.showSearch">
|
||||||
<umb-tree section="content"
|
<umb-tree
|
||||||
hideheader="false"
|
section="content"
|
||||||
hideoptions="true"
|
hideheader="false"
|
||||||
isdialog="true"
|
hideoptions="true"
|
||||||
eventhandler="dialogTreeEventHandler"
|
isdialog="true"
|
||||||
enablecheckboxes="true">
|
eventhandler="dialogTreeEventHandler"
|
||||||
</umb-tree>
|
enablelistviewexpand="true"
|
||||||
|
enablecheckboxes="true">
|
||||||
|
</umb-tree>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<umb-mini-list-view
|
||||||
|
ng-if="miniListView"
|
||||||
|
node="miniListView"
|
||||||
|
entity-type="Document"
|
||||||
|
on-select="selectListViewNode(node)"
|
||||||
|
on-close="closeMiniListView()">
|
||||||
|
</umb-mini-list-view>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,6 +22,51 @@ function startUpDynamicContentController(dashboardResource, assetsService) {
|
|||||||
var vm = this;
|
var vm = this;
|
||||||
vm.loading = true;
|
vm.loading = true;
|
||||||
vm.showDefault = false;
|
vm.showDefault = false;
|
||||||
|
|
||||||
|
// default dashboard content
|
||||||
|
vm.defaultDashboard = {
|
||||||
|
infoBoxes: [
|
||||||
|
{
|
||||||
|
title: "Documentation",
|
||||||
|
description: "Find the answers to your Umbraco questions",
|
||||||
|
url: "https://our.umbraco.org/documentation/?utm_source=core&utm_medium=dashboard&utm_content=text&utm_campaign=documentation/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Community",
|
||||||
|
description: "Find the answers or ask your Umbraco questions",
|
||||||
|
url: "https://our.umbraco.org/?utm_source=core&utm_medium=dashboard&utm_content=text&utm_campaign=our_forum"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Umbraco.tv",
|
||||||
|
description: "Tutorial videos (some are free, some are on subscription)",
|
||||||
|
url: "https://umbraco.tv/?utm_source=core&utm_medium=dashboard&utm_content=text&utm_campaign=tutorial_videos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Training",
|
||||||
|
description: "Real-life training and official Umbraco certifications",
|
||||||
|
url: "https://umbraco.com/training/?utm_source=core&utm_medium=dashboard&utm_content=text&utm_campaign=training"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
articles: [
|
||||||
|
{
|
||||||
|
title: "Umbraco.TV - Learn from the source!",
|
||||||
|
description: "Umbraco.TV will help you go from zero to Umbraco hero at a pace that suits you. Our easy to follow online training videos will give you the fundamental knowledge to start building awesome Umbraco websites.",
|
||||||
|
img: "views/dashboard/default/umbracotv.jpg",
|
||||||
|
url: "https://umbraco.tv/?utm_source=core&utm_medium=dashboard&utm_content=image&utm_campaign=tv",
|
||||||
|
altText: "Umbraco.TV - Hours of Umbraco Video Tutorials",
|
||||||
|
buttonText: "Visit Umbraco.TV"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Our Umbraco - The Friendliest Community",
|
||||||
|
description: "Our Umbraco - the official community site is your one stop for everything Umbraco. Whether you need a question answered or looking for cool plugins, the world's best and friendliest community is just a click away.",
|
||||||
|
img: "views/dashboard/default/ourumbraco.jpg",
|
||||||
|
url: "https://our.umbraco.org/?utm_source=core&utm_medium=dashboard&utm_content=image&utm_campaign=our",
|
||||||
|
altText: "Our Umbraco",
|
||||||
|
buttonText: "Visit Our Umbraco"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//proxy remote css through the local server
|
//proxy remote css through the local server
|
||||||
assetsService.loadCss( dashboardResource.getRemoteDashboardCssUrl("content") );
|
assetsService.loadCss( dashboardResource.getRemoteDashboardCssUrl("content") );
|
||||||
|
|||||||
@@ -38,58 +38,34 @@
|
|||||||
|
|
||||||
<!-- Default content in case we cannot fetch content from the outside -->
|
<!-- Default content in case we cannot fetch content from the outside -->
|
||||||
<div style="max-width: 1200px" ng-if="vm.showDefault">
|
<div style="max-width: 1200px" ng-if="vm.showDefault">
|
||||||
<h3><strong>Welcome to The Friendly CMS</strong></h3>
|
|
||||||
<p style="font-size: 16px; line-height: 1.5; margin-bottom: 30px; max-width: 760px;">
|
|
||||||
<span>Thank you for choosing Umbraco - we think this could be the beginning of something beautiful. While it may feel overwhelming at first, we've done a lot to make the learning curve as smooth and fast as possible.</span>
|
|
||||||
</p>
|
|
||||||
<h4>Find out more:</h4>
|
|
||||||
<ul>
|
|
||||||
<li>Find the answers to your Umbraco questions in <a href="https://our.umbraco.org/documentation/" target="_blank" class="btn-link-underline">our Documentation</a></li>
|
|
||||||
<li>Ask a question in the <a href="https://our.umbraco.org" target="_blank" class="btn-link-underline">Community Forum</a></li>
|
|
||||||
<li>Find <a href="https://our.umbraco.org/projects" target="_blank" class="btn-link-underline">an add-on package</a> to help you get going quickly</li>
|
|
||||||
<li>Watch <a href="https://umbraco.tv" class="btn-link-underline">our tutorial videos</a> (some are free, some require a subscription)</li>
|
|
||||||
<li>Find out about <a href="https://umbraco.com/products-and-support" target="_blank" class="btn-link-underline">our productivity boosting tools and commercial support</a></li>
|
|
||||||
<li>Find out about <a href="https://umbraco.com/products/training" target="_blank" class="btn-link-underline">real-life training and certification opportunities</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="welcome-dashboard__intro">
|
||||||
<div class="span4">
|
<h1 class="welcome-dashboard__title">Welcome to The Friendly CMS</h1>
|
||||||
<a href="https://umbraco.tv/?utm_source=core&utm_medium=dashboard&utm_content=image&utm_campaign=tv" target="_blank" class="nounderline">
|
<p class="welcome-dashboard__intro-text">Thank you for choosing Umbraco - we think this could be the beginning of something beautiful. While it may feel overwhelming at first, we've done a lot to make the learning curve as smooth and fast as possible.</p>
|
||||||
<img src="views/dashboard/default/umbracotv.png" alt="Umbraco.TV - Hours of Umbraco Video Tutorials" style="margin: 10px 0 10px 0" />
|
</div>
|
||||||
</a>
|
|
||||||
|
|
||||||
|
<div class="welcome-dashboard__info-box-boxes">
|
||||||
|
<a ng-href="{{infoBox.url}}" target="_blank" class="welcome-dashboard__info-box" ng-repeat="infoBox in vm.defaultDashboard.infoBoxes">
|
||||||
|
<div class="welcome-dashboard__info-box-title">{{ infoBox.title }}</div>
|
||||||
|
<div class="welcome-dashboard__info-box-description">{{ infoBox.description }}</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<a href="https://umbraco.tv/?utm_source=core&utm_medium=dashboard&utm_content=header&utm_campaign=tv" target="_blank" class="btn-link -underline">
|
<div class="welcome-dashboard__cards">
|
||||||
<h4> <strong>Umbraco.TV - Learn from the source!</strong> </h4>
|
<div class="welcome-dashboard__card" ng-repeat="article in vm.defaultDashboard.articles">
|
||||||
</a>
|
<div class="welcome-dashboard__card-image-wrapper">
|
||||||
|
<a ng-href="{{article.url}}" target="_blank">
|
||||||
<p style="line-height: 1.5;">
|
<img class="welcome-dashboard__card-image" ng-src="{{article.img}}" alt="{{ article.altText }}" />
|
||||||
Umbraco.TV will help you go from zero to Umbraco
|
</a>
|
||||||
hero at a pace that suits you. Our easy to follow
|
</div>
|
||||||
online training videos will give you the fundamental
|
<div class="welcome-dashboard__card-content">
|
||||||
knowledge to start building awesome Umbraco websites.
|
<h2 class="welcome-dashboard__card-title">{{ article.title }}</h2>
|
||||||
</p>
|
<div class="welcome-dashboard__card-teaser">{{ article.description }}</div>
|
||||||
</div>
|
<a class="btn btn-success" ng-href="{{article.url}}" target="_blank">{{article.buttonText}}</a>
|
||||||
|
</div>
|
||||||
<div class="span4 offset1">
|
|
||||||
|
|
||||||
<a href="https://our.umbraco.org/?utm_source=core&utm_medium=dashboard&utm_content=image&utm_campaign=our" target="_blank" class="nounderline">
|
|
||||||
<img src="views/dashboard/default/ourumbraco.png" alt="Our Umbraco" style="margin: 10px 0 10px 0" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://our.umbraco.org/?utm_source=core&utm_medium=dashboard&utm_content=header&utm_campaign=our" target="_blank" class="btn-link -underline">
|
|
||||||
<h4><strong>Our Umbraco - The Friendliest Community</strong></h4>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<p style="line-height: 1.5;">
|
|
||||||
Our Umbraco - the official community site is your one
|
|
||||||
stop for everything Umbraco. Whether you need a
|
|
||||||
question answered or looking for cool plugins, the
|
|
||||||
worlds best community is just a click away.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 104 KiB |
@@ -7,8 +7,11 @@ angular.module("umbraco").controller("Umbraco.Editors.Media.MoveController",
|
|||||||
var node = dialogOptions.currentNode;
|
var node = dialogOptions.currentNode;
|
||||||
|
|
||||||
function nodeSelectHandler(ev, args) {
|
function nodeSelectHandler(ev, args) {
|
||||||
args.event.preventDefault();
|
|
||||||
args.event.stopPropagation();
|
if(args && args.event) {
|
||||||
|
args.event.preventDefault();
|
||||||
|
args.event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
eventsService.emit("editors.media.moveController.select", args);
|
eventsService.emit("editors.media.moveController.select", args);
|
||||||
|
|
||||||
@@ -21,8 +24,15 @@ angular.module("umbraco").controller("Umbraco.Editors.Media.MoveController",
|
|||||||
$scope.target.selected = true;
|
$scope.target.selected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler);
|
function nodeExpandedHandler(ev, args) {
|
||||||
|
// open mini list view for list views
|
||||||
|
if (args.node.metaData.isContainer) {
|
||||||
|
openMiniListView(args.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler);
|
||||||
|
$scope.dialogTreeEventHandler.bind("treeNodeExpanded", nodeExpandedHandler);
|
||||||
|
|
||||||
$scope.move = function () {
|
$scope.move = function () {
|
||||||
mediaResource.move({ parentId: $scope.target.id, id: node.id })
|
mediaResource.move({ parentId: $scope.target.id, id: node.id })
|
||||||
@@ -55,5 +65,21 @@ angular.module("umbraco").controller("Umbraco.Editors.Media.MoveController",
|
|||||||
|
|
||||||
$scope.$on('$destroy', function () {
|
$scope.$on('$destroy', function () {
|
||||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||||
|
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Mini list view
|
||||||
|
$scope.selectListViewNode = function (node) {
|
||||||
|
node.selected = node.selected === true ? false : true;
|
||||||
|
nodeSelectHandler({}, { node: node });
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.closeMiniListView = function () {
|
||||||
|
$scope.miniListView = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
function openMiniListView(node) {
|
||||||
|
$scope.miniListView = node;
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -1,33 +1,49 @@
|
|||||||
<div ng-controller="Umbraco.Editors.Media.MoveController">
|
<div ng-controller="Umbraco.Editors.Media.MoveController">
|
||||||
<div class="umb-dialog-body">
|
<div class="umb-dialog-body" ng-cloak>
|
||||||
<div class="umb-pane">
|
<div class="umb-pane">
|
||||||
|
|
||||||
|
<div ng-show="error">
|
||||||
|
<div class="alert alert-error">
|
||||||
|
<div><strong>{{error.errorMsg}}</strong></div>
|
||||||
|
<div>{{error.data.message}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-show="success">
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<strong>{{currentNode.name}}</strong> was moved underneath <strong>{{target.name}}</strong>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p class="abstract" ng-hide="success">
|
<p class="abstract" ng-hide="success">
|
||||||
<localize key="actions_chooseWhereToMove">Choose where to move</localize>
|
<localize key="actions_chooseWhereToMove">Choose where to move</localize>
|
||||||
<strong>{{currentNode.name}}</strong>
|
<strong>{{currentNode.name}}</strong>
|
||||||
<localize key="actions_toInTheTreeStructureBelow">to in the tree structure below</localize>
|
<localize key="actions_toInTheTreeStructureBelow">to in the tree structure below</localize>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="alert alert-error" ng-show="error" ng-cloak>
|
|
||||||
<h4>{{error.errorMsg}}</h4>
|
|
||||||
<p>{{error.data.Message}}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-success" ng-show="success" ng-cloak>
|
|
||||||
<p><strong>{{currentNode.name}}</strong> was moved underneath
|
|
||||||
<strong>{{target.name}}</strong></p>
|
|
||||||
|
|
||||||
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-hide="success">
|
<div ng-hide="success">
|
||||||
<umb-tree section="media"
|
|
||||||
hideheader="false"
|
<div ng-hide="miniListView">
|
||||||
hideoptions="true"
|
<umb-tree
|
||||||
isdialog="true"
|
section="media"
|
||||||
eventhandler="dialogTreeEventHandler"
|
hideheader="false"
|
||||||
enablecheckboxes="true">
|
hideoptions="true"
|
||||||
</umb-tree>
|
isdialog="true"
|
||||||
|
eventhandler="dialogTreeEventHandler"
|
||||||
|
enablelistviewexpand="true"
|
||||||
|
enablecheckboxes="true">
|
||||||
|
</umb-tree>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<umb-mini-list-view
|
||||||
|
ng-if="miniListView"
|
||||||
|
node="miniListView"
|
||||||
|
entity-type="Media"
|
||||||
|
on-select="selectListViewNode(node)"
|
||||||
|
on-close="closeMiniListView()">
|
||||||
|
</umb-mini-list-view>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,47 +1,42 @@
|
|||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function PartialViewMacrosCreateController($scope, codefileResource, $location, navigationService, formHelper, localizationService, appState) {
|
function PartialViewMacrosCreateController($scope, codefileResource, macroResource, $location, navigationService, formHelper, localizationService, appState) {
|
||||||
|
|
||||||
var vm = this;
|
var vm = this;
|
||||||
var node = $scope.dialogOptions.currentNode;
|
var node = $scope.dialogOptions.currentNode;
|
||||||
var localizeCreateFolder = localizationService.localize("defaultdialog_createFolder");
|
var localizeCreateFolder = localizationService.localize("defaultdialog_createFolder");
|
||||||
|
|
||||||
vm.snippets = [];
|
vm.snippets = [];
|
||||||
vm.showSnippets = false;
|
vm.snippet = "Empty";
|
||||||
vm.creatingFolder = false;
|
vm.createMacro = false;
|
||||||
vm.createFolderError = "";
|
vm.createFolderError = "";
|
||||||
vm.folderName = "";
|
vm.folderName = "";
|
||||||
|
vm.fileName = "";
|
||||||
|
|
||||||
|
vm.creatingFolder = false;
|
||||||
|
vm.creatingFile = false;
|
||||||
|
|
||||||
vm.createPartialViewMacro = createPartialViewMacro;
|
|
||||||
vm.showCreateFolder = showCreateFolder;
|
vm.showCreateFolder = showCreateFolder;
|
||||||
|
vm.showCreateFile = showCreateFile;
|
||||||
vm.createFolder = createFolder;
|
vm.createFolder = createFolder;
|
||||||
vm.showCreateFromSnippet = showCreateFromSnippet;
|
vm.createFile = createFile;
|
||||||
|
|
||||||
function onInit() {
|
function onInit() {
|
||||||
codefileResource.getSnippets('partialViewMacros')
|
codefileResource.getSnippets('partialViewMacros')
|
||||||
.then(function(snippets) {
|
.then(function (snippets) {
|
||||||
vm.snippets = snippets;
|
vm.snippets = snippets;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createPartialViewMacro(selectedSnippet) {
|
|
||||||
|
|
||||||
var snippet = null;
|
|
||||||
|
|
||||||
if(selectedSnippet && selectedSnippet.fileName) {
|
|
||||||
snippet = selectedSnippet.fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
$location.path("/developer/partialviewmacros/edit/" + node.id).search("create", "true").search("snippet", snippet);
|
|
||||||
navigationService.hideMenu();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function showCreateFolder() {
|
function showCreateFolder() {
|
||||||
vm.creatingFolder = true;
|
vm.creatingFolder = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showCreateFile() {
|
||||||
|
vm.creatingFile = true;
|
||||||
|
}
|
||||||
|
|
||||||
function createFolder(form) {
|
function createFolder(form) {
|
||||||
if (formHelper.submitForm({scope: $scope, formCtrl: form, statusMessage: localizeCreateFolder})) {
|
if (formHelper.submitForm({scope: $scope, formCtrl: form, statusMessage: localizeCreateFolder})) {
|
||||||
|
|
||||||
@@ -75,11 +70,32 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showCreateFromSnippet() {
|
function createFile(form) {
|
||||||
vm.showSnippets = true;
|
if (formHelper.submitForm({ scope: $scope, formCtrl: form, statusMessage: 'create file' })) {
|
||||||
|
|
||||||
|
if (vm.createMacro) {
|
||||||
|
var path = decodeURIComponent(node.id);
|
||||||
|
macroResource.createPartialViewMacroWithFile(path, vm.fileName).then(function(created) {
|
||||||
|
$location.path("/developer/partialviewmacros/edit/" + node.id).search("create", "true").search("name", vm.fileName).search("snippet", vm.snippet);
|
||||||
|
navigationService.hideMenu();
|
||||||
|
}, function(err) {
|
||||||
|
vm.createFileError = err;
|
||||||
|
|
||||||
|
//show any notifications
|
||||||
|
if (angular.isArray(err.data.notifications)) {
|
||||||
|
for (var i = 0; i < err.data.notifications.length; i++) {
|
||||||
|
notificationsService.showNotification(err.data.notifications[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$location.path("/developer/partialviewmacros/edit/" + node.id).search("create", "true").search("name", vm.fileName).search("snippet", vm.snippet);
|
||||||
|
navigationService.hideMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onInit();
|
onInit();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,46 +2,61 @@
|
|||||||
|
|
||||||
<div class="umbracoDialog umb-dialog-body with-footer">
|
<div class="umbracoDialog umb-dialog-body with-footer">
|
||||||
|
|
||||||
<div class="umb-pane" ng-if="!vm.creatingFolder">
|
<div class="umb-pane" ng-if="!vm.creatingFolder && !vm.creatingFile">
|
||||||
|
|
||||||
<h5><localize key="create_createUnder">Create an item under</localize> {{currentNode.name}}</h5>
|
<h5><localize key="create_createUnder">Create an item under</localize> {{currentNode.name}}</h5>
|
||||||
|
|
||||||
<!-- Main options -->
|
<!-- Main options -->
|
||||||
<div ng-if="!vm.showSnippets">
|
<ul class="umb-actions umb-actions-child">
|
||||||
<ul class="umb-actions umb-actions-child">
|
<li>
|
||||||
<li>
|
<a href="" ng-click="vm.showCreateFile()" umb-auto-focus>
|
||||||
<a href="" ng-click="vm.createPartialViewMacro()" umb-auto-focus>
|
<i class="large icon-article"></i>
|
||||||
<i class="large icon-article"></i>
|
<span class="menu-label"><localize key="create_newPartialViewMacro">New partial view macro</localize></span>
|
||||||
<span class="menu-label"><localize key="create_newEmptyPartialViewMacro">New empty partial view macro</localize></span>
|
</a>
|
||||||
</a>
|
</li>
|
||||||
</li>
|
<li>
|
||||||
<li>
|
<a href="" ng-click="vm.showCreateFolder()">
|
||||||
<a href="" ng-click="vm.showCreateFromSnippet()">
|
<i class="large icon-folder"></i>
|
||||||
<i class="large icon-article"></i>
|
<span class="menu-label"><localize key="general_folder"></localize></span>
|
||||||
<span class="menu-label"><localize key="create_newPartialViewMacroFromSnippet">New partial view macro from snippet</localize></span>
|
</a>
|
||||||
</a>
|
</li>
|
||||||
</li>
|
</ul>
|
||||||
<li>
|
|
||||||
<a href="" ng-click="vm.showCreateFolder()">
|
|
||||||
<i class="large icon-folder"></i>
|
|
||||||
<span class="menu-label"><localize key="general_folder"></localize></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Snippets list -->
|
</div>
|
||||||
<div ng-if="vm.showSnippets">
|
|
||||||
<ul class="umb-actions umb-actions-child">
|
|
||||||
<li ng-repeat="snippet in vm.snippets">
|
|
||||||
<a href="" ng-click="vm.createPartialViewMacro(snippet)" style="padding-top: 6px; padding-bottom: 6px;">
|
|
||||||
<i class="icon-article" style="font-size: 20px;"></i>
|
|
||||||
<span class="menu-label" style="margin-left: 0; padding-left: 5px;">{{ snippet.name }}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<!-- Create file -->
|
||||||
|
<div class="umb-pane" ng-if="vm.creatingFile">
|
||||||
|
<form novalidate name="createFileForm"
|
||||||
|
ng-submit="vm.createFile(createFileForm)"
|
||||||
|
val-form-manager>
|
||||||
|
|
||||||
|
<div ng-show="vm.createFileError">
|
||||||
|
<h5 class="text-error">{{vm.createFileError.errorMsg}}</h5>
|
||||||
|
<p class="text-error">{{vm.createFileError.data.message}}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<umb-control-group label="Enter a file name" hide-label="false">
|
||||||
|
<input type="text" name="fileName" ng-model="vm.fileName" class="umb-textstring textstring input-block-level" umb-auto-focus required no-dirty-check />
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="checkbox">
|
||||||
|
<input type="checkbox" name="createMacro" ng-model="vm.createMacro" ng-true-value="true" ng-false-value="false" no-dirty-check/>
|
||||||
|
Create corresponding macro
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</umb-control-group>
|
||||||
|
|
||||||
|
<umb-control-group label="Select a snippet (or create an empty file)" hide-label="false">
|
||||||
|
|
||||||
|
<select name="snippet"
|
||||||
|
class="umb-editor umb-dropdown"
|
||||||
|
ng-model="vm.snippet"
|
||||||
|
ng-options="snippet.fileName as snippet.name for snippet in vm.snippets"></select>
|
||||||
|
|
||||||
|
</umb-control-group>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Create folder -->
|
<!-- Create folder -->
|
||||||
@@ -49,14 +64,14 @@
|
|||||||
<form novalidate name="createFolderForm"
|
<form novalidate name="createFolderForm"
|
||||||
ng-submit="vm.createFolder(createFolderForm)"
|
ng-submit="vm.createFolder(createFolderForm)"
|
||||||
val-form-manager>
|
val-form-manager>
|
||||||
|
|
||||||
<div ng-show="vm.createFolderError">
|
<div ng-show="vm.createFolderError">
|
||||||
<h5 class="text-error">{{vm.createFolderError.errorMsg}}</h5>
|
<h5 class="text-error">{{vm.createFolderError.errorMsg}}</h5>
|
||||||
<p class="text-error">{{vm.createFolderError.data.message}}</p>
|
<p class="text-error">{{vm.createFolderError.data.message}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<umb-control-group label="Enter a folder name" hide-label="false">
|
<umb-control-group label="Enter a folder name" hide-label="false">
|
||||||
<input type="text" name="folderName" ng-model="vm.folderName" class="umb-textstring textstring input-block-level" umb-auto-focus required />
|
<input type="text" name="folderName" ng-model="vm.folderName" class="umb-textstring textstring input-block-level" umb-auto-focus required no-dirty-check />
|
||||||
</umb-control-group>
|
</umb-control-group>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
|
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user