Compare commits
128 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1dacbbdbf6 | |||
| f0b374c30b | |||
| ec5feee1f3 | |||
| 1d1d99ddad | |||
| c306f94a6a | |||
| 11b2ec89fd | |||
| 89596f00f1 | |||
| 4fa6e70e72 | |||
| a5a0a84d46 | |||
| 839431e6fa | |||
| 5369a6fc56 | |||
| 8a078e258f | |||
| fb42574c34 | |||
| 9ad3b6a337 | |||
| 65b16fbfe5 | |||
| 6ad2853bce | |||
| b2407eab98 | |||
| 778c7a836b | |||
| 11f9cdead0 | |||
| a1076d5443 | |||
| 4a11bf68f3 | |||
| fa64e73a43 | |||
| adf3e2dfe0 | |||
| c4c86cf5ce | |||
| 479aba8e1d | |||
| 0c474e2aba | |||
| 4f5b34cdfe | |||
| 0cb7f220ea | |||
| 0995b2cb5a | |||
| 1b37475144 | |||
| be0bacd895 | |||
| a2564bd0c3 | |||
| 402a5c9d56 | |||
| 2a2f22c7d9 | |||
| 372a768dca | |||
| f6e48243a6 | |||
| 94ea677ec0 | |||
| 55e7159f7d | |||
| 390a94e323 | |||
| 19fb920aa1 | |||
| f35e1604ca | |||
| b9765c3bec | |||
| d5a57c505c | |||
| 5f365241a8 | |||
| 9c121f0044 | |||
| f13bc07ddc | |||
| a707d23692 | |||
| 0929b7d42c | |||
| 35a9272b68 | |||
| 112453a032 | |||
| bba7367ba6 | |||
| 83e679ba5e | |||
| 05c35b22bd | |||
| 4d950fb4d4 | |||
| 0d191fb8bd | |||
| f6318fb6f3 | |||
| c7a3efadb1 | |||
| 956425dfbf | |||
| c616354522 | |||
| 17b29357d4 | |||
| 36246b96d4 | |||
| 7d8791ec86 | |||
| f349a9ae3e | |||
| 2719e2c231 | |||
| 57a766098d | |||
| dafde545b0 | |||
| 610538261e | |||
| f78cb8a970 | |||
| def276de01 | |||
| 293b170a56 | |||
| 9f7b82e20f | |||
| 6ba4efc416 | |||
| 981fb39af6 | |||
| c64f6f894e | |||
| 3e73c2da43 | |||
| 26a8d23039 | |||
| 2632ef740c | |||
| f024dba864 | |||
| 9758851a4b | |||
| 04b3532e9d | |||
| 38e56f0fea | |||
| 462baf91e4 | |||
| 01bcd3b623 | |||
| 64fd95bd22 | |||
| f1366c7d29 | |||
| baaa9340e4 | |||
| 183a5b5c43 | |||
| 1a0c095f40 | |||
| ffada74aa4 | |||
| f2fc70f731 | |||
| 866b0113e7 | |||
| 06c49daca7 | |||
| 9293008b94 | |||
| dbb9386d22 | |||
| 51ed441b85 | |||
| f566fec665 | |||
| 9d92781a97 | |||
| 123bfe5afe | |||
| 3383d2a2ac | |||
| cc6dfd0c55 | |||
| d4802fcef6 | |||
| 65c97040b3 | |||
| 0f8a13d60a | |||
| 5c1502c806 | |||
| 3cdebf4427 | |||
| 5176b68935 | |||
| 0bfc5f1272 | |||
| 39c18d4201 | |||
| 66ea8ae604 | |||
| 6fc794ca2e | |||
| df958223b0 | |||
| 1217d9f0b3 | |||
| 1301897f39 | |||
| 6d34fe416d | |||
| a884ece8b1 | |||
| 0ffcc9b889 | |||
| ee3131b63d | |||
| 4fd7182388 | |||
| ae85b7bf2b | |||
| b52c480da3 | |||
| dada91f006 | |||
| 348694d9d4 | |||
| 855e3b3dcc | |||
| 5a8ea4aa41 | |||
| 4bd465f666 | |||
| ad591c07cf | |||
| cd3aaa47ca | |||
| a05cc03254 |
@@ -72,7 +72,6 @@
|
||||
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.xml" target="lib\UmbracoExamine.xml" />
|
||||
<file src="tools\install.core.ps1" target="tools\install.ps1" />
|
||||
<file src="tools\uninstall.core.ps1" target="tools\uninstall.ps1" />
|
||||
|
||||
<!-- Added to be able to produce a symbols package -->
|
||||
<file src="..\_BuildOutput\bin\SQLCE4Umbraco.pdb" target="lib" />
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
<file src="..\_BuildOutput\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
|
||||
<file src="..\_BuildOutput\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
|
||||
<file src="tools\install.ps1" target="tools\install.ps1" />
|
||||
<file src="tools\uninstall.ps1" target="tools\uninstall.ps1" />
|
||||
<file src="tools\Readme.txt" target="tools\Readme.txt" />
|
||||
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
|
||||
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
<appSettings xdt:Transform="InsertIfMissing" />
|
||||
<appSettings>
|
||||
<add key="owin:appStartup" value="UmbracoDefaultOwinStartup" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
|
||||
<add key="Umbraco.ModelsBuilder.Enable" value="false" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
|
||||
<add key="Umbraco.ModelsBuilder.ModelsMode" value="Nothing" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
|
||||
</appSettings>
|
||||
|
||||
<umbracoConfiguration xdt:Transform="InsertIfMissing">
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
param($installPath, $toolsPath, $package, $project)
|
||||
|
||||
Write-Host "installPath:" "${installPath}"
|
||||
Write-Host "toolsPath:" "${toolsPath}"
|
||||
|
||||
Write-Host " "
|
||||
|
||||
if ($project) {
|
||||
|
||||
# Create paths and list them
|
||||
$projectPath = (Get-Item $project.Properties.Item("FullPath").Value).FullName
|
||||
Write-Host "projectPath:" "${projectPath}"
|
||||
$backupPath = Join-Path $projectPath "App_Data\NuGetBackup"
|
||||
Write-Host "backupPath:" "${backupPath}"
|
||||
$umbracoBinFolder = Join-Path $projectPath "bin"
|
||||
Write-Host "umbracoBinFolder:" "${umbracoBinFolder}"
|
||||
|
||||
# Remove backups
|
||||
Write-Host "removing backups:" "${backupPath}"
|
||||
if(Test-Path $backupPath) { Remove-Item -Recurse -Force $backupPath -Confirm:$false }
|
||||
|
||||
# Delete files Umbraco ships with
|
||||
|
||||
Write-Host "removing dlls:" "${umbracoBinFolder}"
|
||||
if(Test-Path $umbracoBinFolder\businesslogic.dll) { Remove-Item $umbracoBinFolder\businesslogic.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\cms.dll) { Remove-Item $umbracoBinFolder\cms.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\controls.dll) { Remove-Item $umbracoBinFolder\controls.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\interfaces.dll) { Remove-Item $umbracoBinFolder\interfaces.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\log4net.dll) { Remove-Item $umbracoBinFolder\log4net.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll) { Remove-Item $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\SQLCE4Umbraco.dll) { Remove-Item $umbracoBinFolder\SQLCE4Umbraco.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\TidyNet.dll) { Remove-Item $umbracoBinFolder\TidyNet.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\umbraco.dll) { Remove-Item $umbracoBinFolder\umbraco.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Umbraco.Core.dll) { Remove-Item $umbracoBinFolder\Umbraco.Core.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\umbraco.DataLayer.dll) { Remove-Item $umbracoBinFolder\umbraco.DataLayer.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\umbraco.editorControls.dll) { Remove-Item $umbracoBinFolder\umbraco.editorControls.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\umbraco.MacroEngines.dll) { Remove-Item $umbracoBinFolder\umbraco.MacroEngines.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\umbraco.providers.dll) { Remove-Item $umbracoBinFolder\umbraco.providers.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Umbraco.Web.UI.dll) { Remove-Item $umbracoBinFolder\Umbraco.Web.UI.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\UmbracoExamine.dll) { Remove-Item $umbracoBinFolder\UmbracoExamine.dll -Force -Confirm:$false }
|
||||
|
||||
$amd64Folder = Join-Path $umbracoBinFolder "amd64"
|
||||
if(Test-Path $amd64Folder) { Remove-Item $amd64Folder -Force -Recurse -Confirm:$false }
|
||||
$x86Folder = Join-Path $umbracoBinFolder "x86"
|
||||
if(Test-Path $x86Folder) { Remove-Item $x86Folder -Force -Recurse -Confirm:$false }
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
param($installPath, $toolsPath, $package, $project)
|
||||
|
||||
Write-Host "installPath:" "${installPath}"
|
||||
Write-Host "toolsPath:" "${toolsPath}"
|
||||
|
||||
Write-Host " "
|
||||
|
||||
if ($project) {
|
||||
|
||||
# Create paths and list them
|
||||
$projectPath = (Get-Item $project.Properties.Item("FullPath").Value).FullName
|
||||
Write-Host "projectPath:" "${projectPath}"
|
||||
$backupPath = Join-Path $projectPath "App_Data\NuGetBackup"
|
||||
Write-Host "backupPath:" "${backupPath}"
|
||||
$appBrowsers = Join-Path $projectPath "App_Browsers"
|
||||
Write-Host "appBrowsers:" "${appBrowsers}"
|
||||
$appData = Join-Path $projectPath "App_Data"
|
||||
Write-Host "appData:" "${appData}"
|
||||
|
||||
# Remove backups
|
||||
Write-Host "removing backups:" "${backupPath}"
|
||||
if(Test-Path $backupPath) { Remove-Item -Recurse -Force $backupPath -Confirm:$false }
|
||||
|
||||
# Remove app_data files
|
||||
Write-Host "removing app_data files:" "${appData}"
|
||||
if(Test-Path $appData\packages) { Remove-Item $appData\packages -Recurse -Force -Confirm:$false }
|
||||
|
||||
Write-Host "removing app_browsers:" "${appBrowsers}"
|
||||
if(Test-Path $appBrowsers\Form.browser) { Remove-Item $appBrowsers\Form.browser -Force -Confirm:$false }
|
||||
if(Test-Path $appBrowsers\w3cvalidator.browser) { Remove-Item $appBrowsers\w3cvalidator.browser -Force -Confirm:$false }
|
||||
|
||||
# Remove umbraco and umbraco_files
|
||||
$umbracoFolder = Join-Path $projectPath "Umbraco"
|
||||
Write-Host "removing umbraco folder:" "${umbracoFolder}"
|
||||
if(Test-Path $umbracoFolder) { Remove-Item $umbracoFolder -Recurse -Force -Confirm:$false }
|
||||
$umbracoClientFolder = Join-Path $projectPath "Umbraco_Client"
|
||||
Write-Host "removing umbraco client folder:" "${umbracoClientFolder}"
|
||||
if(Test-Path $umbracoClientFolder) { Remove-Item $umbracoClientFolder -Recurse -Force -Confirm:$false }
|
||||
}
|
||||
@@ -5,8 +5,10 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Web.Services.Description;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Dynamics
|
||||
{
|
||||
@@ -20,6 +22,20 @@ namespace Umbraco.Core.Dynamics
|
||||
/// </summary>
|
||||
private static readonly ConcurrentDictionary<Tuple<Type, string, int>, MethodInfo[]> MethodCache = new ConcurrentDictionary<Tuple<Type, string, int>, MethodInfo[]>();
|
||||
|
||||
private static IEnumerable<Type> GetTypes(Assembly a)
|
||||
{
|
||||
try
|
||||
{
|
||||
return TypeFinder.GetTypesWithFormattedException(a);
|
||||
}
|
||||
catch (ReflectionTypeLoadException ex)
|
||||
{
|
||||
// is this going to flood the log?
|
||||
LogHelper.Error(typeof (ExtensionMethodFinder), "Failed to get types.", ex);
|
||||
return Enumerable.Empty<Type>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the enumerable of all extension method info's in the app domain = USE SPARINGLY!!!
|
||||
/// </summary>
|
||||
@@ -36,7 +52,7 @@ namespace Umbraco.Core.Dynamics
|
||||
// assemblies that contain extension methods
|
||||
.Where(a => a.IsDefined(typeof (ExtensionAttribute), false))
|
||||
// types that contain extension methods
|
||||
.SelectMany(a => a.GetTypes()
|
||||
.SelectMany(a => GetTypes(a)
|
||||
.Where(t => t.IsDefined(typeof (ExtensionAttribute), false) && t.IsSealed && t.IsGenericType == false && t.IsNested == false))
|
||||
// actual extension methods
|
||||
.SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public)
|
||||
@@ -45,9 +61,9 @@ namespace Umbraco.Core.Dynamics
|
||||
.Concat(typeof (Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public))
|
||||
//If we don't do this then we'll be scanning all assemblies each time!
|
||||
.ToArray(),
|
||||
|
||||
|
||||
//only cache for 5 minutes
|
||||
timeout: TimeSpan.FromMinutes(5),
|
||||
timeout: TimeSpan.FromMinutes(5),
|
||||
|
||||
//each time this is accessed it will be for 5 minutes longer
|
||||
isSliding:true);
|
||||
@@ -57,7 +73,7 @@ namespace Umbraco.Core.Dynamics
|
||||
/// Returns all extension methods found matching the definition
|
||||
/// </summary>
|
||||
/// <param name="runtimeCache">
|
||||
/// The runtime cache is used to temporarily cache all extension methods found in the app domain so that
|
||||
/// The runtime cache is used to temporarily cache all extension methods found in the app domain so that
|
||||
/// while we search for individual extension methods, the process will be reasonably 'quick'. We then statically
|
||||
/// cache the MethodInfo's that we are looking for and then the runtime cache will expire and give back all that memory.
|
||||
/// </param>
|
||||
@@ -78,7 +94,7 @@ namespace Umbraco.Core.Dynamics
|
||||
{
|
||||
var candidates = GetAllExtensionMethodsInAppDomain(runtimeCache);
|
||||
|
||||
// filter by name
|
||||
// filter by name
|
||||
var filtr1 = candidates.Where(m => m.Name == name);
|
||||
|
||||
// filter by args count
|
||||
@@ -102,7 +118,7 @@ namespace Umbraco.Core.Dynamics
|
||||
|
||||
return filtr3.ToArray();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static MethodInfo DetermineMethodFromParams(IEnumerable<MethodInfo> methods, Type genericType, IEnumerable<object> args)
|
||||
@@ -123,12 +139,12 @@ namespace Umbraco.Core.Dynamics
|
||||
types = method.GetParameters().Select(pi => pi.ParameterType).Skip(1)
|
||||
});
|
||||
|
||||
//This type comparer will check
|
||||
//This type comparer will check
|
||||
var typeComparer = new DelegateEqualityComparer<Type>(
|
||||
//Checks if the argument type passed in can be assigned from the parameter type in the method. For
|
||||
//Checks if the argument type passed in can be assigned from the parameter type in the method. For
|
||||
// example, if the argument type is HtmlHelper<MyModel> but the method parameter type is HtmlHelper then
|
||||
// it will match because the argument is assignable to that parameter type and will be able to execute
|
||||
TypeHelper.IsTypeAssignableFrom,
|
||||
TypeHelper.IsTypeAssignableFrom,
|
||||
//This will not ever execute but if it does we need to get the hash code of the string because the hash
|
||||
// code of a type is random
|
||||
type => type.FullName.GetHashCode());
|
||||
@@ -159,7 +175,7 @@ namespace Umbraco.Core.Dynamics
|
||||
.ToArray();
|
||||
|
||||
var methods = GetAllExtensionMethods(runtimeCache, thisType, name, args.Length).ToArray();
|
||||
|
||||
|
||||
return DetermineMethodFromParams(methods, genericType, args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Semver;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Persistence.Migrations;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
@@ -13,23 +14,49 @@ namespace Umbraco.Core.Events
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="targetVersion"></param>
|
||||
/// <param name="productName"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="configuredVersion"></param>
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion, bool canCancel)
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
ConfiguredSemVersion = configuredVersion;
|
||||
TargetSemVersion = targetVersion;
|
||||
}
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion, string productName, bool canCancel)
|
||||
: this(eventObject, null, configuredVersion, targetVersion, productName, canCancel)
|
||||
{ }
|
||||
|
||||
[Obsolete("Use constructor accepting UmbracoVersion instances instead")]
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple migrations that are used in the migration runner
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="targetVersion"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="configuredVersion"></param>
|
||||
[Obsolete("Use constructor accepting a product name instead.")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion, bool canCancel)
|
||||
: this(eventObject, null, configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName, canCancel)
|
||||
{ }
|
||||
|
||||
[Obsolete("Use constructor accepting SemVersion instances and a product name instead.")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, Version configuredVersion, Version targetVersion, bool canCancel)
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
ConfiguredSemVersion = new SemVersion(configuredVersion);
|
||||
TargetSemVersion = new SemVersion(targetVersion);
|
||||
}
|
||||
: this(eventObject, null, new SemVersion(configuredVersion), new SemVersion(targetVersion), GlobalSettings.UmbracoMigrationName, canCancel)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple migrations that are used in the migration runner
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="migrationContext"></param>
|
||||
/// <param name="targetVersion"></param>
|
||||
/// <param name="productName"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="configuredVersion"></param>
|
||||
internal MigrationEventArgs(IList<IMigration> eventObject, MigrationContext migrationContext, SemVersion configuredVersion, SemVersion targetVersion, string productName, bool canCancel)
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
MigrationContext = migrationContext;
|
||||
ConfiguredSemVersion = configuredVersion;
|
||||
TargetSemVersion = targetVersion;
|
||||
ProductName = productName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple migrations that are used in the migration runner
|
||||
@@ -39,12 +66,15 @@ namespace Umbraco.Core.Events
|
||||
/// <param name="targetVersion"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="configuredVersion"></param>
|
||||
[Obsolete("Use constructor accepting a product name instead.")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
internal MigrationEventArgs(IList<IMigration> eventObject, MigrationContext migrationContext, SemVersion configuredVersion, SemVersion targetVersion, bool canCancel)
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
MigrationContext = migrationContext;
|
||||
ConfiguredSemVersion = configuredVersion;
|
||||
TargetSemVersion = targetVersion;
|
||||
ProductName = GlobalSettings.UmbracoMigrationName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -53,21 +83,28 @@ namespace Umbraco.Core.Events
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="configuredVersion"></param>
|
||||
/// <param name="targetVersion"></param>
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion)
|
||||
: base(eventObject)
|
||||
{
|
||||
ConfiguredSemVersion = configuredVersion;
|
||||
TargetSemVersion = targetVersion;
|
||||
}
|
||||
/// <param name="productName"></param>
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion, string productName)
|
||||
: this(eventObject, null, configuredVersion, targetVersion, productName, false)
|
||||
{ }
|
||||
|
||||
[Obsolete("Use constructor accepting UmbracoVersion instances instead")]
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple migrations that are used in the migration runner
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="configuredVersion"></param>
|
||||
/// <param name="targetVersion"></param>
|
||||
[Obsolete("Use constructor accepting a product name instead.")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion)
|
||||
: this(eventObject, null, configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName, false)
|
||||
{ }
|
||||
|
||||
[Obsolete("Use constructor accepting SemVersion instances and a product name instead.")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, Version configuredVersion, Version targetVersion)
|
||||
: base(eventObject)
|
||||
{
|
||||
ConfiguredSemVersion = new SemVersion(configuredVersion);
|
||||
TargetSemVersion = new SemVersion(targetVersion);
|
||||
}
|
||||
: this(eventObject, null, new SemVersion(configuredVersion), new SemVersion(targetVersion), GlobalSettings.UmbracoMigrationName, false)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Returns all migrations that were used in the migration runner
|
||||
@@ -95,6 +132,8 @@ namespace Umbraco.Core.Events
|
||||
|
||||
public SemVersion TargetSemVersion { get; private set; }
|
||||
|
||||
public string ProductName { get; private set; }
|
||||
|
||||
internal MigrationContext MigrationContext { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,12 @@ namespace Umbraco.Core.Models
|
||||
/// </summary
|
||||
public interface IMediaType : IContentTypeComposition
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
|
||||
/// </summary>
|
||||
/// <param name="newAlias"></param>
|
||||
/// <returns></returns>
|
||||
IMediaType DeepCloneWithResetIdentities(string newAlias);
|
||||
}
|
||||
}
|
||||
@@ -38,5 +38,30 @@ namespace Umbraco.Core.Models
|
||||
: base(parent, alias)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IMediaType DeepCloneWithResetIdentities(string alias)
|
||||
{
|
||||
var clone = (MediaType)DeepClone();
|
||||
clone.Alias = alias;
|
||||
clone.Key = Guid.Empty;
|
||||
foreach (var propertyGroup in clone.PropertyGroups)
|
||||
{
|
||||
propertyGroup.ResetIdentity();
|
||||
propertyGroup.ResetDirtyProperties(false);
|
||||
}
|
||||
foreach (var propertyType in clone.PropertyTypes)
|
||||
{
|
||||
propertyType.ResetIdentity();
|
||||
propertyType.ResetDirtyProperties(false);
|
||||
}
|
||||
|
||||
clone.ResetIdentity();
|
||||
clone.ResetDirtyProperties(false);
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Caching;
|
||||
using System.Web.UI;
|
||||
using Umbraco.Core.Cache;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
@@ -16,6 +13,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
public class PublishedContentType
|
||||
{
|
||||
private readonly PublishedPropertyType[] _propertyTypes;
|
||||
private readonly HashSet<string> _compositionAliases;
|
||||
|
||||
// fast alias-to-index xref containing both the raw alias and its lowercase version
|
||||
private readonly Dictionary<string, int> _indexes = new Dictionary<string, int>();
|
||||
@@ -27,6 +25,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
Id = contentType.Id;
|
||||
Alias = contentType.Alias;
|
||||
_compositionAliases = new HashSet<string>(contentType.CompositionAliases(), StringComparer.InvariantCultureIgnoreCase);
|
||||
_propertyTypes = contentType.CompositionPropertyTypes
|
||||
.Select(x => new PublishedPropertyType(this, x))
|
||||
.ToArray();
|
||||
@@ -34,10 +33,11 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
}
|
||||
|
||||
// internal so it can be used for unit tests
|
||||
internal PublishedContentType(int id, string alias, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
internal PublishedContentType(int id, string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
{
|
||||
Id = id;
|
||||
Alias = alias;
|
||||
_compositionAliases = new HashSet<string>(compositionAliases, StringComparer.InvariantCultureIgnoreCase);
|
||||
_propertyTypes = propertyTypes.ToArray();
|
||||
foreach (var propertyType in _propertyTypes)
|
||||
propertyType.ContentType = this;
|
||||
@@ -45,8 +45,8 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
}
|
||||
|
||||
// create detached content type - ie does not match anything in the DB
|
||||
internal PublishedContentType(string alias, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
: this (0, alias, propertyTypes)
|
||||
internal PublishedContentType(string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
: this(0, alias, compositionAliases, propertyTypes)
|
||||
{ }
|
||||
|
||||
private void InitializeIndexes()
|
||||
@@ -63,6 +63,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
|
||||
public int Id { get; private set; }
|
||||
public string Alias { get; private set; }
|
||||
public HashSet<string> CompositionAliases { get { return _compositionAliases; } }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -113,10 +114,25 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
internal static void ClearContentType(int id)
|
||||
{
|
||||
Logging.LogHelper.Debug<PublishedContentType>("Clear content type w/id {0}.", () => id);
|
||||
// requires a predicate because the key does not contain the ID
|
||||
// faster than key strings comparisons anyway
|
||||
|
||||
// we don't support "get all" at the moment - so, cheating
|
||||
var all = ApplicationContext.Current.ApplicationCache.StaticCache.GetCacheItemsByKeySearch<PublishedContentType>("PublishedContentType_").ToArray();
|
||||
|
||||
// the one we want to clear
|
||||
var clr = all.FirstOrDefault(x => x.Id == id);
|
||||
if (clr == null) return;
|
||||
|
||||
// those that have that one in their composition aliases
|
||||
// note: CompositionAliases contains all recursive aliases
|
||||
var oth = all.Where(x => x.CompositionAliases.InvariantContains(clr.Alias)).Select(x => x.Id);
|
||||
|
||||
// merge ids
|
||||
var ids = oth.Concat(new[] { clr.Id }).ToArray();
|
||||
|
||||
// clear them all at once
|
||||
// we don't support "clear many at once" at the moment - so, cheating
|
||||
ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheObjectTypes<PublishedContentType>(
|
||||
(key, value) => value.Id == id);
|
||||
(key, value) => ids.Contains(value.Id));
|
||||
}
|
||||
|
||||
internal static void ClearDataType(int id)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -27,18 +28,21 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
private readonly IMigration[] _migrations;
|
||||
|
||||
[Obsolete("Use the ctor that specifies all dependencies instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public MigrationRunner(Version currentVersion, Version targetVersion, string productName)
|
||||
: this(LoggerResolver.Current.Logger, currentVersion, targetVersion, productName)
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Use the ctor that specifies all dependencies instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public MigrationRunner(ILogger logger, Version currentVersion, Version targetVersion, string productName)
|
||||
: this(logger, currentVersion, targetVersion, productName, null)
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Use the ctor that specifies all dependencies instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public MigrationRunner(ILogger logger, Version currentVersion, Version targetVersion, string productName, params IMigration[] migrations)
|
||||
: this(ApplicationContext.Current.Services.MigrationEntryService, logger, new SemVersion(currentVersion), new SemVersion(targetVersion), productName, migrations)
|
||||
{
|
||||
@@ -92,7 +96,7 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
: OrderedDowngradeMigrations(foundMigrations).ToList();
|
||||
|
||||
|
||||
if (Migrating.IsRaisedEventCancelled(new MigrationEventArgs(migrations, _currentVersion, _targetVersion, true), this))
|
||||
if (Migrating.IsRaisedEventCancelled(new MigrationEventArgs(migrations, _currentVersion, _targetVersion, _productName, true), this))
|
||||
{
|
||||
_logger.Warn<MigrationRunner>("Migration was cancelled by an event");
|
||||
return false;
|
||||
@@ -121,7 +125,7 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
throw;
|
||||
}
|
||||
|
||||
Migrated.RaiseEvent(new MigrationEventArgs(migrations, migrationContext, _currentVersion, _targetVersion, false), this);
|
||||
Migrated.RaiseEvent(new MigrationEventArgs(migrations, migrationContext, _currentVersion, _targetVersion, _productName, false), this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -128,6 +128,34 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
right = Visit(b.Right);
|
||||
}
|
||||
}
|
||||
else if (operand == "=")
|
||||
{
|
||||
// deal with (x == true|false) - most common
|
||||
var constRight = b.Right as ConstantExpression;
|
||||
if (constRight != null && constRight.Type == typeof (bool))
|
||||
return ((bool) constRight.Value) ? VisitNotNot(b.Left) : VisitNot(b.Left);
|
||||
right = Visit(b.Right);
|
||||
|
||||
// deal with (true|false == x) - why not
|
||||
var constLeft = b.Left as ConstantExpression;
|
||||
if (constLeft != null && constLeft.Type == typeof (bool))
|
||||
return ((bool) constLeft.Value) ? VisitNotNot(b.Right) : VisitNot(b.Right);
|
||||
left = Visit(b.Left);
|
||||
}
|
||||
else if (operand == "<>")
|
||||
{
|
||||
// deal with (x != true|false) - most common
|
||||
var constRight = b.Right as ConstantExpression;
|
||||
if (constRight != null && constRight.Type == typeof(bool))
|
||||
return ((bool) constRight.Value) ? VisitNot(b.Left) : VisitNotNot(b.Left);
|
||||
right = Visit(b.Right);
|
||||
|
||||
// deal with (true|false != x) - why not
|
||||
var constLeft = b.Left as ConstantExpression;
|
||||
if (constLeft != null && constLeft.Type == typeof(bool))
|
||||
return ((bool) constLeft.Value) ? VisitNot(b.Right) : VisitNotNot(b.Right);
|
||||
left = Visit(b.Left);
|
||||
}
|
||||
else
|
||||
{
|
||||
left = Visit(b.Left);
|
||||
@@ -231,25 +259,47 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
switch (u.NodeType)
|
||||
{
|
||||
case ExpressionType.Not:
|
||||
var o = Visit(u.Operand);
|
||||
|
||||
//use a Not equal operator instead of <> since we don't know that <> works in all sql servers
|
||||
|
||||
switch (u.Operand.NodeType)
|
||||
{
|
||||
case ExpressionType.MemberAccess:
|
||||
//In this case it wil be a false property , i.e. x => !Trashed
|
||||
SqlParameters.Add(true);
|
||||
return string.Format("NOT ({0} = @0)", o);
|
||||
default:
|
||||
//In this case it could be anything else, such as: x => !x.Path.StartsWith("-20")
|
||||
return string.Format("NOT ({0})", o);
|
||||
}
|
||||
return VisitNot(u.Operand);
|
||||
default:
|
||||
return Visit(u.Operand);
|
||||
}
|
||||
}
|
||||
|
||||
private string VisitNot(Expression exp)
|
||||
{
|
||||
var o = Visit(exp);
|
||||
|
||||
// use a "NOT (...)" syntax instead of "<>" since we don't know whether "<>" works in all sql servers
|
||||
// also, x.StartsWith(...) translates to "x LIKE '...%'" which we cannot "<>" and have to "NOT (...")
|
||||
|
||||
switch (exp.NodeType)
|
||||
{
|
||||
case ExpressionType.MemberAccess:
|
||||
// false property , i.e. x => !Trashed
|
||||
SqlParameters.Add(true);
|
||||
return "NOT (" + o + " = @0)";
|
||||
default:
|
||||
// could be anything else, such as: x => !x.Path.StartsWith("-20")
|
||||
return "NOT (" + o + ")";
|
||||
}
|
||||
}
|
||||
|
||||
private string VisitNotNot(Expression exp)
|
||||
{
|
||||
var o = Visit(exp);
|
||||
|
||||
switch (exp.NodeType)
|
||||
{
|
||||
case ExpressionType.MemberAccess:
|
||||
// true property, i.e. x => Trashed
|
||||
SqlParameters.Add(true);
|
||||
return o + " = @0";
|
||||
default:
|
||||
// could be anything else, such as: x => x.Path.StartsWith("-20")
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string VisitNewArray(NewArrayExpression na)
|
||||
{
|
||||
|
||||
|
||||
@@ -1212,5 +1212,19 @@ AND umbracoNode.id <> @id",
|
||||
{
|
||||
return PerformExists(id);
|
||||
}
|
||||
|
||||
public string GetUniqueAlias(string alias)
|
||||
{
|
||||
// alias is unique accross ALL content types!
|
||||
var aliasColumn = SqlSyntax.GetQuotedColumnName("alias");
|
||||
var aliases = Database.Fetch<string>(@"SELECT cmsContentType." + aliasColumn + @" FROM cmsContentType
|
||||
INNER JOIN umbracoNode ON cmsContentType.nodeId = umbracoNode.id
|
||||
WHERE cmsContentType." + aliasColumn + @" LIKE @pattern",
|
||||
new { pattern = alias + "%", objectType = NodeObjectTypeId });
|
||||
var i = 1;
|
||||
string test;
|
||||
while (aliases.Contains(test = alias + i)) i++;
|
||||
return test;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,5 +32,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<string> GetAllContentTypeAliases(params Guid[] objectTypes);
|
||||
|
||||
/// <summary>
|
||||
/// Derives a unique alias from an existing alias.
|
||||
/// </summary>
|
||||
/// <param name="alias">The original alias.</param>
|
||||
/// <returns>The original alias with a number appended to it, so that it is unique.</returns>
|
||||
/// /// <remarks>Unique accross all content, media and member types.</remarks>
|
||||
string GetUniqueAlias(string alias);
|
||||
}
|
||||
}
|
||||
@@ -15,5 +15,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
IEnumerable<IMediaType> GetByQuery(IQuery<PropertyType> query);
|
||||
|
||||
IEnumerable<MoveEventInfo<IMediaType>> Move(IMediaType toMove, EntityContainer container);
|
||||
|
||||
/// <summary>
|
||||
/// Derives a unique alias from an existing alias.
|
||||
/// </summary>
|
||||
/// <param name="alias">The original alias.</param>
|
||||
/// <returns>The original alias with a number appended to it, so that it is unique.</returns>
|
||||
/// <remarks>Unique accross all content, media and member types.</remarks>
|
||||
string GetUniqueAlias(string alias);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
GuidColumnDefinition = "char(36)";
|
||||
|
||||
DefaultValueFormat = "DEFAULT {0}";
|
||||
|
||||
InitColumnTypeMap();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetTablesInSchema(Database db)
|
||||
|
||||
@@ -794,7 +794,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
//TODO: This needs to change, if we are deleting a content type, we should just delete the data,
|
||||
// this method will recursively go lookup every content item, check if any of it's descendants are
|
||||
// of a different type, move them to the recycle bin, then permanently delete the content items.
|
||||
// of a different type, move them to the recycle bin, then permanently delete the content items.
|
||||
// The main problem with this is that for every content item being deleted, events are raised...
|
||||
// which we need for many things like keeping caches in sync, but we can surely do this MUCH better.
|
||||
|
||||
@@ -1067,6 +1067,92 @@ namespace Umbraco.Core.Services
|
||||
new OperationStatus<MoveOperationStatusType>(MoveOperationStatusType.Success, evtMsgs));
|
||||
}
|
||||
|
||||
public Attempt<OperationStatus<IMediaType, MoveOperationStatusType>> CopyMediaType(IMediaType toCopy, int containerId)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
IMediaType copy;
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var containerRepository = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.MediaTypeContainerGuid))
|
||||
using (var repository = RepositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (containerId > 0)
|
||||
{
|
||||
var container = containerRepository.Get(containerId);
|
||||
if (container == null)
|
||||
throw new DataOperationException<MoveOperationStatusType>(MoveOperationStatusType.FailedParentNotFound);
|
||||
}
|
||||
var alias = repository.GetUniqueAlias(toCopy.Alias);
|
||||
copy = toCopy.DeepCloneWithResetIdentities(alias);
|
||||
copy.Name = copy.Name + " (copy)"; // might not be unique
|
||||
|
||||
// if it has a parent, and the parent is a content type, unplug composition
|
||||
// all other compositions remain in place in the copied content type
|
||||
if (copy.ParentId > 0)
|
||||
{
|
||||
var parent = repository.Get(copy.ParentId);
|
||||
if (parent != null)
|
||||
copy.RemoveContentType(parent.Alias);
|
||||
}
|
||||
|
||||
copy.ParentId = containerId;
|
||||
repository.AddOrUpdate(copy);
|
||||
}
|
||||
catch (DataOperationException<MoveOperationStatusType> ex)
|
||||
{
|
||||
return Attempt.Fail(new OperationStatus<IMediaType, MoveOperationStatusType>(null, ex.Operation, evtMsgs));
|
||||
}
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
return Attempt.Succeed(new OperationStatus<IMediaType, MoveOperationStatusType>(copy, MoveOperationStatusType.Success, evtMsgs));
|
||||
}
|
||||
|
||||
public Attempt<OperationStatus<IContentType, MoveOperationStatusType>> CopyContentType(IContentType toCopy, int containerId)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
IContentType copy;
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var containerRepository = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DocumentTypeContainerGuid))
|
||||
using (var repository = RepositoryFactory.CreateContentTypeRepository(uow))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (containerId > 0)
|
||||
{
|
||||
var container = containerRepository.Get(containerId);
|
||||
if (container == null)
|
||||
throw new DataOperationException<MoveOperationStatusType>(MoveOperationStatusType.FailedParentNotFound);
|
||||
}
|
||||
var alias = repository.GetUniqueAlias(toCopy.Alias);
|
||||
copy = toCopy.DeepCloneWithResetIdentities(alias);
|
||||
copy.Name = copy.Name + " (copy)"; // might not be unique
|
||||
|
||||
// if it has a parent, and the parent is a content type, unplug composition
|
||||
// all other compositions remain in place in the copied content type
|
||||
if (copy.ParentId > 0)
|
||||
{
|
||||
var parent = repository.Get(copy.ParentId);
|
||||
if (parent != null)
|
||||
copy.RemoveContentType(parent.Alias);
|
||||
}
|
||||
|
||||
copy.ParentId = containerId;
|
||||
repository.AddOrUpdate(copy);
|
||||
}
|
||||
catch (DataOperationException<MoveOperationStatusType> ex)
|
||||
{
|
||||
return Attempt.Fail(new OperationStatus<IContentType, MoveOperationStatusType>(null, ex.Operation, evtMsgs));
|
||||
}
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
return Attempt.Succeed(new OperationStatus<IContentType, MoveOperationStatusType>(copy, MoveOperationStatusType.Success, evtMsgs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a single <see cref="IMediaType"/> object
|
||||
/// </summary>
|
||||
|
||||
@@ -291,5 +291,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Attempt<OperationStatus<MoveOperationStatusType>> MoveMediaType(IMediaType toMove, int containerId);
|
||||
Attempt<OperationStatus<MoveOperationStatusType>> MoveContentType(IContentType toMove, int containerId);
|
||||
Attempt<OperationStatus<IMediaType, MoveOperationStatusType>> CopyMediaType(IMediaType toCopy, int containerId);
|
||||
Attempt<OperationStatus<IContentType, MoveOperationStatusType>> CopyContentType(IContentType toCopy, int containerId);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Core
|
||||
|
||||
/// <summary>
|
||||
/// A utility class to find all classes of a certain type by reflection in the current bin folder
|
||||
/// of the web application.
|
||||
/// of the web application.
|
||||
/// </summary>
|
||||
public static class TypeFinder
|
||||
{
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Core
|
||||
/// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
|
||||
/// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
|
||||
/// loaded in the CLR, not all assemblies.
|
||||
/// See these threads:
|
||||
/// http://issues.umbraco.org/issue/U5-198
|
||||
@@ -136,7 +136,7 @@ namespace Umbraco.Core
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
|
||||
/// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
|
||||
/// and exluding the ones passed in and excluding the exclusion list filter, the results of this are
|
||||
/// cached for perforance reasons.
|
||||
/// </summary>
|
||||
@@ -190,6 +190,7 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match
|
||||
/// NOTE this means that "foo." will NOT exclude "foo.dll" but only "foo.*.dll"
|
||||
/// </remarks>
|
||||
internal static readonly string[] KnownAssemblyExclusionFilter = new[]
|
||||
{
|
||||
@@ -214,7 +215,7 @@ namespace Umbraco.Core
|
||||
"RouteDebugger,",
|
||||
"SqlCE4Umbraco,",
|
||||
"umbraco.datalayer,",
|
||||
"umbraco.interfaces,",
|
||||
"umbraco.interfaces,",
|
||||
//"umbraco.providers,",
|
||||
//"Umbraco.Web.UI,",
|
||||
"umbraco.webservices",
|
||||
@@ -230,9 +231,9 @@ namespace Umbraco.Core
|
||||
"AutoMapper,",
|
||||
"AutoMapper.",
|
||||
"AzureDirectory,",
|
||||
"itextsharp,",
|
||||
"itextsharp,",
|
||||
"UrlRewritingNet.",
|
||||
"HtmlAgilityPack,",
|
||||
"HtmlAgilityPack,",
|
||||
"MiniProfiler,",
|
||||
"Moq,",
|
||||
"nunit.framework,",
|
||||
@@ -371,7 +372,7 @@ namespace Umbraco.Core
|
||||
|
||||
var assemblyList = assemblies.ToArray();
|
||||
|
||||
//find all assembly references that are referencing the attribute type's assembly since we
|
||||
//find all assembly references that are referencing the attribute type's assembly since we
|
||||
//should only be scanning those assemblies because any other assembly will definitely not
|
||||
//contain a class that has this attribute.
|
||||
var referencedAssemblies = TypeHelper.GetReferencedAssemblies(attributeType, assemblyList);
|
||||
@@ -418,7 +419,7 @@ namespace Umbraco.Core
|
||||
foreach (var subTypesInAssembly in allAttributeTypes.GroupBy(x => x.Assembly))
|
||||
{
|
||||
|
||||
//So that we are not scanning too much, we need to group the sub types:
|
||||
//So that we are not scanning too much, we need to group the sub types:
|
||||
// * if there is more than 1 sub type in the same assembly then we should only search on the 'lowest base' type.
|
||||
// * We should also not search for sub types if the type is sealed since you cannot inherit from a sealed class
|
||||
// * We should not search for sub types if the type is static since you cannot inherit from them.
|
||||
@@ -489,7 +490,7 @@ namespace Umbraco.Core
|
||||
|
||||
/// <summary>
|
||||
/// Finds types that are assignable from the assignTypeFrom parameter and will scan for these types in the assembly
|
||||
/// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type
|
||||
/// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type
|
||||
/// deriving from the base type.
|
||||
/// </summary>
|
||||
/// <param name="assignTypeFrom"></param>
|
||||
@@ -513,7 +514,7 @@ namespace Umbraco.Core
|
||||
|
||||
var assemblyList = assemblies.ToArray();
|
||||
|
||||
//find all assembly references that are referencing the current type's assembly since we
|
||||
//find all assembly references that are referencing the current type's assembly since we
|
||||
//should only be scanning those assemblies because any other assembly will definitely not
|
||||
//contain sub type's of the one we're currently looking for
|
||||
var referencedAssemblies = TypeHelper.GetReferencedAssemblies(assignTypeFrom, assemblyList);
|
||||
@@ -560,7 +561,7 @@ namespace Umbraco.Core
|
||||
foreach (var subTypesInAssembly in allSubTypes.GroupBy(x => x.Assembly))
|
||||
{
|
||||
|
||||
//So that we are not scanning too much, we need to group the sub types:
|
||||
//So that we are not scanning too much, we need to group the sub types:
|
||||
// * if there is more than 1 sub type in the same assembly then we should only search on the 'lowest base' type.
|
||||
// * We should also not search for sub types if the type is sealed since you cannot inherit from a sealed class
|
||||
// * We should not search for sub types if the type is static since you cannot inherit from them.
|
||||
@@ -602,39 +603,69 @@ namespace Umbraco.Core
|
||||
return foundAssignableTypes;
|
||||
}
|
||||
|
||||
private static IEnumerable<Type> GetTypesWithFormattedException(Assembly a)
|
||||
internal static IEnumerable<Type> GetTypesWithFormattedException(Assembly a)
|
||||
{
|
||||
//if the assembly is dynamic, do not try to scan it
|
||||
if (a.IsDynamic)
|
||||
return Enumerable.Empty<Type>();
|
||||
|
||||
var getAll = a.GetCustomAttribute<AllowPartiallyTrustedCallersAttribute>() == null;
|
||||
|
||||
try
|
||||
{
|
||||
//we need to detect if an assembly is partially trusted, if so we cannot go interrogating all of it's types
|
||||
//only its exported types, otherwise we'll get exceptions.
|
||||
if (a.GetCustomAttribute<AllowPartiallyTrustedCallersAttribute>() == null)
|
||||
{
|
||||
return a.GetTypes();
|
||||
}
|
||||
else
|
||||
{
|
||||
return a.GetExportedTypes();
|
||||
}
|
||||
return getAll ? a.GetTypes() : a.GetExportedTypes();
|
||||
}
|
||||
catch (ReflectionTypeLoadException ex)
|
||||
catch (TypeLoadException ex) // GetExportedTypes *can* throw TypeLoadException!
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("Could not load types from assembly " + a.FullName + ", errors:");
|
||||
foreach (var loaderException in ex.LoaderExceptions.WhereNotNull())
|
||||
{
|
||||
sb.AppendLine("Exception: " + loaderException);
|
||||
}
|
||||
throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString());
|
||||
AppendCouldNotLoad(sb, a, getAll);
|
||||
AppendLoaderException(sb, ex);
|
||||
|
||||
// rethrow as ReflectionTypeLoadException (for consistency) with new message
|
||||
throw new ReflectionTypeLoadException(new Type[0], new Exception[] { ex }, sb.ToString());
|
||||
}
|
||||
catch (ReflectionTypeLoadException rex) // GetTypes throws ReflectionTypeLoadException
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
AppendCouldNotLoad(sb, a, getAll);
|
||||
foreach (var loaderException in rex.LoaderExceptions.WhereNotNull())
|
||||
AppendLoaderException(sb, loaderException);
|
||||
|
||||
// rethrow with new message
|
||||
throw new ReflectionTypeLoadException(rex.Types, rex.LoaderExceptions, sb.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void AppendCouldNotLoad(StringBuilder sb, Assembly a, bool getAll)
|
||||
{
|
||||
sb.Append("Could not load ");
|
||||
sb.Append(getAll ? "all" : "exported");
|
||||
sb.Append(" types from \"");
|
||||
sb.Append(a.FullName);
|
||||
sb.AppendLine("\" due to LoaderExceptions, skipping:");
|
||||
}
|
||||
|
||||
private static void AppendLoaderException(StringBuilder sb, Exception loaderException)
|
||||
{
|
||||
sb.Append(". ");
|
||||
sb.Append(loaderException.GetType().FullName);
|
||||
|
||||
var tloadex = loaderException as TypeLoadException;
|
||||
if (tloadex != null)
|
||||
{
|
||||
sb.Append(" on ");
|
||||
sb.Append(tloadex.TypeName);
|
||||
}
|
||||
|
||||
sb.Append(": ");
|
||||
sb.Append(loaderException.Message);
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
public static Type GetTypeByName(string typeName)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Semver;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Migrations;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Strategies.Migrations;
|
||||
|
||||
namespace Umbraco.Tests.Persistence.Migrations
|
||||
{
|
||||
[TestFixture]
|
||||
public class MigrationStartupHandlerTests
|
||||
{
|
||||
[Test]
|
||||
public void Executes_For_Any_Product_Name_When_Not_Specified()
|
||||
{
|
||||
var changed1 = new Args { CountExecuted = 0 };
|
||||
var testHandler1 = new TestMigrationHandler(changed1);
|
||||
testHandler1.OnApplicationStarting(Mock.Of<UmbracoApplicationBase>(), new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
|
||||
|
||||
var conn = new Mock<IDbConnection>();
|
||||
conn.Setup(x => x.BeginTransaction(It.IsAny<IsolationLevel>())).Returns(Mock.Of<IDbTransaction>());
|
||||
var db = new Mock<Database>(conn.Object);
|
||||
|
||||
var runner1 = new MigrationRunner(Mock.Of<IMigrationEntryService>(), Mock.Of<ILogger>(), new SemVersion(1), new SemVersion(2), "Test1",
|
||||
new IMigration[] { Mock.Of<IMigration>() });
|
||||
var result1 = runner1.Execute(db.Object, DatabaseProviders.SqlServerCE, false);
|
||||
Assert.AreEqual(1, changed1.CountExecuted);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Executes_Only_For_Specified_Product_Name()
|
||||
{
|
||||
var changed1 = new Args { CountExecuted = 0};
|
||||
var testHandler1 = new TestMigrationHandler("Test1", changed1);
|
||||
testHandler1.OnApplicationStarting(Mock.Of<UmbracoApplicationBase>(), new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
|
||||
var changed2 = new Args { CountExecuted = 0 };
|
||||
var testHandler2 = new TestMigrationHandler("Test2", changed2);
|
||||
testHandler2.OnApplicationStarting(Mock.Of<UmbracoApplicationBase>(), new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
|
||||
|
||||
var conn = new Mock<IDbConnection>();
|
||||
conn.Setup(x => x.BeginTransaction(It.IsAny<IsolationLevel>())).Returns(Mock.Of<IDbTransaction>());
|
||||
var db = new Mock<Database>(conn.Object);
|
||||
|
||||
var runner1 = new MigrationRunner(Mock.Of<IMigrationEntryService>(), Mock.Of<ILogger>(), new SemVersion(1), new SemVersion(2), "Test1",
|
||||
new IMigration[] { Mock.Of<IMigration>()});
|
||||
var result1 = runner1.Execute(db.Object, DatabaseProviders.SqlServerCE, false);
|
||||
Assert.AreEqual(1, changed1.CountExecuted);
|
||||
Assert.AreEqual(0, changed2.CountExecuted);
|
||||
|
||||
var runner2 = new MigrationRunner(Mock.Of<IMigrationEntryService>(), Mock.Of<ILogger>(), new SemVersion(1), new SemVersion(2), "Test2",
|
||||
new IMigration[] { Mock.Of<IMigration>() });
|
||||
var result2 = runner2.Execute(db.Object, DatabaseProviders.SqlServerCE, false);
|
||||
Assert.AreEqual(1, changed1.CountExecuted);
|
||||
Assert.AreEqual(1, changed2.CountExecuted);
|
||||
}
|
||||
|
||||
public class Args
|
||||
{
|
||||
public int CountExecuted { get; set; }
|
||||
}
|
||||
|
||||
public class TestMigrationHandler : MigrationStartupHander
|
||||
{
|
||||
private readonly string _prodName;
|
||||
private readonly Args _changed;
|
||||
|
||||
public TestMigrationHandler(Args changed)
|
||||
{
|
||||
_changed = changed;
|
||||
}
|
||||
|
||||
public TestMigrationHandler(string prodName, Args changed)
|
||||
{
|
||||
_prodName = prodName;
|
||||
_changed = changed;
|
||||
}
|
||||
|
||||
protected override void AfterMigration(MigrationRunner sender, MigrationEventArgs e)
|
||||
{
|
||||
_changed.CountExecuted++;
|
||||
}
|
||||
|
||||
public override string[] TargetProductNames
|
||||
{
|
||||
get { return _prodName.IsNullOrWhiteSpace() ? new string[] {} : new[] {_prodName}; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,18 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
Assert.AreEqual("-20%", sql.Arguments[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_EqualsFalse_Starts_With()
|
||||
{
|
||||
var level = 1;
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Level == level && x.Path.StartsWith("-20") == false);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[level] = @0 AND NOT (upper([umbracoNode].[path]) LIKE upper(@1)))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(2, sql.Arguments.Length);
|
||||
Assert.AreEqual(level, sql.Arguments[0]);
|
||||
Assert.AreEqual("-20%", sql.Arguments[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_Equals_Clause()
|
||||
{
|
||||
@@ -71,6 +83,16 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
Assert.AreEqual(true, sql.Arguments[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_EqualsFalse_Boolean()
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Trashed == false);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (NOT ([umbracoNode].[trashed] = @0))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual(true, sql.Arguments[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_Boolean()
|
||||
{
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
using System;
|
||||
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Migrations;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.Persistence.SyntaxProvider
|
||||
{
|
||||
[NUnit.Framework.Ignore("This doesn't actually test anything")]
|
||||
//[NUnit.Framework.Ignore("This doesn't actually test anything")]
|
||||
[TestFixture]
|
||||
public class MySqlSyntaxProviderTests
|
||||
public class MySqlSyntaxProviderTests : BaseUsingSqlCeSyntax
|
||||
{
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
@@ -20,6 +23,7 @@ namespace Umbraco.Tests.Persistence.SyntaxProvider
|
||||
}
|
||||
|
||||
[Test]
|
||||
[NUnit.Framework.Ignore]
|
||||
public void Can_Generate_Create_Table_Statement()
|
||||
{
|
||||
var type = typeof(TagRelationshipDto);
|
||||
@@ -48,5 +52,40 @@ namespace Umbraco.Tests.Persistence.SyntaxProvider
|
||||
{
|
||||
SqlSyntaxContext.SqlSyntaxProvider = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void U4_8017()
|
||||
{
|
||||
var logger = Mock.Of<ILogger>();
|
||||
var migration = new TestMigration(SqlSyntaxContext.SqlSyntaxProvider, logger);
|
||||
var context = new MigrationContext(DatabaseProviders.MySql, null, logger);
|
||||
migration.Context = context;
|
||||
migration.Up();
|
||||
var x = context.Expressions;
|
||||
Assert.AreEqual(1, x.Count);
|
||||
var e = x.First().ToString();
|
||||
|
||||
// SQLCE provider *does* use UniqueIdentifier
|
||||
// MySql using GUID...? because InitColumnTypeMap() missing in provider, fixed
|
||||
|
||||
Assert.AreEqual("ALTER TABLE `cmsPropertyTypeGroup` ADD COLUMN `uniqueID` char(36) NOT NULL", e);
|
||||
}
|
||||
|
||||
[Migration("1.0.0", 0, "Test")]
|
||||
private class TestMigration : MigrationBase
|
||||
{
|
||||
public TestMigration(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
|
||||
{}
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
Create.Column("uniqueID").OnTable("cmsPropertyTypeGroup").AsGuid().NotNullable().WithDefault(SystemMethods.NewGuid);
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,12 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Create.Index;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Expressions;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.Persistence.SyntaxProvider
|
||||
{
|
||||
[TestFixture]
|
||||
public class SqlCeSyntaxProviderTests
|
||||
public class SqlCeSyntaxProviderTests : BaseUsingSqlCeSyntax
|
||||
{
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -79,8 +79,8 @@ namespace Umbraco.Tests.Plugins
|
||||
var originalTypesFound = TypeFinderOriginal.FindClassesOfType<IApplicationStartupHandler>(_assemblies);
|
||||
|
||||
Assert.AreEqual(originalTypesFound.Count(), typesFound.Count());
|
||||
Assert.AreEqual(8, typesFound.Count());
|
||||
Assert.AreEqual(8, originalTypesFound.Count());
|
||||
Assert.AreEqual(9, typesFound.Count());
|
||||
Assert.AreEqual(9, originalTypesFound.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -234,9 +234,9 @@ namespace Umbraco.Tests.PublishedContent
|
||||
new PublishedPropertyType("prop1", 1, "?"),
|
||||
};
|
||||
|
||||
var contentType1 = new PublishedContentType(1, "ContentType1", props);
|
||||
var contentType2 = new PublishedContentType(2, "ContentType2", props);
|
||||
var contentType2s = new PublishedContentType(3, "ContentType2Sub", props);
|
||||
var contentType1 = new PublishedContentType(1, "ContentType1", Enumerable.Empty<string>(), props);
|
||||
var contentType2 = new PublishedContentType(2, "ContentType2", Enumerable.Empty<string>(), props);
|
||||
var contentType2s = new PublishedContentType(3, "ContentType2Sub", Enumerable.Empty<string>(), props);
|
||||
|
||||
cache.Add(new SolidPublishedContent(contentType1)
|
||||
{
|
||||
|
||||
@@ -355,7 +355,11 @@ namespace Umbraco.Tests.PublishedContent
|
||||
private static readonly PublishedPropertyType Default = new PublishedPropertyType("*", 0, "?");
|
||||
|
||||
public AutoPublishedContentType(int id, string alias, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
: base(id, alias, propertyTypes)
|
||||
: base(id, alias, Enumerable.Empty<string>(), propertyTypes)
|
||||
{ }
|
||||
|
||||
public AutoPublishedContentType(int id, string alias, IEnumerable<string> compositionAliases, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
: base(id, alias, compositionAliases, propertyTypes)
|
||||
{ }
|
||||
|
||||
public override PublishedPropertyType GetPropertyType(string alias)
|
||||
|
||||
@@ -50,7 +50,8 @@ namespace Umbraco.Tests.PublishedContent
|
||||
new PublishedPropertyType("content", 0, Constants.PropertyEditors.TinyMCEAlias),
|
||||
new PublishedPropertyType("testRecursive", 0, "?"),
|
||||
};
|
||||
var type = new AutoPublishedContentType(0, "anything", propertyTypes);
|
||||
var compositionAliases = new[] {"MyCompositionAlias"};
|
||||
var type = new AutoPublishedContentType(0, "anything", compositionAliases, propertyTypes);
|
||||
PublishedContentType.GetPublishedContentTypeCallback = (alias) => type;
|
||||
}
|
||||
|
||||
@@ -468,6 +469,16 @@ namespace Umbraco.Tests.PublishedContent
|
||||
Assert.IsNull(doc.FirstChild<IPublishedContent>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsComposedOf()
|
||||
{
|
||||
var doc = GetNode(1173);
|
||||
|
||||
var isComposedOf = doc.IsComposedOf("MyCompositionAlias");
|
||||
|
||||
Assert.IsTrue(isComposedOf);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasProperty()
|
||||
{
|
||||
@@ -475,8 +486,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
|
||||
var hasProp = doc.HasProperty(Constants.Conventions.Content.UrlAlias);
|
||||
|
||||
Assert.AreEqual(true, (bool)hasProp);
|
||||
|
||||
Assert.IsTrue(hasProp);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -175,6 +175,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Persistence\Migrations\MigrationStartupHandlerTests.cs" />
|
||||
<Compile Include="Web\AngularIntegration\AngularAntiForgeryTests.cs" />
|
||||
<Compile Include="Web\AngularIntegration\ContentModelSerializationTests.cs" />
|
||||
<Compile Include="Web\AngularIntegration\JsInitializationTests.cs" />
|
||||
@@ -244,6 +245,7 @@
|
||||
<Compile Include="Models\UmbracoEntityTests.cs" />
|
||||
<Compile Include="Models\UserTests.cs" />
|
||||
<Compile Include="Models\UserTypeTests.cs" />
|
||||
<Compile Include="Web\Mvc\RenderModelBinderTests.cs" />
|
||||
<Compile Include="Web\Mvc\SurfaceControllerTests.cs" />
|
||||
<Compile Include="Web\Mvc\UmbracoViewPageTests.cs" />
|
||||
<Compile Include="BootManagers\CoreBootManagerTests.cs" />
|
||||
@@ -758,7 +760,7 @@
|
||||
xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\" /Y /F /E /I /C /D</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Tests.Web.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class RenderModelBinderTests
|
||||
{
|
||||
[Test]
|
||||
public void Returns_Binder_For_IPublishedContent_And_IRenderModel()
|
||||
{
|
||||
var binder = new RenderModelBinder();
|
||||
var found = binder.GetBinder(typeof (IPublishedContent));
|
||||
Assert.IsNotNull(found);
|
||||
found = binder.GetBinder(typeof(IRenderModel));
|
||||
Assert.IsNotNull(found);
|
||||
found = binder.GetBinder(typeof(RenderModel));
|
||||
Assert.IsNotNull(found);
|
||||
found = binder.GetBinder(typeof(DynamicPublishedContent));
|
||||
Assert.IsNotNull(found);
|
||||
found = binder.GetBinder(typeof(MyContent));
|
||||
Assert.IsNotNull(found);
|
||||
|
||||
found = binder.GetBinder(typeof(MyOtherContent));
|
||||
Assert.IsNull(found);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BindModel_Null_Source_Returns_Null()
|
||||
{
|
||||
Assert.IsNull(RenderModelBinder.BindModel(null, typeof(MyContent), CultureInfo.CurrentCulture));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BindModel_Returns_If_Same_Type()
|
||||
{
|
||||
var content = new MyContent(Mock.Of<IPublishedContent>());
|
||||
var bound = RenderModelBinder.BindModel(content, typeof (IPublishedContent), CultureInfo.CurrentCulture);
|
||||
Assert.AreSame(content, bound);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BindModel_RenderModel_To_IPublishedContent()
|
||||
{
|
||||
var content = new MyContent(Mock.Of<IPublishedContent>());
|
||||
var renderModel = new RenderModel(content, CultureInfo.CurrentCulture);
|
||||
var bound = RenderModelBinder.BindModel(renderModel, typeof(IPublishedContent), CultureInfo.CurrentCulture);
|
||||
Assert.AreSame(content, bound);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BindModel_IPublishedContent_To_RenderModel()
|
||||
{
|
||||
var content = new MyContent(Mock.Of<IPublishedContent>());
|
||||
var bound = (IRenderModel)RenderModelBinder.BindModel(content, typeof(RenderModel), CultureInfo.CurrentCulture);
|
||||
Assert.AreSame(content, bound.Content);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BindModel_IPublishedContent_To_Generic_RenderModel()
|
||||
{
|
||||
var content = new MyContent(Mock.Of<IPublishedContent>());
|
||||
var bound = (IRenderModel)RenderModelBinder.BindModel(content, typeof(RenderModel<MyContent>), CultureInfo.CurrentCulture);
|
||||
Assert.AreSame(content, bound.Content);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_DataToken_Returns_Null()
|
||||
{
|
||||
var binder = new RenderModelBinder();
|
||||
var routeData = new RouteData();
|
||||
var result = binder.BindModel(new ControllerContext(Mock.Of<HttpContextBase>(), routeData, Mock.Of<ControllerBase>()),
|
||||
new ModelBindingContext());
|
||||
|
||||
Assert.IsNull(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Invalid_DataToken_Model_Type_Returns_Null()
|
||||
{
|
||||
var binder = new RenderModelBinder();
|
||||
var routeData = new RouteData();
|
||||
routeData.DataTokens[Core.Constants.Web.UmbracoDataToken] = "hello";
|
||||
|
||||
//the value provider is the default implementation
|
||||
var valueProvider = new Mock<IValueProvider>();
|
||||
//also IUnvalidatedValueProvider
|
||||
var invalidatedValueProvider = valueProvider.As<IUnvalidatedValueProvider>();
|
||||
invalidatedValueProvider.Setup(x => x.GetValue(It.IsAny<string>(), It.IsAny<bool>())).Returns(() =>
|
||||
new ValueProviderResult(null, "", CultureInfo.CurrentCulture));
|
||||
|
||||
var controllerCtx = new ControllerContext(
|
||||
Mock.Of<HttpContextBase>(http => http.Items == new Dictionary<object, object>()),
|
||||
routeData,
|
||||
Mock.Of<ControllerBase>());
|
||||
|
||||
var result = binder.BindModel(controllerCtx,
|
||||
new ModelBindingContext
|
||||
{
|
||||
ValueProvider = valueProvider.Object,
|
||||
ModelMetadata = new ModelMetadata(new EmptyModelMetadataProvider(), null, () => null, typeof(IPublishedContent), "content")
|
||||
});
|
||||
|
||||
Assert.IsNull(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IPublishedContent_DataToken_Model_Type_Uses_DefaultImplementation()
|
||||
{
|
||||
var content = new MyContent(Mock.Of<IPublishedContent>());
|
||||
var binder = new RenderModelBinder();
|
||||
var routeData = new RouteData();
|
||||
routeData.DataTokens[Core.Constants.Web.UmbracoDataToken] = content;
|
||||
|
||||
//the value provider is the default implementation
|
||||
var valueProvider = new Mock<IValueProvider>();
|
||||
//also IUnvalidatedValueProvider
|
||||
var invalidatedValueProvider = valueProvider.As<IUnvalidatedValueProvider>();
|
||||
invalidatedValueProvider.Setup(x => x.GetValue(It.IsAny<string>(), It.IsAny<bool>())).Returns(() =>
|
||||
new ValueProviderResult(content, "content", CultureInfo.CurrentCulture));
|
||||
|
||||
var controllerCtx = new ControllerContext(
|
||||
Mock.Of<HttpContextBase>(http => http.Items == new Dictionary<object, object>()),
|
||||
routeData,
|
||||
Mock.Of<ControllerBase>());
|
||||
var result = binder.BindModel(controllerCtx,
|
||||
new ModelBindingContext
|
||||
{
|
||||
ValueProvider = valueProvider.Object,
|
||||
ModelMetadata = new ModelMetadata(new EmptyModelMetadataProvider(), null, () => null, typeof(IPublishedContent), "content")
|
||||
});
|
||||
|
||||
Assert.AreEqual(content, result);
|
||||
}
|
||||
|
||||
public class MyOtherContent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class MyContent : PublishedContentWrapped
|
||||
{
|
||||
public MyContent(IPublishedContent content) : base(content)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,7 +210,7 @@ function submit()
|
||||
if (findDepth(curLineHTML, cc) !== 0) {
|
||||
// Cursor is inside a <tag>, don't set cursor:
|
||||
curLineHTML = curLineHTML.replace(cc, '');
|
||||
doc.setLine(pos.line, curLineHTML);
|
||||
doc.getLineHandle(pos.line).text = curLineHTML;
|
||||
}
|
||||
|
||||
// Submit HTML to TinyMCE:
|
||||
|
||||
@@ -22,15 +22,35 @@ var packages = angular.module("umbraco.packages", []);
|
||||
//module is initilized.
|
||||
angular.module("umbraco.views", ["umbraco.viewcache"]);
|
||||
angular.module("umbraco.viewcache", [])
|
||||
.run(function($rootScope, $templateCache){
|
||||
/** For debug mode, always clear template cache to cut down on
|
||||
.run(function($rootScope, $templateCache) {
|
||||
/** For debug mode, always clear template cache to cut down on
|
||||
dev frustration and chrome cache on templates */
|
||||
if(Umbraco.Sys.ServerVariables.isDebuggingEnabled){
|
||||
//$rootScope.$on('$viewContentLoaded', function() {
|
||||
$templateCache.removeAll();
|
||||
//});
|
||||
if (Umbraco.Sys.ServerVariables.isDebuggingEnabled) {
|
||||
$templateCache.removeAll();
|
||||
}
|
||||
})
|
||||
})
|
||||
.config([
|
||||
//This ensures that all of our angular views are cache busted, if the path starts with views/ and ends with .html, then
|
||||
// we will append the cache busting value to it. This way all upgraded sites will not have to worry about browser cache.
|
||||
"$provide", function($provide) {
|
||||
return $provide.decorator("$http", [
|
||||
"$delegate", function($delegate) {
|
||||
var get = $delegate.get;
|
||||
$delegate.get = function (url, config) {
|
||||
|
||||
if (Umbraco.Sys.ServerVariables.application && url.startsWith("views/") && url.endsWith(".html")) {
|
||||
var rnd = Umbraco.Sys.ServerVariables.application.version + "." + Umbraco.Sys.ServerVariables.application.cdf;
|
||||
var _op = (url.indexOf("?") > 0) ? "&" : "?";
|
||||
url += _op + "umb__rnd=" + rnd;
|
||||
}
|
||||
|
||||
return get(url, config);
|
||||
};
|
||||
return $delegate;
|
||||
}
|
||||
]);
|
||||
}
|
||||
]);
|
||||
|
||||
//Call a document callback if defined, this is sort of a dodgy hack to
|
||||
// be able to configure angular values in the Default.cshtml
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
if(convert){
|
||||
element.html("<i class='icon-section " + convert + "'></i>");
|
||||
}else{
|
||||
element.html("<img src='images/tray/" + icon + "'>");
|
||||
element.html("<img class='icon-section' src='images/tray/" + icon + "'>");
|
||||
}
|
||||
//it's a file, normally legacy so look in the icon tray images
|
||||
}
|
||||
|
||||
+8
-1
@@ -1,10 +1,13 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function EditorHeaderDirective(iconHelper) {
|
||||
function EditorHeaderDirective(iconHelper, variationsHelper) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
scope.showVariationsQuickSwitch = false;
|
||||
scope.variations = variationsHelper.getVariations();
|
||||
|
||||
scope.openIconPicker = function() {
|
||||
scope.dialogModel = {
|
||||
view: "iconpicker",
|
||||
@@ -24,6 +27,10 @@
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
scope.toggleVariationsQuickSwitch = function() {
|
||||
scope.showVariationsQuickSwitch = !scope.showVariationsQuickSwitch;
|
||||
};
|
||||
}
|
||||
|
||||
var directive = {
|
||||
|
||||
+41
-5
@@ -14,7 +14,8 @@ angular.module("umbraco.directives")
|
||||
templateUrl: 'views/components/imaging/umb-image-gravity.html',
|
||||
scope: {
|
||||
src: '=',
|
||||
center: "="
|
||||
center: "=",
|
||||
onImageLoaded: "="
|
||||
},
|
||||
link: function(scope, element, attrs) {
|
||||
|
||||
@@ -26,6 +27,8 @@ angular.module("umbraco.directives")
|
||||
top: 0
|
||||
};
|
||||
|
||||
scope.loaded = false;
|
||||
|
||||
//elements
|
||||
var $viewport = element.find(".viewport");
|
||||
var $image = element.find("img");
|
||||
@@ -42,6 +45,19 @@ angular.module("umbraco.directives")
|
||||
};
|
||||
};
|
||||
|
||||
scope.setFocalPoint = function(event) {
|
||||
|
||||
scope.$emit("imageFocalPointStart");
|
||||
|
||||
var offsetX = event.offsetX - 10;
|
||||
var offsetY = event.offsetY - 10;
|
||||
|
||||
calculateGravity(offsetX, offsetY);
|
||||
|
||||
lazyEndEvent();
|
||||
|
||||
};
|
||||
|
||||
var setDimensions = function(){
|
||||
scope.dimensions.width = $image.width();
|
||||
scope.dimensions.height = $image.height();
|
||||
@@ -54,9 +70,9 @@ angular.module("umbraco.directives")
|
||||
}
|
||||
};
|
||||
|
||||
var calculateGravity = function(){
|
||||
scope.dimensions.left = $overlay[0].offsetLeft;
|
||||
scope.dimensions.top = $overlay[0].offsetTop;
|
||||
var calculateGravity = function(offsetX, offsetY){
|
||||
scope.dimensions.left = offsetX;
|
||||
scope.dimensions.top = offsetY;
|
||||
|
||||
scope.center.left = (scope.dimensions.left+10) / scope.dimensions.width;
|
||||
scope.center.top = (scope.dimensions.top+10) / scope.dimensions.height;
|
||||
@@ -80,7 +96,9 @@ angular.module("umbraco.directives")
|
||||
},
|
||||
stop: function() {
|
||||
scope.$apply(function(){
|
||||
calculateGravity();
|
||||
var offsetX = $overlay[0].offsetLeft;
|
||||
var offsetY = $overlay[0].offsetTop;
|
||||
calculateGravity(offsetX, offsetY);
|
||||
});
|
||||
|
||||
lazyEndEvent();
|
||||
@@ -91,8 +109,26 @@ angular.module("umbraco.directives")
|
||||
$image.load(function(){
|
||||
$timeout(function(){
|
||||
setDimensions();
|
||||
scope.loaded = true;
|
||||
scope.onImageLoaded();
|
||||
});
|
||||
});
|
||||
|
||||
$(window).on('resize.umbImageGravity', function(){
|
||||
scope.$apply(function(){
|
||||
$timeout(function(){
|
||||
setDimensions();
|
||||
});
|
||||
var offsetX = $overlay[0].offsetLeft;
|
||||
var offsetY = $overlay[0].offsetTop;
|
||||
calculateGravity(offsetX, offsetY);
|
||||
});
|
||||
});
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
$(window).off('.umbImageGravity');
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
+2
@@ -26,6 +26,7 @@ angular.module("umbraco.directives")
|
||||
link: function(scope, element, attrs) {
|
||||
//// INIT /////
|
||||
var $image = element.find("img");
|
||||
scope.loaded = false;
|
||||
|
||||
$image.load(function(){
|
||||
$timeout(function(){
|
||||
@@ -52,6 +53,7 @@ angular.module("umbraco.directives")
|
||||
}
|
||||
|
||||
setPreviewStyle();
|
||||
scope.loaded = true;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function WebsiteSelector() {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
scope.showWebsiteDropdown = false;
|
||||
scope.selectedWebsite = {};
|
||||
|
||||
function activate() {
|
||||
for(var i = 0; i < scope.websites.length; i++) {
|
||||
var website = scope.websites[i];
|
||||
if(website.selected) {
|
||||
scope.selectedWebsite = website;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scope.toggleWebsiteDropDown = function() {
|
||||
scope.showWebsiteDropdown = !scope.showWebsiteDropdown;
|
||||
};
|
||||
|
||||
scope.closeWebsiteDropDown = function() {
|
||||
scope.showWebsiteDropdown = false;
|
||||
};
|
||||
|
||||
scope.createWebsite = function() {
|
||||
if(scope.onCreateWebsite) {
|
||||
scope.onCreateWebsite();
|
||||
scope.closeWebsiteDropDown();
|
||||
}
|
||||
};
|
||||
|
||||
scope.clickWebsite = function(website) {
|
||||
if(scope.onClickWebsite) {
|
||||
scope.onClickWebsite(website);
|
||||
setSelectedWebsite(website, scope.websites);
|
||||
scope.closeWebsiteDropDown();
|
||||
}
|
||||
};
|
||||
|
||||
function setSelectedWebsite(selectedWebsite, websites) {
|
||||
for(var i = 0; i < websites.length; i++) {
|
||||
var website = websites[i];
|
||||
website.selected = false;
|
||||
}
|
||||
selectedWebsite.selected = true;
|
||||
scope.selectedWebsite = selectedWebsite;
|
||||
}
|
||||
|
||||
scope.$watch('websites', function(newValue, oldValue){
|
||||
activate();
|
||||
}, true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-website-selector.html',
|
||||
link: link,
|
||||
scope: {
|
||||
websites: "=",
|
||||
onCreateWebsite: "=",
|
||||
onClickWebsite: "="
|
||||
}
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbWebsiteSelector', WebsiteSelector);
|
||||
|
||||
})();
|
||||
@@ -509,6 +509,16 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
'Failed to check permission for item ' + id);
|
||||
},
|
||||
|
||||
getPermissions: function (nodeIds) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetPermissions"),
|
||||
nodeIds),
|
||||
'Failed to get permissions');
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.contentResource#save
|
||||
|
||||
@@ -29,7 +29,7 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
filterContentTypes: filterContentTypes,
|
||||
filterPropertyTypes: filterPropertyTypes
|
||||
};
|
||||
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
@@ -201,9 +201,9 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
* .then(function() {
|
||||
* alert("node was moved");
|
||||
* }, function(err){
|
||||
* alert("node didnt move:" + err.data.Message);
|
||||
* alert("node didnt move:" + err.data.Message);
|
||||
* });
|
||||
* </pre>
|
||||
* </pre>
|
||||
* @param {Object} args arguments object
|
||||
* @param {Int} args.idd the ID of the node to move
|
||||
* @param {Int} args.parentId the ID of the parent node to move to
|
||||
@@ -230,6 +230,26 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
'Failed to move content');
|
||||
},
|
||||
|
||||
copy: function(args) {
|
||||
if (!args) {
|
||||
throw "args cannot be null";
|
||||
}
|
||||
if (!args.parentId) {
|
||||
throw "args.parentId cannot be null";
|
||||
}
|
||||
if (!args.id) {
|
||||
throw "args.id cannot be null";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCopy"),
|
||||
{
|
||||
parentId: args.parentId,
|
||||
id: args.id
|
||||
}),
|
||||
'Failed to copy content');
|
||||
},
|
||||
|
||||
createContainer: function(parentId, name) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
@@ -237,7 +257,7 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
'Failed to create a folder under parent id ' + parentId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.resources').factory('contentTypeResource', contentTypeResource);
|
||||
|
||||
@@ -53,7 +53,7 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
* .then(function(array) {
|
||||
* $scope.type = type;
|
||||
* });
|
||||
* </pre>
|
||||
* </pre>
|
||||
* @param {Int} mediaId id of the media item to retrive allowed child types for
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
@@ -145,9 +145,9 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
* .then(function() {
|
||||
* alert("node was moved");
|
||||
* }, function(err){
|
||||
* alert("node didnt move:" + err.data.Message);
|
||||
* alert("node didnt move:" + err.data.Message);
|
||||
* });
|
||||
* </pre>
|
||||
* </pre>
|
||||
* @param {Object} args arguments object
|
||||
* @param {Int} args.idd the ID of the node to move
|
||||
* @param {Int} args.parentId the ID of the parent node to move to
|
||||
@@ -174,6 +174,26 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
'Failed to move content');
|
||||
},
|
||||
|
||||
copy: function (args) {
|
||||
if (!args) {
|
||||
throw "args cannot be null";
|
||||
}
|
||||
if (!args.parentId) {
|
||||
throw "args.parentId cannot be null";
|
||||
}
|
||||
if (!args.id) {
|
||||
throw "args.id cannot be null";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostCopy"),
|
||||
{
|
||||
parentId: args.parentId,
|
||||
id: args.id
|
||||
}),
|
||||
'Failed to copy content');
|
||||
},
|
||||
|
||||
createContainer: function(parentId, name) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
|
||||
@@ -16,7 +16,7 @@ function treeResource($q, $http, umbRequestHelper) {
|
||||
/** internal method to get the tree menu url */
|
||||
function getTreeMenuUrl(node) {
|
||||
if (!node.menuUrl) {
|
||||
throw "No menuUrl property found on the tree node, cannot load menu";
|
||||
return null;
|
||||
}
|
||||
return node.menuUrl;
|
||||
}
|
||||
@@ -26,10 +26,16 @@ function treeResource($q, $http, umbRequestHelper) {
|
||||
|
||||
/** Loads in the data to display the nodes menu */
|
||||
loadMenu: function (node) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(getTreeMenuUrl(node)),
|
||||
"Failed to retrieve data for a node's menu " + node.id);
|
||||
var treeMenuUrl = getTreeMenuUrl(node);
|
||||
if (treeMenuUrl !== undefined && treeMenuUrl !== null && treeMenuUrl.length > 0) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(getTreeMenuUrl(node)),
|
||||
"Failed to retrieve data for a node's menu " + node.id);
|
||||
} else {
|
||||
return $q.reject({
|
||||
errorMsg: "No tree menu url defined for node " + node.id
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/** Loads in the data to display the nodes for an application */
|
||||
|
||||
@@ -55,7 +55,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
|
||||
var deferred = $q.defer();
|
||||
|
||||
if (!args.scope.busy && formHelper.submitForm({ scope: args.scope, statusMessage: args.statusMessage })) {
|
||||
if (!args.scope.busy && formHelper.submitForm({ scope: args.scope, statusMessage: args.statusMessage, action: args.action })) {
|
||||
|
||||
args.scope.busy = true;
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ function formHelper(angularHelper, serverValidationManager, $timeout, notificati
|
||||
}
|
||||
|
||||
//the first thing any form must do is broadcast the formSubmitting event
|
||||
args.scope.$broadcast("formSubmitting", { scope: args.scope });
|
||||
args.scope.$broadcast("formSubmitting", { scope: args.scope, action: args.action });
|
||||
|
||||
//then check if the form is valid
|
||||
if (!args.skipValidation) {
|
||||
|
||||
@@ -1,270 +1,323 @@
|
||||
// This service was based on OpenJS library available in BSD License
|
||||
// http://www.openjs.com/scripts/events/keyboard_shortcuts/index.php
|
||||
angular.module('umbraco.services')
|
||||
.factory('keyboardService', ['$window', '$timeout', function ($window, $timeout) {
|
||||
var keyboardManagerService = {};
|
||||
var defaultOpt = {
|
||||
'type': 'keydown',
|
||||
'propagate': false,
|
||||
'inputDisabled': false,
|
||||
'target': $window.document,
|
||||
'keyCode': false
|
||||
};
|
||||
|
||||
var isMac = navigator.platform.toUpperCase().indexOf('MAC')>=0;
|
||||
function keyboardService($window, $timeout) {
|
||||
|
||||
var keyboardManagerService = {};
|
||||
|
||||
var defaultOpt = {
|
||||
'type': 'keydown',
|
||||
'propagate': false,
|
||||
'inputDisabled': false,
|
||||
'target': $window.document,
|
||||
'keyCode': false
|
||||
};
|
||||
|
||||
// Store all keyboard combination shortcuts
|
||||
keyboardManagerService.keyboardEvent = {};
|
||||
// Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
|
||||
var shift_nums = {
|
||||
"`": "~",
|
||||
"1": "!",
|
||||
"2": "@",
|
||||
"3": "#",
|
||||
"4": "$",
|
||||
"5": "%",
|
||||
"6": "^",
|
||||
"7": "&",
|
||||
"8": "*",
|
||||
"9": "(",
|
||||
"0": ")",
|
||||
"-": "_",
|
||||
"=": "+",
|
||||
";": ":",
|
||||
"'": "\"",
|
||||
",": "<",
|
||||
".": ">",
|
||||
"/": "?",
|
||||
"\\": "|"
|
||||
};
|
||||
|
||||
// Special Keys - and their codes
|
||||
var special_keys = {
|
||||
'esc': 27,
|
||||
'escape': 27,
|
||||
'tab': 9,
|
||||
'space': 32,
|
||||
'return': 13,
|
||||
'enter': 13,
|
||||
'backspace': 8,
|
||||
|
||||
// Add a new keyboard combination shortcut
|
||||
keyboardManagerService.bind = function (label, callback, opt) {
|
||||
'scrolllock': 145,
|
||||
'scroll_lock': 145,
|
||||
'scroll': 145,
|
||||
'capslock': 20,
|
||||
'caps_lock': 20,
|
||||
'caps': 20,
|
||||
'numlock': 144,
|
||||
'num_lock': 144,
|
||||
'num': 144,
|
||||
|
||||
//replace ctrl key with meta key
|
||||
if(isMac && label !== "ctrl+space"){
|
||||
label = label.replace("ctrl","meta");
|
||||
}
|
||||
'pause': 19,
|
||||
'break': 19,
|
||||
|
||||
var fct, elt, code, k;
|
||||
// Initialize opt object
|
||||
opt = angular.extend({}, defaultOpt, opt);
|
||||
label = label.toLowerCase();
|
||||
elt = opt.target;
|
||||
if(typeof opt.target === 'string'){
|
||||
elt = document.getElementById(opt.target);
|
||||
}
|
||||
'insert': 45,
|
||||
'home': 36,
|
||||
'delete': 46,
|
||||
'end': 35,
|
||||
|
||||
'pageup': 33,
|
||||
'page_up': 33,
|
||||
'pu': 33,
|
||||
|
||||
fct = function (e) {
|
||||
e = e || $window.event;
|
||||
'pagedown': 34,
|
||||
'page_down': 34,
|
||||
'pd': 34,
|
||||
|
||||
// Disable event handler when focus input and textarea
|
||||
if (opt['inputDisabled']) {
|
||||
var elt;
|
||||
if (e.target){
|
||||
elt = e.target;
|
||||
}else if (e.srcElement){
|
||||
elt = e.srcElement;
|
||||
}
|
||||
'left': 37,
|
||||
'up': 38,
|
||||
'right': 39,
|
||||
'down': 40,
|
||||
|
||||
if (elt.nodeType === 3){elt = elt.parentNode;}
|
||||
if (elt.tagName === 'INPUT' || elt.tagName === 'TEXTAREA'){return;}
|
||||
}
|
||||
'f1': 112,
|
||||
'f2': 113,
|
||||
'f3': 114,
|
||||
'f4': 115,
|
||||
'f5': 116,
|
||||
'f6': 117,
|
||||
'f7': 118,
|
||||
'f8': 119,
|
||||
'f9': 120,
|
||||
'f10': 121,
|
||||
'f11': 122,
|
||||
'f12': 123
|
||||
};
|
||||
|
||||
// Find out which key is pressed
|
||||
if (e.keyCode){
|
||||
code = e.keyCode;
|
||||
}else if (e.which){
|
||||
code = e.which;
|
||||
}
|
||||
var isMac = navigator.platform.toUpperCase().indexOf('MAC')>=0;
|
||||
|
||||
var character = String.fromCharCode(code).toLowerCase();
|
||||
// The event handler for bound element events
|
||||
function eventHandler(e) {
|
||||
e = e || $window.event;
|
||||
|
||||
if (code === 188){character = ",";} // If the user presses , when the type is onkeydown
|
||||
if (code === 190){character = ".";} // If the user presses , when the type is onkeydown
|
||||
var code, k;
|
||||
|
||||
var keys = label.split("+");
|
||||
// Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
|
||||
var kp = 0;
|
||||
// Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
|
||||
var shift_nums = {
|
||||
"`":"~",
|
||||
"1":"!",
|
||||
"2":"@",
|
||||
"3":"#",
|
||||
"4":"$",
|
||||
"5":"%",
|
||||
"6":"^",
|
||||
"7":"&",
|
||||
"8":"*",
|
||||
"9":"(",
|
||||
"0":")",
|
||||
"-":"_",
|
||||
"=":"+",
|
||||
";":":",
|
||||
"'":"\"",
|
||||
",":"<",
|
||||
".":">",
|
||||
"/":"?",
|
||||
"\\":"|"
|
||||
};
|
||||
// Special Keys - and their codes
|
||||
var special_keys = {
|
||||
'esc':27,
|
||||
'escape':27,
|
||||
'tab':9,
|
||||
'space':32,
|
||||
'return':13,
|
||||
'enter':13,
|
||||
'backspace':8,
|
||||
// Find out which key is pressed
|
||||
if (e.keyCode)
|
||||
{
|
||||
code = e.keyCode;
|
||||
}
|
||||
else if (e.which) {
|
||||
code = e.which;
|
||||
}
|
||||
|
||||
'scrolllock':145,
|
||||
'scroll_lock':145,
|
||||
'scroll':145,
|
||||
'capslock':20,
|
||||
'caps_lock':20,
|
||||
'caps':20,
|
||||
'numlock':144,
|
||||
'num_lock':144,
|
||||
'num':144,
|
||||
var character = String.fromCharCode(code).toLowerCase();
|
||||
|
||||
'pause':19,
|
||||
'break':19,
|
||||
if (code === 188){character = ",";} // If the user presses , when the type is onkeydown
|
||||
if (code === 190){character = ".";} // If the user presses , when the type is onkeydown
|
||||
|
||||
'insert':45,
|
||||
'home':36,
|
||||
'delete':46,
|
||||
'end':35,
|
||||
var propagate = true;
|
||||
|
||||
'pageup':33,
|
||||
'page_up':33,
|
||||
'pu':33,
|
||||
//Now we need to determine which shortcut this event is for, we'll do this by iterating over each
|
||||
//registered shortcut to find the match. We use Find here so that the loop exits as soon
|
||||
//as we've found the one we're looking for
|
||||
_.find(_.keys(keyboardManagerService.keyboardEvent), function(key) {
|
||||
|
||||
'pagedown':34,
|
||||
'page_down':34,
|
||||
'pd':34,
|
||||
var shortcutLabel = key;
|
||||
var shortcutVal = keyboardManagerService.keyboardEvent[key];
|
||||
|
||||
'left':37,
|
||||
'up':38,
|
||||
'right':39,
|
||||
'down':40,
|
||||
// Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
|
||||
var kp = 0;
|
||||
|
||||
'f1':112,
|
||||
'f2':113,
|
||||
'f3':114,
|
||||
'f4':115,
|
||||
'f5':116,
|
||||
'f6':117,
|
||||
'f7':118,
|
||||
'f8':119,
|
||||
'f9':120,
|
||||
'f10':121,
|
||||
'f11':122,
|
||||
'f12':123
|
||||
};
|
||||
// Some modifiers key
|
||||
var modifiers = {
|
||||
shift: {
|
||||
wanted: false,
|
||||
pressed: e.shiftKey ? true : false
|
||||
},
|
||||
ctrl : {
|
||||
wanted: false,
|
||||
pressed: e.ctrlKey ? true : false
|
||||
},
|
||||
alt : {
|
||||
wanted: false,
|
||||
pressed: e.altKey ? true : false
|
||||
},
|
||||
meta : { //Meta is Mac specific
|
||||
wanted: false,
|
||||
pressed: e.metaKey ? true : false
|
||||
}
|
||||
};
|
||||
// Foreach keys in label (split on +)
|
||||
var l = keys.length;
|
||||
for (var i = 0; i < l; i++) {
|
||||
// Some modifiers key
|
||||
var modifiers = {
|
||||
shift: {
|
||||
wanted: false,
|
||||
pressed: e.shiftKey ? true : false
|
||||
},
|
||||
ctrl: {
|
||||
wanted: false,
|
||||
pressed: e.ctrlKey ? true : false
|
||||
},
|
||||
alt: {
|
||||
wanted: false,
|
||||
pressed: e.altKey ? true : false
|
||||
},
|
||||
meta: { //Meta is Mac specific
|
||||
wanted: false,
|
||||
pressed: e.metaKey ? true : false
|
||||
}
|
||||
};
|
||||
|
||||
var k=keys[i];
|
||||
switch (k) {
|
||||
case 'ctrl':
|
||||
case 'control':
|
||||
kp++;
|
||||
modifiers.ctrl.wanted = true;
|
||||
break;
|
||||
case 'shift':
|
||||
case 'alt':
|
||||
case 'meta':
|
||||
kp++;
|
||||
modifiers[k].wanted = true;
|
||||
break;
|
||||
}
|
||||
var keys = shortcutLabel.split("+");
|
||||
var opt = shortcutVal.opt;
|
||||
var callback = shortcutVal.callback;
|
||||
|
||||
if (k.length > 1) { // If it is a special key
|
||||
if(special_keys[k] === code){
|
||||
kp++;
|
||||
}
|
||||
// Foreach keys in label (split on +)
|
||||
var l = keys.length;
|
||||
for (var i = 0; i < l; i++) {
|
||||
|
||||
} else if (opt['keyCode']) { // If a specific key is set into the config
|
||||
if (opt['keyCode'] === code) {
|
||||
kp++;
|
||||
}
|
||||
var k = keys[i];
|
||||
switch (k) {
|
||||
case 'ctrl':
|
||||
case 'control':
|
||||
kp++;
|
||||
modifiers.ctrl.wanted = true;
|
||||
break;
|
||||
case 'shift':
|
||||
case 'alt':
|
||||
case 'meta':
|
||||
kp++;
|
||||
modifiers[k].wanted = true;
|
||||
break;
|
||||
}
|
||||
|
||||
} else { // The special keys did not match
|
||||
if(character === k) {
|
||||
kp++;
|
||||
}else {
|
||||
if(shift_nums[character] && e.shiftKey) { // Stupid Shift key bug created by using lowercase
|
||||
character = shift_nums[character];
|
||||
if(character === k){
|
||||
kp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (k.length > 1) { // If it is a special key
|
||||
if (special_keys[k] === code) {
|
||||
kp++;
|
||||
}
|
||||
}
|
||||
else if (opt['keyCode']) { // If a specific key is set into the config
|
||||
if (opt['keyCode'] === code) {
|
||||
kp++;
|
||||
}
|
||||
}
|
||||
else { // The special keys did not match
|
||||
if (character === k) {
|
||||
kp++;
|
||||
}
|
||||
else {
|
||||
if (shift_nums[character] && e.shiftKey) { // Stupid Shift key bug created by using lowercase
|
||||
character = shift_nums[character];
|
||||
if (character === k) {
|
||||
kp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} //for end
|
||||
} //for end
|
||||
|
||||
if(kp === keys.length &&
|
||||
modifiers.ctrl.pressed === modifiers.ctrl.wanted &&
|
||||
modifiers.shift.pressed === modifiers.shift.wanted &&
|
||||
modifiers.alt.pressed === modifiers.alt.wanted &&
|
||||
modifiers.meta.pressed === modifiers.meta.wanted) {
|
||||
$timeout(function() {
|
||||
callback(e);
|
||||
}, 1);
|
||||
if (kp === keys.length &&
|
||||
modifiers.ctrl.pressed === modifiers.ctrl.wanted &&
|
||||
modifiers.shift.pressed === modifiers.shift.wanted &&
|
||||
modifiers.alt.pressed === modifiers.alt.wanted &&
|
||||
modifiers.meta.pressed === modifiers.meta.wanted) {
|
||||
|
||||
if(!opt['propagate']) { // Stop the event
|
||||
// e.cancelBubble is supported by IE - this will kill the bubbling process.
|
||||
e.cancelBubble = true;
|
||||
e.returnValue = false;
|
||||
//found the right callback!
|
||||
|
||||
// e.stopPropagation works in Firefox.
|
||||
if (e.stopPropagation) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
// Store shortcut
|
||||
keyboardManagerService.keyboardEvent[label] = {
|
||||
'callback': fct,
|
||||
'target': elt,
|
||||
'event': opt['type']
|
||||
};
|
||||
// Disable event handler when focus input and textarea
|
||||
if (opt['inputDisabled']) {
|
||||
var elt;
|
||||
if (e.target) {
|
||||
elt = e.target;
|
||||
} else if (e.srcElement) {
|
||||
elt = e.srcElement;
|
||||
}
|
||||
|
||||
//Attach the function with the event
|
||||
if(elt.addEventListener){
|
||||
elt.addEventListener(opt['type'], fct, false);
|
||||
}else if(elt.attachEvent){
|
||||
elt.attachEvent('on' + opt['type'], fct);
|
||||
}else{
|
||||
elt['on' + opt['type']] = fct;
|
||||
}
|
||||
};
|
||||
// Remove the shortcut - just specify the shortcut and I will remove the binding
|
||||
keyboardManagerService.unbind = function (label) {
|
||||
label = label.toLowerCase();
|
||||
var binding = keyboardManagerService.keyboardEvent[label];
|
||||
delete(keyboardManagerService.keyboardEvent[label]);
|
||||
if (elt.nodeType === 3) { elt = elt.parentNode; }
|
||||
if (elt.tagName === 'INPUT' || elt.tagName === 'TEXTAREA') {
|
||||
//This exits the Find loop
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!binding){return;}
|
||||
$timeout(function () {
|
||||
callback(e);
|
||||
}, 1);
|
||||
|
||||
var type = binding['event'],
|
||||
if (!opt['propagate']) { // Stop the event
|
||||
propagate = false;
|
||||
}
|
||||
|
||||
//This exits the Find loop
|
||||
return true;
|
||||
}
|
||||
|
||||
//we haven't found one so continue looking
|
||||
return false;
|
||||
|
||||
});
|
||||
|
||||
// Stop the event if required
|
||||
if (!propagate) {
|
||||
// e.cancelBubble is supported by IE - this will kill the bubbling process.
|
||||
e.cancelBubble = true;
|
||||
e.returnValue = false;
|
||||
|
||||
// e.stopPropagation works in Firefox.
|
||||
if (e.stopPropagation) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Store all keyboard combination shortcuts
|
||||
keyboardManagerService.keyboardEvent = {};
|
||||
|
||||
// Add a new keyboard combination shortcut
|
||||
keyboardManagerService.bind = function (label, callback, opt) {
|
||||
|
||||
//replace ctrl key with meta key
|
||||
if(isMac && label !== "ctrl+space"){
|
||||
label = label.replace("ctrl","meta");
|
||||
}
|
||||
|
||||
var elt;
|
||||
// Initialize opt object
|
||||
opt = angular.extend({}, defaultOpt, opt);
|
||||
label = label.toLowerCase();
|
||||
elt = opt.target;
|
||||
if(typeof opt.target === 'string'){
|
||||
elt = document.getElementById(opt.target);
|
||||
}
|
||||
|
||||
//Ensure we aren't double binding to the same element + type otherwise we'll end up multi-binding
|
||||
// and raising events for now reason. So here we'll check if the event is already registered for the element
|
||||
var boundValues = _.values(keyboardManagerService.keyboardEvent);
|
||||
var found = _.find(boundValues, function (i) {
|
||||
return i.target === elt && i.event === opt['type'];
|
||||
});
|
||||
|
||||
// Store shortcut
|
||||
keyboardManagerService.keyboardEvent[label] = {
|
||||
'callback': callback,
|
||||
'target': elt,
|
||||
'opt': opt['type']
|
||||
};
|
||||
|
||||
if (!found) {
|
||||
//Attach the function with the event
|
||||
if (elt.addEventListener) {
|
||||
elt.addEventListener(opt['type'], eventHandler, false);
|
||||
} else if (elt.attachEvent) {
|
||||
elt.attachEvent('on' + opt['type'], eventHandler);
|
||||
} else {
|
||||
elt['on' + opt['type']] = eventHandler;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
// Remove the shortcut - just specify the shortcut and I will remove the binding
|
||||
keyboardManagerService.unbind = function (label) {
|
||||
label = label.toLowerCase();
|
||||
var binding = keyboardManagerService.keyboardEvent[label];
|
||||
delete(keyboardManagerService.keyboardEvent[label]);
|
||||
|
||||
if(!binding){return;}
|
||||
|
||||
var type = binding['event'],
|
||||
elt = binding['target'],
|
||||
callback = binding['callback'];
|
||||
|
||||
if(elt.detachEvent){
|
||||
elt.detachEvent('on' + type, callback);
|
||||
}else if(elt.removeEventListener){
|
||||
elt.removeEventListener(type, callback, false);
|
||||
}else{
|
||||
elt['on'+type] = false;
|
||||
}
|
||||
};
|
||||
//
|
||||
if(elt.detachEvent){
|
||||
elt.detachEvent('on' + type, callback);
|
||||
}else if(elt.removeEventListener){
|
||||
elt.removeEventListener(type, callback, false);
|
||||
}else{
|
||||
elt['on'+type] = false;
|
||||
}
|
||||
};
|
||||
//
|
||||
|
||||
return keyboardManagerService;
|
||||
}]);
|
||||
return keyboardManagerService;
|
||||
}
|
||||
@@ -1,288 +1,319 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function listViewHelper(localStorageService) {
|
||||
function listViewHelper(localStorageService) {
|
||||
|
||||
var firstSelectedIndex = 0;
|
||||
var localStorageKey = "umblistViewLayout";
|
||||
var firstSelectedIndex = 0;
|
||||
var localStorageKey = "umblistViewLayout";
|
||||
|
||||
function getLayout(nodeId, availableLayouts) {
|
||||
function getLayout(nodeId, availableLayouts) {
|
||||
|
||||
var storedLayouts = [];
|
||||
var storedLayouts = [];
|
||||
|
||||
if(localStorageService.get(localStorageKey)) {
|
||||
storedLayouts = localStorageService.get(localStorageKey);
|
||||
}
|
||||
|
||||
if (storedLayouts && storedLayouts.length > 0) {
|
||||
for (var i = 0; storedLayouts.length > i; i++) {
|
||||
var layout = storedLayouts[i];
|
||||
if (layout.nodeId === nodeId) {
|
||||
return setLayout(nodeId, layout, availableLayouts);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return getFirstAllowedLayout(availableLayouts);
|
||||
|
||||
}
|
||||
|
||||
function setLayout(nodeId, selectedLayout, availableLayouts) {
|
||||
|
||||
var activeLayout = {};
|
||||
var layoutFound = false;
|
||||
|
||||
for (var i = 0; availableLayouts.length > i; i++) {
|
||||
var layout = availableLayouts[i];
|
||||
if (layout.path === selectedLayout.path) {
|
||||
activeLayout = layout;
|
||||
layout.active = true;
|
||||
layoutFound = true;
|
||||
} else {
|
||||
layout.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!layoutFound) {
|
||||
activeLayout = getFirstAllowedLayout(availableLayouts);
|
||||
}
|
||||
|
||||
saveLayoutInLocalStorage(nodeId, activeLayout);
|
||||
|
||||
return activeLayout;
|
||||
|
||||
}
|
||||
|
||||
function saveLayoutInLocalStorage(nodeId, selectedLayout) {
|
||||
var layoutFound = false;
|
||||
var storedLayouts = [];
|
||||
|
||||
if(localStorageService.get(localStorageKey)) {
|
||||
storedLayouts = localStorageService.get(localStorageKey);
|
||||
}
|
||||
|
||||
if(storedLayouts.length > 0) {
|
||||
for(var i = 0; storedLayouts.length > i; i++) {
|
||||
var layout = storedLayouts[i];
|
||||
if(layout.nodeId === nodeId) {
|
||||
layout.path = selectedLayout.path;
|
||||
layoutFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!layoutFound) {
|
||||
var storageObject = {
|
||||
"nodeId": nodeId,
|
||||
"path": selectedLayout.path
|
||||
};
|
||||
storedLayouts.push(storageObject);
|
||||
}
|
||||
|
||||
localStorageService.set(localStorageKey, storedLayouts);
|
||||
|
||||
}
|
||||
|
||||
function getFirstAllowedLayout(layouts) {
|
||||
|
||||
var firstAllowedLayout = {};
|
||||
|
||||
for (var i = 0; layouts.length > i; i++) {
|
||||
var layout = layouts[i];
|
||||
if (layout.selected === true) {
|
||||
firstAllowedLayout = layout;
|
||||
break;
|
||||
if (localStorageService.get(localStorageKey)) {
|
||||
storedLayouts = localStorageService.get(localStorageKey);
|
||||
}
|
||||
}
|
||||
|
||||
return firstAllowedLayout;
|
||||
}
|
||||
if (storedLayouts && storedLayouts.length > 0) {
|
||||
for (var i = 0; storedLayouts.length > i; i++) {
|
||||
var layout = storedLayouts[i];
|
||||
if (layout.nodeId === nodeId) {
|
||||
return setLayout(nodeId, layout, availableLayouts);
|
||||
}
|
||||
}
|
||||
|
||||
function selectHandler(selectedItem, selectedIndex, items, selection, $event) {
|
||||
}
|
||||
|
||||
var start = 0;
|
||||
var end = 0;
|
||||
var item = null;
|
||||
return getFirstAllowedLayout(availableLayouts);
|
||||
|
||||
if ($event.shiftKey === true) {
|
||||
}
|
||||
|
||||
if(selectedIndex > firstSelectedIndex) {
|
||||
function setLayout(nodeId, selectedLayout, availableLayouts) {
|
||||
|
||||
start = firstSelectedIndex;
|
||||
end = selectedIndex;
|
||||
var activeLayout = {};
|
||||
var layoutFound = false;
|
||||
|
||||
for (; end >= start; start++) {
|
||||
item = items[start];
|
||||
selectItem(item, selection);
|
||||
}
|
||||
for (var i = 0; availableLayouts.length > i; i++) {
|
||||
var layout = availableLayouts[i];
|
||||
if (layout.path === selectedLayout.path) {
|
||||
activeLayout = layout;
|
||||
layout.active = true;
|
||||
layoutFound = true;
|
||||
} else {
|
||||
layout.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!layoutFound) {
|
||||
activeLayout = getFirstAllowedLayout(availableLayouts);
|
||||
}
|
||||
|
||||
saveLayoutInLocalStorage(nodeId, activeLayout);
|
||||
|
||||
return activeLayout;
|
||||
|
||||
}
|
||||
|
||||
function saveLayoutInLocalStorage(nodeId, selectedLayout) {
|
||||
var layoutFound = false;
|
||||
var storedLayouts = [];
|
||||
|
||||
if (localStorageService.get(localStorageKey)) {
|
||||
storedLayouts = localStorageService.get(localStorageKey);
|
||||
}
|
||||
|
||||
if (storedLayouts.length > 0) {
|
||||
for (var i = 0; storedLayouts.length > i; i++) {
|
||||
var layout = storedLayouts[i];
|
||||
if (layout.nodeId === nodeId) {
|
||||
layout.path = selectedLayout.path;
|
||||
layoutFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!layoutFound) {
|
||||
var storageObject = {
|
||||
"nodeId": nodeId,
|
||||
"path": selectedLayout.path
|
||||
};
|
||||
storedLayouts.push(storageObject);
|
||||
}
|
||||
|
||||
localStorageService.set(localStorageKey, storedLayouts);
|
||||
|
||||
}
|
||||
|
||||
function getFirstAllowedLayout(layouts) {
|
||||
|
||||
var firstAllowedLayout = {};
|
||||
|
||||
for (var i = 0; layouts.length > i; i++) {
|
||||
var layout = layouts[i];
|
||||
if (layout.selected === true) {
|
||||
firstAllowedLayout = layout;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return firstAllowedLayout;
|
||||
}
|
||||
|
||||
function selectHandler(selectedItem, selectedIndex, items, selection, $event) {
|
||||
|
||||
var start = 0;
|
||||
var end = 0;
|
||||
var item = null;
|
||||
|
||||
if ($event.shiftKey === true) {
|
||||
|
||||
if (selectedIndex > firstSelectedIndex) {
|
||||
|
||||
start = firstSelectedIndex;
|
||||
end = selectedIndex;
|
||||
|
||||
for (; end >= start; start++) {
|
||||
item = items[start];
|
||||
selectItem(item, selection);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
start = firstSelectedIndex;
|
||||
end = selectedIndex;
|
||||
|
||||
for (; end <= start; start--) {
|
||||
item = items[start];
|
||||
selectItem(item, selection);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
start = firstSelectedIndex;
|
||||
end = selectedIndex;
|
||||
if (selectedItem.selected) {
|
||||
deselectItem(selectedItem, selection);
|
||||
} else {
|
||||
selectItem(selectedItem, selection);
|
||||
}
|
||||
|
||||
for (; end <= start; start--) {
|
||||
item = items[start];
|
||||
selectItem(item, selection);
|
||||
}
|
||||
firstSelectedIndex = selectedIndex;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
|
||||
if(selectedItem.selected) {
|
||||
deselectItem(selectedItem, selection);
|
||||
} else {
|
||||
selectItem(selectedItem, selection);
|
||||
function selectItem(item, selection) {
|
||||
var isSelected = false;
|
||||
for (var i = 0; selection.length > i; i++) {
|
||||
var selectedItem = selection[i];
|
||||
if (item.id === selectedItem.id) {
|
||||
isSelected = true;
|
||||
}
|
||||
}
|
||||
if (!isSelected) {
|
||||
selection.push({ id: item.id });
|
||||
item.selected = true;
|
||||
}
|
||||
}
|
||||
|
||||
function deselectItem(item, selection) {
|
||||
for (var i = 0; selection.length > i; i++) {
|
||||
var selectedItem = selection[i];
|
||||
if (item.id === selectedItem.id) {
|
||||
selection.splice(i, 1);
|
||||
item.selected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearSelection(items, folders, selection) {
|
||||
|
||||
var i = 0;
|
||||
|
||||
selection.length = 0;
|
||||
|
||||
if (angular.isArray(items)) {
|
||||
for (i = 0; items.length > i; i++) {
|
||||
var item = items[i];
|
||||
item.selected = false;
|
||||
}
|
||||
}
|
||||
|
||||
firstSelectedIndex = selectedIndex;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function selectItem(item, selection) {
|
||||
var isSelected = false;
|
||||
for (var i = 0; selection.length > i; i++) {
|
||||
var selectedItem = selection[i];
|
||||
if (item.id === selectedItem.id) {
|
||||
isSelected = true;
|
||||
if (angular.isArray(items)) {
|
||||
for (i = 0; folders.length > i; i++) {
|
||||
var folder = folders[i];
|
||||
folder.selected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!isSelected) {
|
||||
selection.push({id: item.id});
|
||||
item.selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function deselectItem(item, selection) {
|
||||
for (var i = 0; selection.length > i; i++) {
|
||||
var selectedItem = selection[i];
|
||||
if (item.id === selectedItem.id) {
|
||||
selection.splice(i, 1);
|
||||
item.selected = false;
|
||||
function selectAllItems(items, selection, $event) {
|
||||
|
||||
var checkbox = $event.target;
|
||||
var clearSelection = false;
|
||||
|
||||
if (!angular.isArray(items)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearSelection(items, folders, selection) {
|
||||
selection.length = 0;
|
||||
|
||||
var i = 0;
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
|
||||
selection.length = 0;
|
||||
var item = items[i];
|
||||
|
||||
if (checkbox.checked) {
|
||||
selection.push({ id: item.id });
|
||||
} else {
|
||||
clearSelection = true;
|
||||
}
|
||||
|
||||
item.selected = checkbox.checked;
|
||||
|
||||
if(angular.isArray(items)) {
|
||||
for(i = 0; items.length > i; i++) {
|
||||
var item = items[i];
|
||||
item.selected = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(angular.isArray(items)) {
|
||||
for(i = 0; folders.length > i; i++) {
|
||||
var folder = folders[i];
|
||||
folder.selected = false;
|
||||
if (clearSelection) {
|
||||
selection.length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectAllItems(items, selection, $event) {
|
||||
}
|
||||
|
||||
var checkbox = $event.target;
|
||||
var clearSelection = false;
|
||||
function isSelectedAll(items, selection) {
|
||||
|
||||
if (!angular.isArray(items)) {
|
||||
return;
|
||||
}
|
||||
var numberOfSelectedItem = 0;
|
||||
|
||||
selection.length = 0;
|
||||
for (var itemIndex = 0; items.length > itemIndex; itemIndex++) {
|
||||
var item = items[itemIndex];
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
for (var selectedIndex = 0; selection.length > selectedIndex; selectedIndex++) {
|
||||
var selectedItem = selection[selectedIndex];
|
||||
|
||||
var item = items[i];
|
||||
if (item.id === selectedItem.id) {
|
||||
numberOfSelectedItem++;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkbox.checked) {
|
||||
selection.push({id: item.id});
|
||||
} else {
|
||||
clearSelection = true;
|
||||
}
|
||||
}
|
||||
|
||||
item.selected = checkbox.checked;
|
||||
if (numberOfSelectedItem === items.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (clearSelection) {
|
||||
selection.length = 0;
|
||||
}
|
||||
function setSortingDirection(col, direction, options) {
|
||||
return options.orderBy.toUpperCase() === col.toUpperCase() && options.orderDirection === direction;
|
||||
}
|
||||
|
||||
}
|
||||
function setSorting(field, allow, options) {
|
||||
if (allow) {
|
||||
options.orderBy = field;
|
||||
|
||||
function isSelectedAll(items, selection) {
|
||||
if (options.orderDirection === "desc") {
|
||||
options.orderDirection = "asc";
|
||||
} else {
|
||||
options.orderDirection = "desc";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//This takes in a dictionary of Ids with Permissions and determines
|
||||
// the intersect of all permissions to return an object representing the
|
||||
// listview button permissions
|
||||
function getButtonPermissions(unmergedPermissions, currentIdsWithPermissions) {
|
||||
|
||||
if (currentIdsWithPermissions == null) {
|
||||
currentIdsWithPermissions = {};
|
||||
}
|
||||
|
||||
var numberOfSelectedItem = 0;
|
||||
//merge the newly retrieved permissions to the main dictionary
|
||||
_.each(unmergedPermissions, function (value, key, list) {
|
||||
currentIdsWithPermissions[key] = value;
|
||||
});
|
||||
|
||||
for(var itemIndex = 0; items.length > itemIndex; itemIndex++) {
|
||||
var item = items[itemIndex];
|
||||
//get the intersect permissions
|
||||
var arr = [];
|
||||
_.each(currentIdsWithPermissions, function (value, key, list) {
|
||||
arr.push(value);
|
||||
});
|
||||
|
||||
for(var selectedIndex = 0; selection.length > selectedIndex; selectedIndex++) {
|
||||
var selectedItem = selection[selectedIndex];
|
||||
//we need to use 'apply' to call intersection with an array of arrays,
|
||||
//see: http://stackoverflow.com/a/16229480/694494
|
||||
var intersectPermissions = _.intersection.apply(_, arr);
|
||||
|
||||
if(item.id === selectedItem.id) {
|
||||
numberOfSelectedItem++;
|
||||
}
|
||||
}
|
||||
return {
|
||||
canCopy: _.contains(intersectPermissions, 'O'), //Magic Char = O
|
||||
canCreate: _.contains(intersectPermissions, 'C'), //Magic Char = C
|
||||
canDelete: _.contains(intersectPermissions, 'D'), //Magic Char = D
|
||||
canMove: _.contains(intersectPermissions, 'M'), //Magic Char = M
|
||||
canPublish: _.contains(intersectPermissions, 'U'), //Magic Char = U
|
||||
canUnpublish: _.contains(intersectPermissions, 'U'), //Magic Char = Z (however UI says it can't be set, so if we can publish 'U' we can unpublish)
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
var service = {
|
||||
getLayout: getLayout,
|
||||
getFirstAllowedLayout: getFirstAllowedLayout,
|
||||
setLayout: setLayout,
|
||||
saveLayoutInLocalStorage: saveLayoutInLocalStorage,
|
||||
selectHandler: selectHandler,
|
||||
selectItem: selectItem,
|
||||
deselectItem: deselectItem,
|
||||
clearSelection: clearSelection,
|
||||
selectAllItems: selectAllItems,
|
||||
isSelectedAll: isSelectedAll,
|
||||
setSortingDirection: setSortingDirection,
|
||||
setSorting: setSorting,
|
||||
getButtonPermissions: getButtonPermissions
|
||||
};
|
||||
|
||||
if(numberOfSelectedItem === items.length) {
|
||||
return true;
|
||||
}
|
||||
return service;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setSortingDirection(col, direction, options) {
|
||||
return options.orderBy.toUpperCase() === col.toUpperCase() && options.orderDirection === direction;
|
||||
}
|
||||
|
||||
|
||||
function setSorting(field, allow, options) {
|
||||
if (allow) {
|
||||
options.orderBy = field;
|
||||
|
||||
if (options.orderDirection === "desc") {
|
||||
options.orderDirection = "asc";
|
||||
} else {
|
||||
options.orderDirection = "desc";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var service = {
|
||||
getLayout: getLayout,
|
||||
getFirstAllowedLayout: getFirstAllowedLayout,
|
||||
setLayout: setLayout,
|
||||
saveLayoutInLocalStorage: saveLayoutInLocalStorage,
|
||||
selectHandler: selectHandler,
|
||||
selectItem: selectItem,
|
||||
deselectItem: deselectItem,
|
||||
clearSelection: clearSelection,
|
||||
selectAllItems: selectAllItems,
|
||||
isSelectedAll: isSelectedAll,
|
||||
setSortingDirection: setSortingDirection,
|
||||
setSorting: setSorting
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
|
||||
angular.module('umbraco.services').factory('listViewHelper', listViewHelper);
|
||||
angular.module('umbraco.services').factory('listViewHelper', listViewHelper);
|
||||
|
||||
|
||||
})();
|
||||
|
||||
@@ -21,6 +21,7 @@ function packageHelper(assetsService, treeService, eventsService, $templateCache
|
||||
}
|
||||
angular.module('umbraco.services').factory('packageHelper', packageHelper);
|
||||
|
||||
//TODO: I believe this is obsolete
|
||||
function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, mediaHelper, umbRequestHelper) {
|
||||
return {
|
||||
/** sets the image's url, thumbnail and if its a folder */
|
||||
@@ -319,7 +320,6 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco.services").factory("umbPhotoFolderHelper", umbPhotoFolderHelper);
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function variationsHelper() {
|
||||
|
||||
var variations = [];
|
||||
|
||||
function setMaster(master) {
|
||||
master.master = true;
|
||||
variations.push(master);
|
||||
}
|
||||
|
||||
function getVariations() {
|
||||
return variations;
|
||||
}
|
||||
|
||||
function createVariation(variation) {
|
||||
var newVariation = angular.copy(variation);
|
||||
newVariation.master = false;
|
||||
variations.push(newVariation);
|
||||
}
|
||||
|
||||
function saveVariation(updatedVariation) {
|
||||
|
||||
for(var i = 0; i < variations.length; i++) {
|
||||
|
||||
var variation = variations[i];
|
||||
|
||||
if(variation.id === updatedVariation) {
|
||||
variation.name = updatedVariation.name;
|
||||
variation.description = updatedVariation.description;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function cloneVariation(variation) {
|
||||
var variationClone = angular.copy(variation);
|
||||
variationClone.master = false;
|
||||
variationClone.published = false;
|
||||
variations.push(variationClone);
|
||||
console.log(variations);
|
||||
}
|
||||
|
||||
function deleteVariation(variation, event, index) {
|
||||
variations.splice(index, 1);
|
||||
}
|
||||
|
||||
var service = {
|
||||
setMaster: setMaster,
|
||||
getVariations: getVariations,
|
||||
createVariation: createVariation,
|
||||
saveVariation: saveVariation,
|
||||
cloneVariation: cloneVariation,
|
||||
deleteVariation: deleteVariation
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
|
||||
angular.module('umbraco.services').factory('variationsHelper', variationsHelper);
|
||||
|
||||
})();
|
||||
@@ -155,6 +155,53 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
|
||||
}
|
||||
};
|
||||
|
||||
$scope.websites = [
|
||||
{
|
||||
name: "English",
|
||||
language: "en-UK",
|
||||
selected: true
|
||||
},
|
||||
{
|
||||
name: "Dansk",
|
||||
language: "da-DK",
|
||||
selected: false
|
||||
}
|
||||
];
|
||||
|
||||
$scope.createWebsite = function() {
|
||||
|
||||
$scope.createWebsiteOverlay = {
|
||||
view: "createwebsite",
|
||||
title: "Create website",
|
||||
submitButtonLabel: "Create website",
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
|
||||
// deselct all current sites
|
||||
for(var i = 0; i < $scope.websites.length; i++) {
|
||||
var website = $scope.websites[i];
|
||||
website.selected = false;
|
||||
}
|
||||
|
||||
// set new site to selected and push to scope
|
||||
model.website.selected = true;
|
||||
$scope.websites.push(model.website);
|
||||
|
||||
// clsoe overlay
|
||||
$scope.createWebsiteOverlay.show = false;
|
||||
$scope.createWebsiteOverlay = null;
|
||||
},
|
||||
close: function() {
|
||||
$scope.createWebsiteOverlay.show = false;
|
||||
$scope.createWebsiteOverlay = null;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
$scope.clickWebsite = function(website) {
|
||||
};
|
||||
|
||||
//ensure to unregister from all events!
|
||||
$scope.$on('$destroy', function () {
|
||||
for (var e in evts) {
|
||||
|
||||
@@ -107,7 +107,9 @@
|
||||
@import "components/umb-grid.less";
|
||||
@import "components/umb-empty-state.less";
|
||||
@import "components/umb-property-editor.less";
|
||||
|
||||
@import "components/umb-iconpicker.less";
|
||||
@import "components/umb-website-selector.less";
|
||||
@import "components/umb-dots.less";
|
||||
@import "components/buttons/umb-button.less";
|
||||
@import "components/buttons/umb-button-group.less";
|
||||
|
||||
|
||||
@@ -152,6 +152,30 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- OVERLAY TREE ---------- */
|
||||
.umb-overlay.umb-overlay-tree {
|
||||
position: absolute;
|
||||
width: 500px;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
bottom: 0;
|
||||
border: none;
|
||||
//box-shadow: 0 0 20px rgba(0,0,0,0.19), 0 0 6px rgba(0,0,0,0.23);
|
||||
box-shadow: 3px 0 7px #dbdbdb;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.umb-overlay.umb-overlay-tree .umb-overlay-header {
|
||||
flex-basis: 100px;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.umb-overlay.umb-overlay-tree .umb-overlay-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- OVERLAY ITEM DETAILS ---------- */
|
||||
.umb-overlay__item-details {
|
||||
position: absolute;
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
.umb-dots {
|
||||
position: relative;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background-color: @gray;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.umb-dots:before,
|
||||
.umb-dots:after {
|
||||
display: block;
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background-color: @gray;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.umb-dots:before {
|
||||
transform: translateX(-8px);
|
||||
}
|
||||
|
||||
.umb-dots:after {
|
||||
transform: translateX(8px);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
.umb-iconpicker {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.umb-iconpicker-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex: 0 0 14.28%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
margin-bottom: 0;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.umb-iconpicker-item a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
padding: 15px 0;
|
||||
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.umb-iconpicker-item a:hover,
|
||||
.umb-iconpicker-item a:focus{
|
||||
background: darken(@grayLighter, 1%);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.umb-iconpicker-item a:active {
|
||||
background: darken(@grayLighter, 4%);
|
||||
}
|
||||
|
||||
.umb-iconpicker-item i {
|
||||
font-size: 30px;
|
||||
}
|
||||
@@ -16,8 +16,23 @@
|
||||
|
||||
.umb-keyboard-shortcuts-overview__overlay-close {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
font-size: 25px;
|
||||
border-radius: 20px;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.umb-keyboard-shortcuts-overview__overlay-close:hover {
|
||||
background-color: @blue;
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.umb-keyboard-shortcuts-overview__overlay-content {
|
||||
|
||||
@@ -198,6 +198,7 @@ input.umb-table__input {
|
||||
padding: 6px 2px;
|
||||
|
||||
text-align: left;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.umb-table-cell > * {
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
.umb-website-selector {
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
height: 50px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.umb-website-selector__create-website {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: @blue;
|
||||
}
|
||||
|
||||
.umb-website-selector__dropdown-toggle {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.umb-website-selector__dropdown-toggle:hover,
|
||||
.umb-website-selector__dropdown-toggle:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.umb-website-selector__dropdown-toggle-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.umb-website-selector__dropdown-toggle-name {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.umb-website-selector__dropdown {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.umb-website-selector__websites {
|
||||
margin-left: 0;
|
||||
margin-bottom: 0;
|
||||
list-style: none;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.umb-website-selector__website-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-top: 10px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 38px;
|
||||
}
|
||||
|
||||
.umb-website-selector__website-link:hover,
|
||||
.umb-website-selector__website-link.-selected {
|
||||
background-color: @grayLighter;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.umb-website-selector__dropdown-action {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
color: @blue;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.umb-website-selector__dropdown-arrow {
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.umb-website-selector__dropdown-arrow.-down {
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-top: 4px solid @gray;
|
||||
}
|
||||
|
||||
.umb-website-selector__dropdown-arrow.-up {
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-bottom: 4px solid @gray;
|
||||
}
|
||||
|
||||
.umb-website-selector__dropdown-action:hover {
|
||||
text-decoration: none;
|
||||
background: @blue;
|
||||
color: #ffffff;
|
||||
}
|
||||
@@ -16,12 +16,12 @@ label small, .guiDialogTiny {
|
||||
font-size: 11px
|
||||
}
|
||||
|
||||
label.control-label {
|
||||
label.control-label, .control-label {
|
||||
padding: 0 10px 0 0 !important;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.umb-status-label{
|
||||
color: @gray !important;
|
||||
}
|
||||
@@ -164,7 +164,7 @@ textarea {
|
||||
|
||||
// Identify controls by their labels
|
||||
label {
|
||||
display: block;
|
||||
display: inline-block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ h5.-black {
|
||||
}
|
||||
|
||||
/* LABELS*/
|
||||
.umb-control-group label.control-label {
|
||||
.umb-control-group label.control-label, .umb-control-group .control-label {
|
||||
text-align: left;
|
||||
}
|
||||
.umb-control-group label.control-label > div > label {
|
||||
|
||||
@@ -9,13 +9,41 @@
|
||||
color: @white;
|
||||
position: absolute;
|
||||
z-index: 10000;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
margin: 0 !Important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0 !important;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
|
||||
only screen and (min-resolution: 144dpi)
|
||||
{
|
||||
.login-overlay {
|
||||
background-image: url(../img/application/logo@2x.png) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 2),
|
||||
only screen and (min-resolution: 192dpi)
|
||||
{
|
||||
.login-overlay {
|
||||
background-image: url(../img/application/logo@2x.png) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 3),
|
||||
only screen and (min-resolution: 3dppx),
|
||||
only screen and (min-resolution: 350dpi)
|
||||
{
|
||||
.login-overlay {
|
||||
background-image: url(../img/application/logo@3x.png) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.login-overlay .umb-modalcolumn {
|
||||
background: none;
|
||||
border: none;
|
||||
@@ -62,7 +90,7 @@
|
||||
}
|
||||
|
||||
#hrOr hr {
|
||||
margin: 0px;
|
||||
margin: 0;
|
||||
border: none;
|
||||
background-color: @gray;
|
||||
height: 1px;
|
||||
|
||||
@@ -493,3 +493,66 @@ input.umb-panel-header-description {
|
||||
.umb-editor-drawer-content__left-side {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* --- VARIATIONS --- */
|
||||
.umb-variations-quick-switcher__toggle {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.umb-variations-quick-switcher_variations {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 20;
|
||||
background-color: #ffffff;
|
||||
max-height: 200px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.umb-variations-quick-switcher__variation {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.umb-variations-quick-switcher__variation:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.umb-variations-quick-switcher__variation:hover,
|
||||
.umb-variations-quick-switcher__variation:focus {
|
||||
background-color: @grayLighter;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.umb-variations-quick-switcher__variation-published-state {
|
||||
display: block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: @grayLight;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.umb-variations-quick-switcher__variation-published-state.-published {
|
||||
background-color: @green;
|
||||
}
|
||||
|
||||
.umb-variations-quick-switcher__variation-name {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.umb-variations-quick-switcher__variation-description {
|
||||
font-size: 12px;
|
||||
color: @gray;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,9 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
font-size:16px !important;
|
||||
}
|
||||
|
||||
/* pre-value editor */
|
||||
.rte-editor-preval .control-group .controls > div > label .mce-ico { line-height: 20px; }
|
||||
|
||||
|
||||
//
|
||||
// Color picker
|
||||
@@ -275,11 +278,12 @@ ul.color-picker li a {
|
||||
|
||||
.umb-cropper{
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.umb-cropper img, .umb-cropper-gravity img{
|
||||
position: absolute;
|
||||
position: relative;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
@@ -293,19 +297,22 @@ ul.color-picker li a {
|
||||
left: 0;
|
||||
cursor: move;
|
||||
z-index: 6001;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.umb-cropper .viewport{
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
margin: auto;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.umb-cropper-gravity .viewport{
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 400px;
|
||||
height: 300px
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -335,27 +342,45 @@ ul.color-picker li a {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.umb-cropper-gravity .overlay i{
|
||||
.umb-cropper-gravity .overlay i {
|
||||
font-size: 26px;
|
||||
line-height: 26px;
|
||||
opacity: 0.8 !important;
|
||||
}
|
||||
|
||||
.umb-cropper .crop-container{
|
||||
.umb-cropper .crop-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.umb-cropper .crop-slider{
|
||||
vertical-align: middle;
|
||||
padding: 10px 50px 10px 50px;
|
||||
.umb-cropper .crop-slider {
|
||||
padding: 10px;
|
||||
border-top: 1px solid @grayLighter;
|
||||
margin-top: 10px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
flex-wrap: wrap;
|
||||
|
||||
@media (min-width: 769px) {
|
||||
padding: 10px 50px 10px 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-cropper .crop-slider i{color: @gray;}
|
||||
.umb-cropper .crop-slider input{
|
||||
margin-top: 7px;
|
||||
width: 320px;
|
||||
.umb-cropper .crop-slider i {
|
||||
color: @gray;
|
||||
flex: 0 0 25px;
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.umb-cropper .crop-slider i:first-of-type {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.umb-cropper .crop-slider input {
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
.umb-cropper-gravity .viewport, .umb-cropper-gravity, .umb-cropper-imageholder {
|
||||
display: inline-block;
|
||||
@@ -372,55 +397,98 @@ ul.color-picker li a {
|
||||
}
|
||||
|
||||
.gravity-container .viewport {
|
||||
width: 494px;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.gravity-container .viewport:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.imagecropper {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: row;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
flex-direction: column;
|
||||
float: left;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.imagecropper .umb-cropper__container {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
max-width: 100%;
|
||||
border: 1px solid #f8f8f8;
|
||||
|
||||
@media (min-width: 769px) {
|
||||
width: 600px;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-close-cropper {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.umb-close-cropper:hover {
|
||||
opacity: .9;
|
||||
background: @grayLighter;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails {
|
||||
border-left: 2px solid #f8f8f8;
|
||||
margin-left: 4px;
|
||||
padding-left: 2px;
|
||||
float: left;
|
||||
width: 100px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails li {
|
||||
display: block;
|
||||
}
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails li.current a, .imagecropper .umb-sortable-thumbnails li.current a:hover {
|
||||
background: #eeeeee;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails li:first-of-type {
|
||||
padding: 8px;
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails li .crop-name, .imagecropper .umb-sortable-thumbnails li .crop-size {
|
||||
.imagecropper .umb-sortable-thumbnails li.current {
|
||||
border-color: @grayLight;
|
||||
background: @grayLighter;
|
||||
color: @black;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails li:hover,
|
||||
.imagecropper .umb-sortable-thumbnails li.current:hover {
|
||||
border-color: @grayLight;
|
||||
background: @grayLighter;
|
||||
color: @black;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
opacity: .95;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails li .crop-name,
|
||||
.imagecropper .umb-sortable-thumbnails li .crop-size {
|
||||
display: block;
|
||||
text-align: left;
|
||||
font-size: 11px;
|
||||
font-size: 13px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails li .crop-name {
|
||||
font-weight: bold;
|
||||
margin: 10px 0 5px;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails li .crop-size {
|
||||
font-size: 10px;
|
||||
font-style: italic;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails li a {
|
||||
display: block;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails li a:hover {
|
||||
background: #f8f8f8;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails li a:hover .crop-text {
|
||||
text-decoration: none;
|
||||
margin: 0 0 5px;
|
||||
}
|
||||
|
||||
.btn-crop-delete {
|
||||
@@ -428,20 +496,6 @@ ul.color-picker li a {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails.many {
|
||||
width: 210px;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails.many li {
|
||||
width: 85px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.imagecropper .umb-sortable-thumbnails.many li:nth-child(2) {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
//
|
||||
// folder-browser
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -19,7 +19,8 @@ ul.sections li {
|
||||
}
|
||||
|
||||
ul.sections li [class^="icon-"]:before,
|
||||
ul.sections li [class*=" icon-"]:before{
|
||||
ul.sections li [class*=" icon-"]:before,
|
||||
ul.sections li img.icon-section {
|
||||
font-size: 30px;
|
||||
margin: 1px 0 0 0;
|
||||
opacity: 0.4;
|
||||
@@ -29,7 +30,8 @@ ul.sections li [class*=" icon-"]:before{
|
||||
}
|
||||
|
||||
ul.sections:hover li [class^="icon-"]:before,
|
||||
ul.sections:hover li [class*=" icon-"]:before {
|
||||
ul.sections:hover li [class*=" icon-"]:before,
|
||||
ul.sections:hover li img.icon-section {
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
|
||||
@@ -2,55 +2,48 @@
|
||||
<div class="umb-panel-header">
|
||||
<div class="umb-el-wrap umb-panel-buttons">
|
||||
<div class="form-search">
|
||||
<i class="icon-search"></i>
|
||||
<i class="icon-search"></i>
|
||||
<input type="text"
|
||||
style="width: 100%"
|
||||
ng-model="searchTerm"
|
||||
class="umb-search-field search-query input-block-level"
|
||||
style="width: 100%"
|
||||
ng-model="searchTerm"
|
||||
class="umb-search-field search-query input-block-level"
|
||||
placeholder="Filter...">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-panel-body with-footer">
|
||||
|
||||
|
||||
<div class="umb-control-group">
|
||||
<select ng-model="color" class="input-block-level">
|
||||
<option value="">Black</option>
|
||||
<option value="color-green">Green</option>
|
||||
<option value="color-yellow">Yellow</option>
|
||||
<option value="color-green">Green</option>
|
||||
<option value="color-yellow">Yellow</option>
|
||||
<option value="color-orange">Orange</option>
|
||||
<option value="color-blue">Blue</option>
|
||||
<option value="color-blue">Blue</option>
|
||||
<option value="color-red">Red</option>
|
||||
</select>
|
||||
<!--
|
||||
<select class="input-block-level">
|
||||
<option value="">Black</option>
|
||||
<option value="color-green">Green</option>
|
||||
<option value="color-blue">Turquoise</option>
|
||||
<option value="color-purple">Purple</option>
|
||||
<option value="color-red">Red</option>
|
||||
<option value="color-orange">Orange</option>
|
||||
<option value="color-sky-blue">Sky blue</option>
|
||||
<option value="color-yellow">Yellow</option>
|
||||
</select>-->
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-loader" ng-hide="icons"></div>
|
||||
<umb-load-indicator ng-if="loading"></umb-load-indicator>
|
||||
|
||||
<div class="umb-control-group">
|
||||
<ul class="umb-thumbnails thumbnails" ng-class="color">
|
||||
<li class="span1" ng-repeat="icon in icons|filter: searchTerm">
|
||||
<a href="#" title="{{icon}}" class="thumbnail" ng-click="submitClass(icon)" prevent-default>
|
||||
<i class="{{icon}} large" style="font-size: 32px"></i>
|
||||
<div class="umb-control-group" ng-show="!loading">
|
||||
<ul class="umb-iconpicker" ng-class="color" ng-show="icons">
|
||||
<li class="umb-iconpicker-item" ng-repeat="icon in filtered = (icons | filter: searchTerm) track by $id(icon)">
|
||||
<a href="#" title="{{icon}}" ng-click="submitClass(icon)" prevent-default>
|
||||
<i class="{{icon}} large"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="filtered.length === 0"
|
||||
position="center">
|
||||
<localize key="defaultdialogs_noIconsFound">No icons were found.</localize>
|
||||
</umb-empty-state>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="umb-panel-footer" >
|
||||
<div class="umb-el-wrap umb-panel-buttons">
|
||||
<div class="btn-toolbar umb-btn-toolbar pull-right">
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
function CreateWebsiteOverlay($scope) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
$scope.model.website = {};
|
||||
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Overlay.CreateWebsiteOverlay", CreateWebsiteOverlay);
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,26 @@
|
||||
<div ng-controller="Umbraco.Overlay.CreateWebsiteOverlay as vm">
|
||||
|
||||
<div class="umb-control-group control-group">
|
||||
<label>Website name</label>
|
||||
<input type="text" ng-model="model.website.name" />
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group control-group">
|
||||
<label>Website language</label>
|
||||
<select ng-model="model.website.language">
|
||||
<option value="aa-DJ">Afar (Djinouti) [aa-DJ]</option>
|
||||
<option value="aa-ER">Afar (Eritrea) [aa-ER]</option>
|
||||
<option value="aa-ET">Afar (Ethiopia) [aa-ET]</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group control-group">
|
||||
<label>Create blank</label>
|
||||
<input type="checkbox" ng-model="model.website.blank" />
|
||||
<label>Copy all</label>
|
||||
<input type="checkbox" ng-model="model.website.copyAll" />
|
||||
<label>Copy selected</label>
|
||||
<input type="checkbox" ng-model="model.website.copySelected" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -38,14 +38,19 @@
|
||||
|
||||
<umb-load-indicator ng-if="loading"></umb-load-indicator>
|
||||
|
||||
<div class="umb-control-group" ng-show="!loading">
|
||||
<ul class="umb-thumbnails thumbnails" ng-class="color">
|
||||
<li class="span1" ng-repeat="icon in icons|filter: searchTerm">
|
||||
<a href="#" title="{{icon}}" class="thumbnail" ng-click="selectIcon(icon, color)" prevent-default>
|
||||
<i class="{{icon}} large" style="font-size: 32px"></i>
|
||||
<div class="umb-control-group" ng-show="!loading && filtered.length > 0 ">
|
||||
<ul class="umb-iconpicker" ng-class="color" ng-show="icons">
|
||||
<li class="umb-iconpicker-item" ng-repeat="icon in filtered = (icons | filter: searchTerm) track by $id(icon)">
|
||||
<a href="#" title="{{icon}}" ng-click="selectIcon(icon, color)" prevent-default>
|
||||
<i class="{{icon}} large"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="filtered.length === 0"
|
||||
position="center">
|
||||
<localize key="defaultdialogs_noIconsFound">No icons were found.</localize>
|
||||
</umb-empty-state>
|
||||
</div>
|
||||
|
||||
@@ -65,8 +65,14 @@
|
||||
|
||||
</div>
|
||||
|
||||
<umb-website-selector
|
||||
websites="websites"
|
||||
on-create-website="createWebsite"
|
||||
on-click-website="clickWebsite">
|
||||
</umb-website-selector>
|
||||
|
||||
<!-- the tree -->
|
||||
<div id="tree" class="umb-modalcolumn-body" ng-if="authenticated">
|
||||
<div id="tree" ng-if="authenticated && websites.length > 0">
|
||||
<umb-tree
|
||||
cachekey="_"
|
||||
eventhandler="treeEventHandler"
|
||||
@@ -87,6 +93,12 @@
|
||||
</umb-context-menu>
|
||||
</div>
|
||||
|
||||
<umb-overlay
|
||||
ng-if="createWebsiteOverlay.show"
|
||||
model="createWebsiteOverlay"
|
||||
view="createWebsiteOverlay.view"
|
||||
position="tree">
|
||||
</umb-overlay>
|
||||
|
||||
<!-- Tree dialogs -->
|
||||
<div id="dialog" class='umb-modalcolumn fill shadow'
|
||||
|
||||
@@ -1,62 +1,62 @@
|
||||
<div>
|
||||
<div id="applications" ng-class="{faded:stickyNavigation}">
|
||||
<ul class="sections">
|
||||
<li class="avatar">
|
||||
<a href="#" ng-click="avatarClick()" hotkey="ctrl+shift+u" title="{{user.name}}" prevent-default>
|
||||
<img id="avatar-img" ng-src="{{avatar[0].value}}" ng-srcset="{{avatar[1].value}} 2x, {{avatar[2].value}} 3x" />
|
||||
</a>
|
||||
</li>
|
||||
<li ng-repeat="section in sections | limitTo: maxSections" ng-class="{current: section.alias == currentSection}">
|
||||
<a href="#/{{section.alias}}"
|
||||
ng-dblclick="sectionDblClick(section)"
|
||||
ng-click="sectionClick($event, section)"
|
||||
prevent-default>
|
||||
<section-icon icon="{{section.cssclass}}"></section-icon>
|
||||
<span>{{section.name}}</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="expand" ng-class="{ 'open': showTray === true }" ng-show="needTray">
|
||||
<a href ng-click="trayClick()">
|
||||
<i class="icon icon-arrow-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="help">
|
||||
<a href class="help" hotkey="ctrl+shift+h" ng-click="helpClick()" prevent-default>
|
||||
<i class="icon-help-alt"></i>
|
||||
<span><localize key="sections_help">Help</localize></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="applications-tray" ng-show="showTray" ng-animate="trayAnimation()">
|
||||
<ul class="sections sections-tray">
|
||||
<li ng-repeat="section in sections | limitTo: overflowingSections" ng-class="{current: section.alias == currentSection}">
|
||||
<a href="#/{{section.alias}}"
|
||||
ng-dblclick="sectionDblClick(section)"
|
||||
ng-click="sectionClick($event, section)"
|
||||
prevent-default>
|
||||
<section-icon icon="{{section.cssclass}}"></section-icon>
|
||||
<span>{{section.name}}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<umb-overlay
|
||||
ng-if="helpDialog.show"
|
||||
model="helpDialog"
|
||||
view="helpDialog.view"
|
||||
position="left">
|
||||
</umb-overlay>
|
||||
|
||||
<umb-overlay
|
||||
ng-if="userDialog.show"
|
||||
model="userDialog"
|
||||
view="userDialog.view"
|
||||
position="left">
|
||||
</umb-overlay>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<div id="applications" ng-class="{faded:stickyNavigation}">
|
||||
<ul class="sections">
|
||||
<li class="avatar">
|
||||
<a href="#" ng-click="avatarClick()" hotkey="ctrl+shift+u" title="{{user.name}}" prevent-default>
|
||||
<img id="avatar-img" ng-src="{{avatar[0].value}}" ng-srcset="{{avatar[1].value}} 2x, {{avatar[2].value}} 3x" />
|
||||
</a>
|
||||
</li>
|
||||
<li ng-repeat="section in sections | limitTo: maxSections" ng-class="{current: section.alias == currentSection}">
|
||||
<a href="#/{{section.alias}}"
|
||||
ng-dblclick="sectionDblClick(section)"
|
||||
ng-click="sectionClick($event, section)"
|
||||
prevent-default>
|
||||
<section-icon icon="{{section.cssclass}}"></section-icon>
|
||||
<span>{{section.name}}</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="expand" ng-class="{ 'open': showTray === true }" ng-show="needTray">
|
||||
<a href ng-click="trayClick()">
|
||||
<i class="icon icon-arrow-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="help">
|
||||
<a href class="help" hotkey="ctrl+shift+h" ng-click="helpClick()" prevent-default>
|
||||
<i class="icon-help-alt"></i>
|
||||
<span><localize key="sections_help">Help</localize></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="applications-tray" ng-show="showTray" ng-animate="trayAnimation()" style="display: none;">
|
||||
<ul class="sections sections-tray">
|
||||
<li ng-repeat="section in sections | limitTo: overflowingSections" ng-class="{current: section.alias == currentSection}">
|
||||
<a href="#/{{section.alias}}"
|
||||
ng-dblclick="sectionDblClick(section)"
|
||||
ng-click="sectionClick($event, section)"
|
||||
prevent-default>
|
||||
<section-icon icon="{{section.cssclass}}"></section-icon>
|
||||
<span>{{section.name}}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<umb-overlay
|
||||
ng-if="helpDialog.show"
|
||||
model="helpDialog"
|
||||
view="helpDialog.view"
|
||||
position="left">
|
||||
</umb-overlay>
|
||||
|
||||
<umb-overlay
|
||||
ng-if="userDialog.show"
|
||||
model="userDialog"
|
||||
view="userDialog.view"
|
||||
position="left">
|
||||
</umb-overlay>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -31,10 +31,14 @@
|
||||
|
||||
<div class="umb-panel-header-name" ng-if="nameLocked">{{ name }}</div>
|
||||
|
||||
<umb-generate-alias class="umb-panel-header-alias"
|
||||
ng-if="!hideAlias"
|
||||
alias="$parent.alias"
|
||||
alias-from="$parent.name"
|
||||
<a class="umb-variations-quick-switcher__toggle" href="" ng-click="toggleVariationsQuickSwitch()">
|
||||
<i class="icon-documents"></i>
|
||||
</a>
|
||||
|
||||
<umb-generate-alias class="umb-panel-header-alias"
|
||||
ng-if="!hideAlias"
|
||||
alias="$parent.alias"
|
||||
alias-from="$parent.name"
|
||||
enable-lock="true"
|
||||
server-validation-field="Alias"></umb-generate-alias>
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<div class="umb-cropper-gravity">
|
||||
<div class="gravity-container">
|
||||
<div class="gravity-container" ng-show="loaded">
|
||||
<div class="viewport">
|
||||
<img ng-src="{{src}}" style="max-width: 100%; max-height: 100%" />
|
||||
<img ng-src="{{src}}" style="max-width: 100%; max-height: 100%" ng-click="setFocalPoint($event)" draggable="false" />
|
||||
|
||||
<div class="overlay" ng-style="style()">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<div class="umb-crop-thumbnail-container"
|
||||
ng-style="{height: height, width: width, overflow: 'hidden', position: 'relative'}">
|
||||
<div class="umb-crop-thumbnail-container"
|
||||
ng-style="{height: height, width: width, overflow: 'hidden', position: 'relative'}"
|
||||
ng-show="loaded">
|
||||
<img ng-src="{{src}}" alt="{{}}" ng-style="preview" class="noScale" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="umb-overlay umb-overlay-{{position}}" on-outside-click="closeOverLay()">
|
||||
<form class="umb-overlay__form" name="overlayForm" ng-submit="submitForm(model)" novalidate val-form-manager>
|
||||
<ng-form class="umb-overlay__form" name="overlayForm" novalidate val-form-manager>
|
||||
|
||||
<div class="umb-overlay-header">
|
||||
<h4 class="umb-overlay__title">{{model.title}}</h4>
|
||||
@@ -44,8 +44,9 @@
|
||||
<umb-button
|
||||
button-style="success"
|
||||
label="Confirm"
|
||||
type="submit"
|
||||
disabled="!directive.enableConfirmButton">
|
||||
type="button"
|
||||
disabled="!directive.enableConfirmButton"
|
||||
action="submitForm(model)">
|
||||
</umb-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -64,10 +65,11 @@
|
||||
label-key="{{model.submitButtonLabelKey}}"
|
||||
label="{{model.submitButtonLabel}}"
|
||||
ng-if="model.submit && model.hideSubmitButton !== true"
|
||||
type="submit">
|
||||
type="button"
|
||||
action="submitForm(model)">
|
||||
</umb-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</ng-form>
|
||||
</div>
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
<div>
|
||||
<ul class="umb-tree">
|
||||
<li class="root">
|
||||
<ul class="umb-search-group">
|
||||
<li ng-repeat="result in results">
|
||||
<div style="padding-left: 20px">
|
||||
<a class="umb-search-group-item-link" ng-class="{first:$first}" ng-click="selectResultCallback($event, result)">
|
||||
<div class="umb-search-group-item-name">
|
||||
<i class="icon umb-tree-icon sprTree {{result.icon}}"></i>
|
||||
{{result.name}}
|
||||
</div>
|
||||
<small class="search-subtitle" ng-if="result.subTitle">{{result.subTitle}}</small>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ul class="umb-tree">
|
||||
|
||||
<li class="root">
|
||||
<ul class="umb-search-group">
|
||||
|
||||
<li ng-repeat="result in results">
|
||||
|
||||
<div style="padding-left: 20px" ng-class="{'umb-tree-node-checked' : result.selected}">
|
||||
<a class="umb-search-group-item-link" ng-class="{first:$first}" ng-click="selectResultCallback($event, result)">
|
||||
<div class="umb-search-group-item-name">
|
||||
<i class="icon umb-tree-icon sprTree {{result.icon}}"></i>
|
||||
{{result.name}}
|
||||
</div>
|
||||
<small class="search-subtitle" ng-if="result.subTitle">{{result.subTitle}}</small>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
<div class="umb-keyboard-shortcuts-overview__overlay" ng-if="shortcutOverlay">
|
||||
|
||||
<a href="" ng-click="toggleShortcutsOverlay()" data-hotkey="esc">
|
||||
<i class="umb-keyboard-shortcuts-overview__overlay-close icon-delete"></i>
|
||||
<a href="" class="umb-keyboard-shortcuts-overview__overlay-close" ng-click="toggleShortcutsOverlay()" data-hotkey="esc" hotkey-when-hidden="true">
|
||||
<i class="icon-delete"></i>
|
||||
</a>
|
||||
|
||||
<div class="umb-keyboard-shortcuts-overview__overlay-content">
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<div class="umb-website-selector" on-outside-click="closeWebsiteDropDown()">
|
||||
|
||||
<a class="umb-website-selector__create-website" ng-if="websites.length === 0" href="" ng-click="createWebsite()">
|
||||
Create website
|
||||
</span>
|
||||
|
||||
<a class="umb-website-selector__dropdown-toggle" ng-if="websites.length > 0" href="" ng-click="toggleWebsiteDropDown()">
|
||||
<div class="umb-website-selector__dropdown-toggle-content">
|
||||
<span ng-if="showWebsiteDropdown" class="umb-website-selector__dropdown-arrow -up"></span>
|
||||
<span ng-if="!showWebsiteDropdown" class="umb-website-selector__dropdown-arrow -down"></span>
|
||||
<span class="umb-website-selector__dropdown-toggle-name">{{ selectedWebsite.name }}</span>
|
||||
<small>({{ selectedWebsite.language }})</small>
|
||||
</div>
|
||||
<div class="umb-dots"></div>
|
||||
</a>
|
||||
|
||||
<div class="umb-website-selector__dropdown shadow-depth-3" ng-show="showWebsiteDropdown">
|
||||
<ul class="umb-website-selector__websites">
|
||||
<li class="umb-website-selector__website" ng-repeat="website in websites | filter:{ selected: '!'+true }">
|
||||
<a class="umb-website-selector__website-link" ng-click="clickWebsite(website)" href="" ng-class="{'-selecetd': website.selected}">
|
||||
<div>
|
||||
<span class="umb-website-selector__website-name">{{ website.name}}</span>
|
||||
<small>({{ website.language }})</small>
|
||||
</div>
|
||||
<div class="umb-dots"></div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a class="umb-website-selector__dropdown-action" ng-click="createWebsite()" href="">Create website</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -82,7 +82,8 @@ function ContentEditController($scope, $rootScope, $routeParams, $q, $timeout, $
|
||||
statusMessage: args.statusMessage,
|
||||
saveMethod: args.saveMethod,
|
||||
scope: $scope,
|
||||
content: $scope.content
|
||||
content: $scope.content,
|
||||
action: args.action
|
||||
}).then(function (data) {
|
||||
//success
|
||||
init($scope.content);
|
||||
@@ -195,15 +196,15 @@ function ContentEditController($scope, $rootScope, $routeParams, $q, $timeout, $
|
||||
};
|
||||
|
||||
$scope.sendToPublish = function () {
|
||||
return performSave({ saveMethod: contentResource.sendToPublish, statusMessage: "Sending..." });
|
||||
return performSave({ saveMethod: contentResource.sendToPublish, statusMessage: "Sending...", action: "sendToPublish" });
|
||||
};
|
||||
|
||||
$scope.saveAndPublish = function () {
|
||||
return performSave({ saveMethod: contentResource.publish, statusMessage: "Publishing..." });
|
||||
return performSave({ saveMethod: contentResource.publish, statusMessage: "Publishing...", action: "publish" });
|
||||
};
|
||||
|
||||
$scope.save = function () {
|
||||
return performSave({ saveMethod: contentResource.save, statusMessage: "Saving..." });
|
||||
return performSave({ saveMethod: contentResource.save, statusMessage: "Saving...", action: "save" });
|
||||
};
|
||||
|
||||
$scope.preview = function (content) {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Editors.DocumentTypes.CopyController",
|
||||
function ($scope, contentTypeResource, treeService, navigationService, notificationsService, appState, eventsService) {
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if ($scope.target) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.target.selected = false;
|
||||
}
|
||||
|
||||
$scope.target = args.node;
|
||||
$scope.target.selected = true;
|
||||
}
|
||||
|
||||
$scope.copy = function () {
|
||||
|
||||
$scope.busy = true;
|
||||
$scope.error = false;
|
||||
|
||||
contentTypeResource.copy({ parentId: $scope.target.id, id: dialogOptions.currentNode.id })
|
||||
.then(function (path) {
|
||||
$scope.error = false;
|
||||
$scope.success = true;
|
||||
$scope.busy = false;
|
||||
|
||||
//get the currently edited node (if any)
|
||||
var activeNode = appState.getTreeState("selectedNode");
|
||||
|
||||
//we need to do a double sync here: first sync to the copied content - but don't activate the node,
|
||||
//then sync to the currenlty edited content (note: this might not be the content that was copied!!)
|
||||
|
||||
navigationService.syncTree({ tree: "documentTypes", path: path, forceReload: true, activate: false }).then(function (args) {
|
||||
if (activeNode) {
|
||||
var activeNodePath = treeService.getPath(activeNode).join();
|
||||
//sync to this node now - depending on what was copied this might already be synced but might not be
|
||||
navigationService.syncTree({ tree: "documentTypes", path: activeNodePath, forceReload: false, activate: true });
|
||||
}
|
||||
});
|
||||
|
||||
}, function (err) {
|
||||
$scope.success = false;
|
||||
$scope.error = err;
|
||||
$scope.busy = false;
|
||||
//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]);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler);
|
||||
|
||||
$scope.$on('$destroy', function () {
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
<div class="umb-dialog umb-pane" ng-controller="Umbraco.Editors.DocumentTypes.CopyController">
|
||||
|
||||
<div class="umb-dialog-body">
|
||||
<div class="umb-pane">
|
||||
|
||||
<p class="abstract" ng-hide="success">
|
||||
<localize key="contentTypeEditor_folderToCopy">Select the folder to copy</localize> <strong>{{currentNode.name}}</strong> <localize key="contentTypeEditor_structureBelow">to in the tree structure below</localize>
|
||||
</p>
|
||||
|
||||
<div class="umb-loader-wrapper" ng-show="busy">
|
||||
<div class="umb-loader"></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> <localize key="contentTypeEditor_copiedUnderneath">was copied underneath</localize> <strong>{{target.name}}</strong></h5>
|
||||
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
||||
</div>
|
||||
|
||||
<div ng-hide="success">
|
||||
|
||||
<div>
|
||||
<umb-tree section="settings"
|
||||
treealias="documentTypes"
|
||||
customtreeparams="foldersonly=1"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar" ng-hide="success">
|
||||
<a class="btn btn-link" ng-click="nav.hideDialog()" ng-if="!busy">
|
||||
<localize key="general_cancel">Cancel</localize>
|
||||
</a>
|
||||
<button class="btn btn-primary" ng-click="copy()" ng-disabled="busy">
|
||||
<localize key="actions_copy">Copy</localize>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,63 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Editors.MediaTypes.CopyController",
|
||||
function ($scope, mediaTypeResource, treeService, navigationService, notificationsService, appState, eventsService) {
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if ($scope.target) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.target.selected = false;
|
||||
}
|
||||
|
||||
$scope.target = args.node;
|
||||
$scope.target.selected = true;
|
||||
}
|
||||
|
||||
$scope.copy = function () {
|
||||
|
||||
$scope.busy = true;
|
||||
$scope.error = false;
|
||||
|
||||
mediaTypeResource.copy({ parentId: $scope.target.id, id: dialogOptions.currentNode.id })
|
||||
.then(function (path) {
|
||||
$scope.error = false;
|
||||
$scope.success = true;
|
||||
$scope.busy = false;
|
||||
|
||||
//get the currently edited node (if any)
|
||||
var activeNode = appState.getTreeState("selectedNode");
|
||||
|
||||
//we need to do a double sync here: first sync to the copied content - but don't activate the node,
|
||||
//then sync to the currenlty edited content (note: this might not be the content that was copied!!)
|
||||
|
||||
navigationService.syncTree({ tree: "mediaTypes", path: path, forceReload: true, activate: false }).then(function (args) {
|
||||
if (activeNode) {
|
||||
var activeNodePath = treeService.getPath(activeNode).join();
|
||||
//sync to this node now - depending on what was copied this might already be synced but might not be
|
||||
navigationService.syncTree({ tree: "mediaTypes", path: activeNodePath, forceReload: false, activate: true });
|
||||
}
|
||||
});
|
||||
|
||||
}, function (err) {
|
||||
$scope.success = false;
|
||||
$scope.error = err;
|
||||
$scope.busy = false;
|
||||
//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]);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler);
|
||||
|
||||
$scope.$on('$destroy', function () {
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
<div class="umb-dialog umb-pane" ng-controller="Umbraco.Editors.MediaTypes.CopyController">
|
||||
|
||||
<div class="umb-dialog-body">
|
||||
<div class="umb-pane">
|
||||
|
||||
<p class="abstract" ng-hide="success">
|
||||
<localize key="contentTypeEditor_folderToCopy">Select the folder to copy</localize> <strong>{{currentNode.name}}</strong> <localize key="contentTypeEditor_structureBelow">to in the tree structure below</localize>
|
||||
</p>
|
||||
|
||||
<div class="umb-loader-wrapper" ng-show="busy">
|
||||
<div class="umb-loader"></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> <localize key="contentTypeEditor_copiedUnderneath">was copied underneath</localize> <strong>{{target.name}}</strong></h5>
|
||||
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
||||
</div>
|
||||
|
||||
<div ng-hide="success">
|
||||
|
||||
<div>
|
||||
<umb-tree section="settings"
|
||||
treealias="mediaTypes"
|
||||
customtreeparams="foldersonly=1"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar" ng-hide="success">
|
||||
<a class="btn btn-link" ng-click="nav.hideDialog()" ng-if="!busy">
|
||||
<localize key="general_cancel">Cancel</localize>
|
||||
</a>
|
||||
<button class="btn btn-primary" ng-click="copy()" ng-disabled="busy">
|
||||
<localize key="actions_copy">Copy</localize>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -4,6 +4,11 @@ function booleanEditorController($scope, $rootScope, assetsService) {
|
||||
$scope.renderModel = {
|
||||
value: false
|
||||
};
|
||||
|
||||
if ($scope.model.config && $scope.model.config.default && $scope.model.config.default.toString() === "1" && $scope.model && !$scope.model.value) {
|
||||
$scope.renderModel.value = true;
|
||||
}
|
||||
|
||||
if ($scope.model && $scope.model.value && ($scope.model.value.toString() === "1" || angular.lowercase($scope.model.value) === "true")) {
|
||||
$scope.renderModel.value = true;
|
||||
}
|
||||
@@ -14,7 +19,7 @@ function booleanEditorController($scope, $rootScope, assetsService) {
|
||||
$scope.$watch("renderModel.value", function (newVal) {
|
||||
$scope.model.value = newVal === true ? "1" : "0";
|
||||
});
|
||||
|
||||
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
@@ -23,4 +28,4 @@ function booleanEditorController($scope, $rootScope, assetsService) {
|
||||
};
|
||||
|
||||
}
|
||||
angular.module("umbraco").controller("Umbraco.PropertyEditors.BooleanController", booleanEditorController);
|
||||
angular.module("umbraco").controller("Umbraco.PropertyEditors.BooleanController", booleanEditorController);
|
||||
|
||||
+5
@@ -5,6 +5,7 @@ angular.module('umbraco')
|
||||
function ($rootScope, $routeParams, $scope, $log, mediaHelper, cropperHelper, $timeout, editorState, umbRequestHelper, fileManager, angularHelper) {
|
||||
|
||||
var config = angular.copy($scope.model.config);
|
||||
$scope.imageIsLoaded = false;
|
||||
|
||||
//move previously saved value to the editor
|
||||
if ($scope.model.value) {
|
||||
@@ -71,6 +72,10 @@ angular.module('umbraco')
|
||||
}
|
||||
};
|
||||
|
||||
$scope.imageLoaded = function() {
|
||||
$scope.imageIsLoaded = true;
|
||||
};
|
||||
|
||||
//on image selected, update the cropper
|
||||
$scope.$on("filesSelected", function (ev, args) {
|
||||
$scope.model.value = config;
|
||||
|
||||
+26
-19
@@ -16,10 +16,10 @@
|
||||
|
||||
<div class="imagecropper clearfix">
|
||||
|
||||
<div ng-if="currentCrop" style="float:left;" class="clearfix">
|
||||
<div style="position: relative; margin-bottom: 10px; width: 492px; border: 1px solid #f8f8f8;">
|
||||
<div ng-if="currentCrop" style="float:left; max-width: 100%;" class="clearfix">
|
||||
<div class="umb-cropper__container">
|
||||
|
||||
<i ng-click="done()" style="opacity: 0.5; position: absolute; top: 3px; right: 3px" class="icon icon-delete btn-round"></i>
|
||||
<i ng-click="done()" class="icon icon-delete btn-round umb-close-cropper"></i>
|
||||
|
||||
<div>
|
||||
<umb-image-crop height="{{currentCrop.height}}"
|
||||
@@ -27,7 +27,8 @@
|
||||
crop="currentCrop.coordinates"
|
||||
center="model.value.focalPoint"
|
||||
max-size="450"
|
||||
src="imageSrc" />
|
||||
src="imageSrc">
|
||||
</umb-image-crop>
|
||||
</div>
|
||||
|
||||
<a href style="margin:auto; text-align: center; font-size: 11px;" class="btn btn-link red"
|
||||
@@ -36,30 +37,36 @@
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="!currentCrop" class="umb-cropper-imageholder clearfix">
|
||||
<umb-image-gravity src="imageSrc"
|
||||
center="model.value.focalPoint" />
|
||||
<umb-image-gravity
|
||||
src="imageSrc"
|
||||
center="model.value.focalPoint"
|
||||
on-image-loaded="imageLoaded">
|
||||
</umb-image-gravity>
|
||||
<a href class="btn btn-link btn-crop-delete" ng-show="imageIsLoaded" ng-click="clear()"><i class="icon-delete red"></i> <localize key="content_uploadClear">Remove file</localize></a>
|
||||
</div>
|
||||
|
||||
<ul class="umb-sortable-thumbnails cropList clearfix" ng-class="{'many':model.value.crops.length >= 4}">
|
||||
<li ng-repeat=" (key,value) in model.value.crops" ng-class="{'current':currentCrop.alias === value.alias}">
|
||||
<a href title="{{value.alias}}: {{value.width}}px x {{value.height}}px" ng-click="crop(value)">
|
||||
<umb-image-thumbnail center="model.value.focalPoint"
|
||||
crop="value.coordinates"
|
||||
src="imageSrc"
|
||||
height="{{value.height}}"
|
||||
width="{{value.width}}"
|
||||
max-size="75"></umb-image-thumbnail>
|
||||
<ul class="umb-sortable-thumbnails cropList clearfix">
|
||||
<li ng-repeat=" (key,value) in model.value.crops" ng-class="{'current':currentCrop.alias === value.alias}" ng-click="crop(value)">
|
||||
|
||||
<umb-image-thumbnail center="model.value.focalPoint"
|
||||
crop="value.coordinates"
|
||||
src="imageSrc"
|
||||
height="{{value.height}}"
|
||||
width="{{value.width}}"
|
||||
max-size="75">
|
||||
</umb-image-thumbnail>
|
||||
|
||||
<div class="crop-information">
|
||||
<span class="crop-name crop-text">{{value.alias}}</span>
|
||||
<span class="crop-size crop-text">{{value.width}}px x {{value.height}}px</span>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
<a href class="btn btn-link btn-crop-delete" ng-click="clear()"><i class="icon-delete red"></i> <localize key="content_uploadClear">Remove file</localize></a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+60
-3
@@ -1,4 +1,4 @@
|
||||
function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper) {
|
||||
function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService) {
|
||||
|
||||
//this is a quick check to see if we're in create mode, if so just exit - we cannot show children for content
|
||||
// that isn't created yet, if we continue this will use the parent id in the route params which isn't what
|
||||
@@ -58,8 +58,66 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie
|
||||
totalPages: 0,
|
||||
items: []
|
||||
};
|
||||
|
||||
//when this is null, we don't check permissions
|
||||
$scope.buttonPermissions = null;
|
||||
|
||||
//When we are dealing with 'content', we need to deal with permissions on child nodes.
|
||||
// Currently there is no real good way to
|
||||
if ($scope.entityType === "content") {
|
||||
|
||||
var idsWithPermissions = null;
|
||||
|
||||
$scope.buttonPermissions = {
|
||||
canCopy: true,
|
||||
canCreate: true,
|
||||
canDelete: true,
|
||||
canMove: true,
|
||||
canPublish: true,
|
||||
canUnpublish: true
|
||||
};
|
||||
|
||||
$scope.$watch(function() {
|
||||
return $scope.selection.length;
|
||||
}, function(newVal, oldVal) {
|
||||
|
||||
if ((idsWithPermissions == null && newVal > 0) || (idsWithPermissions != null)) {
|
||||
|
||||
//get all of the selected ids
|
||||
var ids = _.map($scope.selection, function(i) {
|
||||
return i.id.toString();
|
||||
});
|
||||
|
||||
//remove the dictionary items that don't have matching ids
|
||||
var filtered = {};
|
||||
_.each(idsWithPermissions, function (value, key, list) {
|
||||
if (_.contains(ids, key)) {
|
||||
filtered[key] = value;
|
||||
}
|
||||
});
|
||||
idsWithPermissions = filtered;
|
||||
|
||||
//find all ids that we haven't looked up permissions for
|
||||
var existingIds = _.keys(idsWithPermissions);
|
||||
var missingLookup = _.map(_.difference(ids, existingIds), function (i) {
|
||||
return Number(i);
|
||||
});
|
||||
|
||||
if (missingLookup.length > 0) {
|
||||
contentResource.getPermissions(missingLookup).then(function(p) {
|
||||
$scope.buttonPermissions = listViewHelper.getButtonPermissions(p, idsWithPermissions);
|
||||
});
|
||||
}
|
||||
else {
|
||||
$scope.buttonPermissions = listViewHelper.getButtonPermissions({}, idsWithPermissions);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
$scope.options = {
|
||||
displayAtTabNumber: $scope.model.config.displayAtTabNumber ? $scope.model.config.displayAtTabNumber : 1,
|
||||
pageSize: $scope.model.config.pageSize ? $scope.model.config.pageSize : 10,
|
||||
pageNumber: ($routeParams.page && Number($routeParams.page) != NaN && Number($routeParams.page) > 0) ? $routeParams.page : 1,
|
||||
filter: '',
|
||||
@@ -165,9 +223,8 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie
|
||||
getListResultsCallback(id, $scope.options).then(function(data) {
|
||||
|
||||
$scope.actionInProgress = false;
|
||||
|
||||
$scope.listViewResultSet = data;
|
||||
|
||||
|
||||
//update all values for display
|
||||
if ($scope.listViewResultSet.items) {
|
||||
_.each($scope.listViewResultSet.items, function(e, index) {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<umb-editor-sub-header-content-left>
|
||||
|
||||
<umb-editor-sub-header-section ng-if="listViewAllowedTypes && listViewAllowedTypes.length > 0 && !isAnythingSelected()">
|
||||
<umb-editor-sub-header-section ng-if="(listViewAllowedTypes && listViewAllowedTypes.length > 0 && !isAnythingSelected()) && currentNodePermissions.canCreate">
|
||||
<div class="btn-group">
|
||||
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<localize key="actions_create">Create</localize>
|
||||
@@ -82,7 +82,7 @@
|
||||
<umb-editor-sub-header-section ng-if="isAnythingSelected()">
|
||||
|
||||
<umb-button
|
||||
ng-if="options.allowBulkPublish"
|
||||
ng-if="options.allowBulkPublish && (buttonPermissions == null || buttonPermissions.canPublish)"
|
||||
type="button"
|
||||
button-style="link"
|
||||
label="Publish"
|
||||
@@ -93,7 +93,7 @@
|
||||
</umb-button>
|
||||
|
||||
<umb-button
|
||||
ng-if="options.allowBulkUnpublish"
|
||||
ng-if="options.allowBulkUnpublish && (buttonPermissions == null || buttonPermissions.canUnpublish)"
|
||||
type="button"
|
||||
button-style="link"
|
||||
label="Unpublish"
|
||||
@@ -104,7 +104,7 @@
|
||||
</umb-button>
|
||||
|
||||
<umb-button
|
||||
ng-if="options.allowBulkCopy"
|
||||
ng-if="options.allowBulkCopy && (buttonPermissions == null || buttonPermissions.canCopy)"
|
||||
type="button"
|
||||
button-style="link"
|
||||
label="Copy"
|
||||
@@ -115,7 +115,7 @@
|
||||
</umb-button>
|
||||
|
||||
<umb-button
|
||||
ng-if="options.allowBulkMove"
|
||||
ng-if="options.allowBulkMove && (buttonPermissions == null || buttonPermissions.canMove)"
|
||||
type="button"
|
||||
button-style="link"
|
||||
label="Move"
|
||||
@@ -126,7 +126,7 @@
|
||||
</umb-button>
|
||||
|
||||
<umb-button
|
||||
ng-if="options.allowBulkDelete"
|
||||
ng-if="options.allowBulkDelete && (buttonPermissions == null || buttonPermissions.canDelete)"
|
||||
type="button"
|
||||
button-style="link"
|
||||
label="Delete"
|
||||
|
||||
@@ -261,7 +261,7 @@ angular.module("umbraco")
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
|
||||
//Create the embedded plugin
|
||||
tinyMceService.createInsertEmbeddedMedia(editor, $scope, function() {
|
||||
|
||||
|
||||
+50
-3
@@ -1,5 +1,5 @@
|
||||
angular.module("umbraco").controller("Umbraco.PrevalueEditors.RteController",
|
||||
function ($scope, $timeout, $log, tinyMceService, stylesheetResource) {
|
||||
function ($scope, $timeout, $log, tinyMceService, stylesheetResource, assetsService) {
|
||||
var cfg = tinyMceService.defaultPrevalues();
|
||||
|
||||
if($scope.model.value){
|
||||
@@ -23,6 +23,14 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.RteController",
|
||||
tinyMceService.configuration().then(function(config){
|
||||
$scope.tinyMceConfig = config;
|
||||
|
||||
// extend commands with properties for font-icon and if it is a custom command
|
||||
$scope.tinyMceConfig.commands = _.map($scope.tinyMceConfig.commands, function (obj) {
|
||||
var icon = getFontIcon(obj.frontEndCommand);
|
||||
return angular.extend(obj, {
|
||||
fontIcon: icon.name,
|
||||
isCustom: icon.isCustom
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
stylesheetResource.getAll().then(function(stylesheets){
|
||||
@@ -57,6 +65,43 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.RteController",
|
||||
$scope.model.value.stylesheets.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
// map properties for specific commands
|
||||
function getFontIcon(alias) {
|
||||
var icon = { name: alias, isCustom: false };
|
||||
|
||||
switch (alias) {
|
||||
case "codemirror":
|
||||
icon.name = "code";
|
||||
icon.isCustom = false;
|
||||
break;
|
||||
case "styleselect":
|
||||
icon.name = "icon-list";
|
||||
icon.isCustom = true;
|
||||
break;
|
||||
case "umbembeddialog":
|
||||
icon.name = "icon-tv";
|
||||
icon.isCustom = true;
|
||||
break;
|
||||
case "umbmediapicker":
|
||||
icon.name = "icon-picture";
|
||||
icon.isCustom = true;
|
||||
break;
|
||||
case "umbmacro":
|
||||
icon.name = "icon-settings-alt";
|
||||
icon.isCustom = true;
|
||||
break;
|
||||
case "umbmacro":
|
||||
icon.name = "icon-settings-alt";
|
||||
icon.isCustom = true;
|
||||
break;
|
||||
default:
|
||||
icon.name = alias;
|
||||
icon.isCustom = false;
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
|
||||
|
||||
@@ -65,9 +110,11 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.RteController",
|
||||
|
||||
});
|
||||
|
||||
//when the scope is destroyed we need to unsubscribe
|
||||
// when the scope is destroyed we need to unsubscribe
|
||||
$scope.$on('$destroy', function () {
|
||||
unsubscribe();
|
||||
});
|
||||
|
||||
});
|
||||
// load TinyMCE skin which contains css for font-icons
|
||||
assetsService.loadCss("lib/tinymce/skins/umbraco/skin.min.css");
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
<div ng-controller="Umbraco.PrevalueEditors.RteController">
|
||||
<div ng-controller="Umbraco.PrevalueEditors.RteController" class="rte-editor-preval">
|
||||
|
||||
<umb-control-group label="Toolbar" hide-label="false">
|
||||
<div ng-repeat="cmd in tinyMceConfig.commands">
|
||||
@@ -8,9 +8,10 @@
|
||||
ng-model="cmd.selected"
|
||||
ng-change="selectCommand(cmd)" />
|
||||
|
||||
<img ng-src="{{cmd.icon}}" />
|
||||
<!--<img ng-src="{{cmd.icon}}" />-->
|
||||
<i class="mce-ico" ng-class="(cmd.isCustom ? ' mce-i-custom ' : ' mce-i-') + cmd.fontIcon"></i>
|
||||
|
||||
{{cmd.frontEndCommand}}
|
||||
{{cmd.name}}
|
||||
</label>
|
||||
</div>
|
||||
</umb-control-group>
|
||||
@@ -27,12 +28,12 @@
|
||||
</div>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="Dimensions" description="Width x Height">
|
||||
<umb-control-group label="Dimensions" description="Width x Height">
|
||||
<div class="vertical-align-items">
|
||||
<input type="number" min="0" ng-model="model.value.dimensions.width" class="umb-editor-tiny" placeholder="Width" /> ×
|
||||
<input type="number" min="0" ng-model="model.value.dimensions.width" class="umb-editor-tiny" placeholder="Width" /> ×
|
||||
<input type="number" min="0" ng-model="model.value.dimensions.height" class="umb-editor-tiny" placeholder="Height" /> Pixels
|
||||
</div>
|
||||
</umb-control-group>
|
||||
</div>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="Maximum size for inserted images" description="0 to disable resizing">
|
||||
<div class="vertical-align-items">
|
||||
|
||||
@@ -5,7 +5,8 @@ var app = angular.module('umbraco', [
|
||||
'umbraco.services',
|
||||
'umbraco.mocks',
|
||||
'umbraco.security',
|
||||
'ngCookies'
|
||||
'ngCookies',
|
||||
'LocalStorageModule'
|
||||
]);
|
||||
|
||||
/* For Angular 1.2: we need to load in Routing separately
|
||||
|
||||
@@ -26,7 +26,7 @@ module.exports = function(karma) {
|
||||
'lib/../build/belle/lib/underscore/underscore-min.js',
|
||||
'lib/umbraco/Extensions.js',
|
||||
'lib/../build/belle/lib/rgrove-lazyload/lazyload.js',
|
||||
|
||||
'lib/../build/belle/lib/angular-local-storage/angular-local-storage.min.js',
|
||||
|
||||
'test/config/app.unit.js',
|
||||
'src/common/mocks/umbraco.servervariables.js',
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
describe('list view helper tests', function () {
|
||||
var $scope, listViewHelper;
|
||||
|
||||
beforeEach(module('LocalStorageModule'));
|
||||
beforeEach(module('umbraco.services'));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
$scope = $injector.get('$rootScope');
|
||||
listViewHelper = $injector.get('listViewHelper');
|
||||
}));
|
||||
|
||||
describe('getButtonPermissions', function () {
|
||||
|
||||
it('should update the currentIdsWithPermissions dictionary', function () {
|
||||
|
||||
var currentIdsWithPermissions = {};
|
||||
var result = listViewHelper.getButtonPermissions({ "1234": ["A", "B", "C"] }, currentIdsWithPermissions);
|
||||
|
||||
expect(_.has(currentIdsWithPermissions, "1234")).toBe(true);
|
||||
expect(_.keys(currentIdsWithPermissions).length).toEqual(1);
|
||||
|
||||
});
|
||||
|
||||
it('returns button permissions', function () {
|
||||
|
||||
var currentIdsWithPermissions = {};
|
||||
var result1 = listViewHelper.getButtonPermissions({ "1234": ["O", "C", "D", "M", "U"] }, currentIdsWithPermissions);
|
||||
|
||||
expect(result1["canCopy"]).toBe(true);
|
||||
expect(result1["canCreate"]).toBe(true);
|
||||
expect(result1["canDelete"]).toBe(true);
|
||||
expect(result1["canMove"]).toBe(true);
|
||||
expect(result1["canPublish"]).toBe(true);
|
||||
expect(result1["canUnpublish"]).toBe(true);
|
||||
|
||||
var result2 = listViewHelper.getButtonPermissions({ "1234": ["A", "B"] }, currentIdsWithPermissions);
|
||||
|
||||
expect(result2["canCopy"]).toBe(false);
|
||||
expect(result2["canCreate"]).toBe(false);
|
||||
expect(result2["canDelete"]).toBe(false);
|
||||
expect(result2["canMove"]).toBe(false);
|
||||
expect(result2["canPublish"]).toBe(false);
|
||||
expect(result2["canUnpublish"]).toBe(false);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@@ -7,9 +7,18 @@
|
||||
'Failed to generate.')
|
||||
.then(function (result) {
|
||||
$scope.generating = false;
|
||||
$scope.dashboard = result;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.reload = function () {
|
||||
$scope.ready = false;
|
||||
modelsBuilderResource.getDashboard().then(function (result) {
|
||||
$scope.dashboard = result;
|
||||
$scope.ready = true;
|
||||
});
|
||||
};
|
||||
|
||||
function init() {
|
||||
modelsBuilderResource.getDashboard().then(function(result) {
|
||||
$scope.dashboard = result;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<div id="modelsBuilder" ng-controller="Umbraco.Dashboard.ModelsBuilderController">
|
||||
|
||||
<div ng-show="ready" style="float: right;">
|
||||
<button type="button" class="btn" ng-click="reload()"><span>Reload</span></button>
|
||||
</div>
|
||||
|
||||
<h3>Models Builder</h3>
|
||||
|
||||
<div ng-show="!ready">
|
||||
@@ -10,7 +14,8 @@
|
||||
<div ng-bind-html-unsafe="dashboard.text"></div>
|
||||
|
||||
<div ng-if="dashboard.outOfDateModels">
|
||||
<p>Models are <strong>out-of-date</strong>.</p>
|
||||
<p>Models are <strong>out-of-date</strong>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div ng-if="dashboard.canGenerate">
|
||||
@@ -26,6 +31,11 @@
|
||||
<div class="umb-loader"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="dashboard.lastError" style="margin-top: 32px;" ng-show="!generating">
|
||||
<span style="color: red; font-weight: bold;">Last generation failed with the following error:</span>
|
||||
<pre style="width: 80%; white-space: pre-line; background: #f8f8f8; padding: 4px; font-size: small;">{{dashboard.lastError}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -348,8 +348,8 @@
|
||||
<Name>umbraco.providers</Name>
|
||||
</ProjectReference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.0.90, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.0\lib\Umbraco.ModelsBuilder.dll</HintPath>
|
||||
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.1.92, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.1\lib\Umbraco.ModelsBuilder.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="UrlRewritingNet.UrlRewriter, Version=2.0.7.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
@@ -2014,14 +2014,9 @@
|
||||
<Content Include="Umbraco\Translation\default.aspx" />
|
||||
<Content Include="Umbraco\Translation\preview.aspx" />
|
||||
<Content Include="Umbraco\Translation\xml.aspx" />
|
||||
<Content Include="Umbraco\Create\content.ascx" />
|
||||
<Content Include="Umbraco\Create\language.ascx">
|
||||
<SubType>UserControl</SubType>
|
||||
</Content>
|
||||
<Content Include="Umbraco\Create\member.ascx" />
|
||||
<Content Include="Umbraco\Create\nodeType.ascx">
|
||||
<SubType>UserControl</SubType>
|
||||
</Content>
|
||||
<Content Include="Umbraco\Create\simple.ascx" />
|
||||
<Content Include="Umbraco\Create\xslt.ascx">
|
||||
<SubType>UserControl</SubType>
|
||||
|
||||
@@ -2,221 +2,246 @@
|
||||
<!-- Any changes to this file requires the application (umbraco) to restart -->
|
||||
<!-- This can be done by touching the web.config or recycling the application pool -->
|
||||
<tinymceConfig>
|
||||
<commands>
|
||||
<command>
|
||||
<umbracoAlias>code</umbracoAlias>
|
||||
<icon>images/editor/code.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="code">code</tinyMceCommand>
|
||||
<priority>1</priority>
|
||||
</command>
|
||||
<command>
|
||||
<commands>
|
||||
<command>
|
||||
<umbracoAlias>code</umbracoAlias>
|
||||
<name>Code</name>
|
||||
<icon>images/editor/code.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="code">code</tinyMceCommand>
|
||||
<priority>1</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>codemirror</umbracoAlias>
|
||||
<name>Code mirror</name>
|
||||
<icon>images/editor/code.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="codemirror">codemirror</tinyMceCommand>
|
||||
<priority>1</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>removeformat</umbracoAlias>
|
||||
<icon>images/editor/removeformat.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="removeformat">removeformat</tinyMceCommand>
|
||||
<priority>2</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>Undo</umbracoAlias>
|
||||
<icon>images/editor/undo.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="undo">undo</tinyMceCommand>
|
||||
<priority>11</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Redo</umbracoAlias>
|
||||
<icon>images/editor/redo.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="redo">redo</tinyMceCommand>
|
||||
<priority>12</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Cut</umbracoAlias>
|
||||
<icon>images/editor/cut.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="cut">cut</tinyMceCommand>
|
||||
<priority>13</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Copy</umbracoAlias>
|
||||
<icon>images/editor/copy.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="copy">copy</tinyMceCommand>
|
||||
<priority>14</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>styleselect</umbracoAlias>
|
||||
<icon>images/editor/showStyles.png</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="styleselect">styleselect</tinyMceCommand>
|
||||
<priority>20</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>bold</umbracoAlias>
|
||||
<icon>images/editor/bold.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="bold">bold</tinyMceCommand>
|
||||
<priority>21</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>italic</umbracoAlias>
|
||||
<icon>images/editor/italic.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="italic">italic</tinyMceCommand>
|
||||
<priority>22</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Underline</umbracoAlias>
|
||||
<icon>images/editor/underline.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="underline">underline</tinyMceCommand>
|
||||
<priority>23</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Strikethrough</umbracoAlias>
|
||||
<icon>images/editor/strikethrough.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="strikethrough">strikethrough</tinyMceCommand>
|
||||
<priority>24</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>JustifyLeft</umbracoAlias>
|
||||
<icon>images/editor/justifyleft.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="alignleft">justifyleft</tinyMceCommand>
|
||||
<priority>31</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>JustifyCenter</umbracoAlias>
|
||||
<icon>images/editor/justifycenter.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="aligncenter">justifycenter</tinyMceCommand>
|
||||
<priority>32</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>JustifyRight</umbracoAlias>
|
||||
<icon>images/editor/justifyright.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="alignright">justifyright</tinyMceCommand>
|
||||
<priority>33</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>JustifyFull</umbracoAlias>
|
||||
<icon>images/editor/justifyfull.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="alignjustify">alignjustify</tinyMceCommand>
|
||||
<priority>34</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>bullist</umbracoAlias>
|
||||
<icon>images/editor/bullist.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="bullist">bullist</tinyMceCommand>
|
||||
<priority>41</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>numlist</umbracoAlias>
|
||||
<icon>images/editor/numlist.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="numlist">numlist</tinyMceCommand>
|
||||
<priority>42</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Outdent</umbracoAlias>
|
||||
<icon>images/editor/outdent.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="outdent">outdent</tinyMceCommand>
|
||||
<priority>43</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Indent</umbracoAlias>
|
||||
<icon>images/editor/indent.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="indent">indent</tinyMceCommand>
|
||||
<priority>44</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>mceLink</umbracoAlias>
|
||||
<icon>images/editor/link.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="link">link</tinyMceCommand>
|
||||
<priority>51</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>unlink</umbracoAlias>
|
||||
<icon>images/editor/unLink.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="unlink">unlink</tinyMceCommand>
|
||||
<priority>52</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>mceInsertAnchor</umbracoAlias>
|
||||
<icon>images/editor/anchor.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="anchor">anchor</tinyMceCommand>
|
||||
<priority>53</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>mceImage</umbracoAlias>
|
||||
<icon>images/editor/image.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="umbmediapicker">image</tinyMceCommand>
|
||||
<priority>61</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>umbracomacro</umbracoAlias>
|
||||
<icon>images/editor/insMacro.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="umbmacro">umbracomacro</tinyMceCommand>
|
||||
<priority>62</priority>
|
||||
</command>
|
||||
|
||||
|
||||
|
||||
<command>
|
||||
<umbracoAlias>mceInsertTable</umbracoAlias>
|
||||
<icon>images/editor/table.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="table">table</tinyMceCommand>
|
||||
<priority>63</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>umbracoembed</umbracoAlias>
|
||||
<icon>images/editor/media.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="umbembeddialog">umbracoembed</tinyMceCommand>
|
||||
<priority>66</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>inserthorizontalrule</umbracoAlias>
|
||||
<icon>images/editor/hr.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="hr">hr</tinyMceCommand>
|
||||
<priority>71</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>subscript</umbracoAlias>
|
||||
<icon>images/editor/sub.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="subscript">subscript</tinyMceCommand>
|
||||
<priority>72</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>superscript</umbracoAlias>
|
||||
<icon>images/editor/sup.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="superscript">superscript</tinyMceCommand>
|
||||
<priority>73</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>mceCharMap</umbracoAlias>
|
||||
<icon>images/editor/charmap.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="charmap">charmap</tinyMceCommand>
|
||||
<priority>74</priority>
|
||||
</command>
|
||||
|
||||
</commands>
|
||||
<plugins>
|
||||
<umbracoAlias>removeformat</umbracoAlias>
|
||||
<name>Remove format</name>
|
||||
<icon>images/editor/removeformat.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="removeformat">removeformat</tinyMceCommand>
|
||||
<priority>2</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>undo</umbracoAlias>
|
||||
<name>Undo</name>
|
||||
<name>Remove Format</name>
|
||||
<icon>images/editor/undo.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="undo">undo</tinyMceCommand>
|
||||
<priority>11</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>redo</umbracoAlias>
|
||||
<name>Redo</name>
|
||||
<icon>images/editor/redo.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="redo">redo</tinyMceCommand>
|
||||
<priority>12</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>cut</umbracoAlias>
|
||||
<name>Cut</name>
|
||||
<icon>images/editor/cut.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="cut">cut</tinyMceCommand>
|
||||
<priority>13</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>copy</umbracoAlias>
|
||||
<name>Copy</name>
|
||||
<icon>images/editor/copy.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="copy">copy</tinyMceCommand>
|
||||
<priority>14</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>paste</umbracoAlias>
|
||||
<name>Paste</name>
|
||||
<icon>images/editor/paste.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="paste">paste</tinyMceCommand>
|
||||
<priority>15</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>styleselect</umbracoAlias>
|
||||
<name>Style select</name>
|
||||
<icon>images/editor/showStyles.png</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="styleselect">styleselect</tinyMceCommand>
|
||||
<priority>20</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>bold</umbracoAlias>
|
||||
<name>Bold</name>
|
||||
<icon>images/editor/bold.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="bold">bold</tinyMceCommand>
|
||||
<priority>21</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>italic</umbracoAlias>
|
||||
<name>Italic</name>
|
||||
<icon>images/editor/italic.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="italic">italic</tinyMceCommand>
|
||||
<priority>22</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>underline</umbracoAlias>
|
||||
<name>Underline</name>
|
||||
<icon>images/editor/underline.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="underline">underline</tinyMceCommand>
|
||||
<priority>23</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>strikethrough</umbracoAlias>
|
||||
<name>Strikethrough</name>
|
||||
<icon>images/editor/strikethrough.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="strikethrough">strikethrough</tinyMceCommand>
|
||||
<priority>24</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>justifyleft</umbracoAlias>
|
||||
<name>Justify left</name>
|
||||
<icon>images/editor/justifyleft.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="alignleft">justifyleft</tinyMceCommand>
|
||||
<priority>31</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>justifycenter</umbracoAlias>
|
||||
<name>Justify center</name>
|
||||
<icon>images/editor/justifycenter.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="aligncenter">justifycenter</tinyMceCommand>
|
||||
<priority>32</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>justifyright</umbracoAlias>
|
||||
<name>Justify right</name>
|
||||
<icon>images/editor/justifyright.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="alignright">justifyright</tinyMceCommand>
|
||||
<priority>33</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>justifyfull</umbracoAlias>
|
||||
<name>Justify full</name>
|
||||
<icon>images/editor/justifyfull.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="alignjustify">alignjustify</tinyMceCommand>
|
||||
<priority>34</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>bullist</umbracoAlias>
|
||||
<name>Bullet list</name>
|
||||
<icon>images/editor/bullist.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="bullist">bullist</tinyMceCommand>
|
||||
<priority>41</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>numlist</umbracoAlias>
|
||||
<name>Numbered list</name>
|
||||
<icon>images/editor/numlist.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="numlist">numlist</tinyMceCommand>
|
||||
<priority>42</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>outdent</umbracoAlias>
|
||||
<name>Decrease indent</name>
|
||||
<icon>images/editor/outdent.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="outdent">outdent</tinyMceCommand>
|
||||
<priority>43</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>indent</umbracoAlias>
|
||||
<name>Increase indent</name>
|
||||
<icon>images/editor/indent.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="indent">indent</tinyMceCommand>
|
||||
<priority>44</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>mceLink</umbracoAlias>
|
||||
<name>Insert/edit link</name>
|
||||
<icon>images/editor/link.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="link">link</tinyMceCommand>
|
||||
<priority>51</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>unlink</umbracoAlias>
|
||||
<name>Remove link</name>
|
||||
<icon>images/editor/unLink.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="unlink">unlink</tinyMceCommand>
|
||||
<priority>52</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>mceInsertAnchor</umbracoAlias>
|
||||
<name>Anchor</name>
|
||||
<icon>images/editor/anchor.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="anchor">anchor</tinyMceCommand>
|
||||
<priority>53</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>mceImage</umbracoAlias>
|
||||
<name>Image</name>
|
||||
<icon>images/editor/image.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="umbmediapicker">image</tinyMceCommand>
|
||||
<priority>61</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>umbracomacro</umbracoAlias>
|
||||
<name>Macro</name>
|
||||
<icon>images/editor/insMacro.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="umbmacro">umbracomacro</tinyMceCommand>
|
||||
<priority>62</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>mceInsertTable</umbracoAlias>
|
||||
<name>Table</name>
|
||||
<icon>images/editor/table.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="table">table</tinyMceCommand>
|
||||
<priority>63</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>umbracoembed</umbracoAlias>
|
||||
<name>Embed</name>
|
||||
<icon>images/editor/media.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="umbembeddialog">umbracoembed</tinyMceCommand>
|
||||
<priority>66</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>inserthorizontalrule</umbracoAlias>
|
||||
<name>Horizontal rule</name>
|
||||
<icon>images/editor/hr.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="hr">hr</tinyMceCommand>
|
||||
<priority>71</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>subscript</umbracoAlias>
|
||||
<name>Subscript</name>
|
||||
<icon>images/editor/sub.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="subscript">subscript</tinyMceCommand>
|
||||
<priority>72</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>superscript</umbracoAlias>
|
||||
<name>Superscript</name>
|
||||
<icon>images/editor/sup.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="superscript">superscript</tinyMceCommand>
|
||||
<priority>73</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>mceCharMap</umbracoAlias>
|
||||
<name>Character map</name>
|
||||
<icon>images/editor/charmap.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="charmap">charmap</tinyMceCommand>
|
||||
<priority>74</priority>
|
||||
</command>
|
||||
</commands>
|
||||
<plugins>
|
||||
<plugin loadOnFrontend="true">code</plugin>
|
||||
<plugin loadOnFrontend="true">codemirror</plugin>
|
||||
<plugin loadOnFrontend="true">paste</plugin>
|
||||
<plugin loadOnFrontend="true">umbracolink</plugin>
|
||||
<plugin loadOnFrontend="true">anchor</plugin>
|
||||
<plugin loadOnFrontend="true">charmap</plugin>
|
||||
<plugin loadOnFrontend="true">table</plugin>
|
||||
<plugin loadOnFrontend="true">codemirror</plugin>
|
||||
<plugin loadOnFrontend="true">paste</plugin>
|
||||
<plugin loadOnFrontend="true">umbracolink</plugin>
|
||||
<plugin loadOnFrontend="true">anchor</plugin>
|
||||
<plugin loadOnFrontend="true">charmap</plugin>
|
||||
<plugin loadOnFrontend="true">table</plugin>
|
||||
<plugin loadOnFrontend="true">lists</plugin>
|
||||
<plugin loadOnFrontend="true">hr</plugin>
|
||||
</plugins>
|
||||
<validElements>
|
||||
<![CDATA[+a[id|style|rel|data-id|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|
|
||||
<plugin loadOnFrontend="true">hr</plugin>
|
||||
</plugins>
|
||||
<validElements>
|
||||
<![CDATA[+a[id|style|rel|data-id|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|
|
||||
ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],
|
||||
-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],
|
||||
img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel|data-id],
|
||||
@@ -228,24 +253,24 @@ thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|heig
|
||||
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],
|
||||
dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],
|
||||
param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*]]]>
|
||||
</validElements>
|
||||
<invalidElements>font</invalidElements>
|
||||
</validElements>
|
||||
<invalidElements>font</invalidElements>
|
||||
|
||||
<!-- this area is for custom config settings that should be added during TinyMCE initialization -->
|
||||
<customConfig>
|
||||
<!-- <config key="myKey">mySetting</config>-->
|
||||
<config key="entity_encoding">raw</config>
|
||||
<config key="codemirror">
|
||||
{
|
||||
"indentOnInit": false,
|
||||
"path": "../../../../lib/codemirror",
|
||||
"config": {
|
||||
},
|
||||
"jsFiles": [
|
||||
],
|
||||
"cssFiles": [
|
||||
]
|
||||
}
|
||||
</config>
|
||||
</customConfig>
|
||||
<!-- this area is for custom config settings that should be added during TinyMCE initialization -->
|
||||
<customConfig>
|
||||
<!-- <config key="myKey">mySetting</config>-->
|
||||
<config key="entity_encoding">raw</config>
|
||||
<config key="codemirror">
|
||||
{
|
||||
"indentOnInit": false,
|
||||
"path": "../../../../lib/codemirror",
|
||||
"config": {
|
||||
},
|
||||
"jsFiles": [
|
||||
],
|
||||
"cssFiles": [
|
||||
]
|
||||
}
|
||||
</config>
|
||||
</customConfig>
|
||||
</tinymceConfig>
|
||||
@@ -5,204 +5,228 @@
|
||||
<commands>
|
||||
<command>
|
||||
<umbracoAlias>code</umbracoAlias>
|
||||
<name>Code</name>
|
||||
<icon>images/editor/code.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="code">code</tinyMceCommand>
|
||||
<priority>1</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>codemirror</umbracoAlias>
|
||||
<name>Code mirror</name>
|
||||
<icon>images/editor/code.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="codemirror">codemirror</tinyMceCommand>
|
||||
<priority>1</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>removeformat</umbracoAlias>
|
||||
<name>Remove format</name>
|
||||
<icon>images/editor/removeformat.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="removeformat">removeformat</tinyMceCommand>
|
||||
<priority>2</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>Undo</umbracoAlias>
|
||||
<umbracoAlias>undo</umbracoAlias>
|
||||
<name>Undo</name>
|
||||
<icon>images/editor/undo.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="undo">undo</tinyMceCommand>
|
||||
<priority>11</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Redo</umbracoAlias>
|
||||
<umbracoAlias>redo</umbracoAlias>
|
||||
<name>Redo</name>
|
||||
<icon>images/editor/redo.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="redo">redo</tinyMceCommand>
|
||||
<priority>12</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Cut</umbracoAlias>
|
||||
<umbracoAlias>cut</umbracoAlias>
|
||||
<name>Cut</name>
|
||||
<icon>images/editor/cut.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="cut">cut</tinyMceCommand>
|
||||
<priority>13</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Copy</umbracoAlias>
|
||||
<umbracoAlias>copy</umbracoAlias>
|
||||
<name>Copy</name>
|
||||
<icon>images/editor/copy.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="copy">copy</tinyMceCommand>
|
||||
<priority>14</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>paste</umbracoAlias>
|
||||
<name>Paste</name>
|
||||
<icon>images/editor/paste.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="paste">paste</tinyMceCommand>
|
||||
<priority>15</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>styleselect</umbracoAlias>
|
||||
<name>Style select</name>
|
||||
<icon>images/editor/showStyles.png</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="styleselect">styleselect</tinyMceCommand>
|
||||
<priority>20</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>bold</umbracoAlias>
|
||||
<name>Bold</name>
|
||||
<icon>images/editor/bold.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="bold">bold</tinyMceCommand>
|
||||
<priority>21</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>italic</umbracoAlias>
|
||||
<name>Italic</name>
|
||||
<icon>images/editor/italic.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="italic">italic</tinyMceCommand>
|
||||
<priority>22</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Underline</umbracoAlias>
|
||||
<umbracoAlias>underline</umbracoAlias>
|
||||
<name>Underline</name>
|
||||
<icon>images/editor/underline.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="underline">underline</tinyMceCommand>
|
||||
<priority>23</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Strikethrough</umbracoAlias>
|
||||
<umbracoAlias>strikethrough</umbracoAlias>
|
||||
<name>Strikethrough</name>
|
||||
<icon>images/editor/strikethrough.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="strikethrough">strikethrough</tinyMceCommand>
|
||||
<priority>24</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>JustifyLeft</umbracoAlias>
|
||||
<umbracoAlias>justifyleft</umbracoAlias>
|
||||
<name>Justify left</name>
|
||||
<icon>images/editor/justifyleft.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="alignleft">justifyleft</tinyMceCommand>
|
||||
<priority>31</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>JustifyCenter</umbracoAlias>
|
||||
<umbracoAlias>justifycenter</umbracoAlias>
|
||||
<name>Justify center</name>
|
||||
<icon>images/editor/justifycenter.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="aligncenter">justifycenter</tinyMceCommand>
|
||||
<priority>32</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>JustifyRight</umbracoAlias>
|
||||
<umbracoAlias>justifyright</umbracoAlias>
|
||||
<name>Justify right</name>
|
||||
<icon>images/editor/justifyright.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="alignright">justifyright</tinyMceCommand>
|
||||
<priority>33</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>JustifyFull</umbracoAlias>
|
||||
<umbracoAlias>justifyfull</umbracoAlias>
|
||||
<name>Justify full</name>
|
||||
<icon>images/editor/justifyfull.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="alignjustify">alignjustify</tinyMceCommand>
|
||||
<priority>34</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>bullist</umbracoAlias>
|
||||
<name>Bullet list</name>
|
||||
<icon>images/editor/bullist.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="bullist">bullist</tinyMceCommand>
|
||||
<priority>41</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>numlist</umbracoAlias>
|
||||
<name>Numbered list</name>
|
||||
<icon>images/editor/numlist.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="numlist">numlist</tinyMceCommand>
|
||||
<priority>42</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Outdent</umbracoAlias>
|
||||
<umbracoAlias>outdent</umbracoAlias>
|
||||
<name>Decrease indent</name>
|
||||
<icon>images/editor/outdent.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="outdent">outdent</tinyMceCommand>
|
||||
<priority>43</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>Indent</umbracoAlias>
|
||||
<umbracoAlias>indent</umbracoAlias>
|
||||
<name>Increase indent</name>
|
||||
<icon>images/editor/indent.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="indent">indent</tinyMceCommand>
|
||||
<priority>44</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>mceLink</umbracoAlias>
|
||||
<name>Insert/edit link</name>
|
||||
<icon>images/editor/link.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="link">link</tinyMceCommand>
|
||||
<priority>51</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>unlink</umbracoAlias>
|
||||
<name>Remove link</name>
|
||||
<icon>images/editor/unLink.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="unlink">unlink</tinyMceCommand>
|
||||
<priority>52</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>mceInsertAnchor</umbracoAlias>
|
||||
<name>Anchor</name>
|
||||
<icon>images/editor/anchor.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="anchor">anchor</tinyMceCommand>
|
||||
<priority>53</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>mceImage</umbracoAlias>
|
||||
<name>Image</name>
|
||||
<icon>images/editor/image.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="umbmediapicker">image</tinyMceCommand>
|
||||
<priority>61</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>umbracomacro</umbracoAlias>
|
||||
<name>Macro</name>
|
||||
<icon>images/editor/insMacro.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="umbmacro">umbracomacro</tinyMceCommand>
|
||||
<priority>62</priority>
|
||||
</command>
|
||||
|
||||
|
||||
|
||||
<command>
|
||||
<umbracoAlias>mceInsertTable</umbracoAlias>
|
||||
<name>Table</name>
|
||||
<icon>images/editor/table.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="table">table</tinyMceCommand>
|
||||
<priority>63</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>umbracoembed</umbracoAlias>
|
||||
<name>Embed</name>
|
||||
<icon>images/editor/media.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="true" frontendCommand="umbembeddialog">umbracoembed</tinyMceCommand>
|
||||
<priority>66</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>inserthorizontalrule</umbracoAlias>
|
||||
<name>Horizontal rule</name>
|
||||
<icon>images/editor/hr.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="hr">hr</tinyMceCommand>
|
||||
<priority>71</priority>
|
||||
</command>
|
||||
<command>
|
||||
<umbracoAlias>subscript</umbracoAlias>
|
||||
<name>Subscript</name>
|
||||
<icon>images/editor/sub.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="subscript">subscript</tinyMceCommand>
|
||||
<priority>72</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>superscript</umbracoAlias>
|
||||
<name>Superscript</name>
|
||||
<icon>images/editor/sup.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="superscript">superscript</tinyMceCommand>
|
||||
<priority>73</priority>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<umbracoAlias>mceCharMap</umbracoAlias>
|
||||
<name>Character map</name>
|
||||
<icon>images/editor/charmap.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="charmap">charmap</tinyMceCommand>
|
||||
<priority>74</priority>
|
||||
</command>
|
||||
|
||||
</commands>
|
||||
<plugins>
|
||||
<plugin loadOnFrontend="true">code</plugin>
|
||||
@@ -247,4 +271,4 @@ param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|cla
|
||||
}
|
||||
</config>
|
||||
</customConfig>
|
||||
</tinymceConfig>
|
||||
</tinymceConfig>
|
||||
@@ -35,6 +35,6 @@
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
|
||||
<package id="System.Reflection.Metadata" version="1.0.21" targetFramework="net45" />
|
||||
<package id="Umbraco.ModelsBuilder" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Umbraco.ModelsBuilder" version="3.0.1" targetFramework="net45" />
|
||||
<package id="UrlRewritingNet.UrlRewriter" version="2.0.7" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -265,6 +265,7 @@
|
||||
<key alias="selectContent">Select content</key>
|
||||
<key alias="selectMember">Select member</key>
|
||||
<key alias="selectMemberGroup">Select member group</key>
|
||||
<key alias="noIconsFound">No icons were found</key>
|
||||
|
||||
<key alias="noMacroParams">There are no parameters for this macro</key>
|
||||
|
||||
@@ -1054,7 +1055,9 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="yesDelete">Yes, delete</key>
|
||||
|
||||
<key alias="movedUnderneath">was moved underneath</key>
|
||||
<key alias="copiedUnderneath">was copied underneath</key>
|
||||
<key alias="folderToMove">Select the folder to move</key>
|
||||
<key alias="folderToCopy">Select the folder to copy</key>
|
||||
<key alias="structureBelow">to in the tree structure below</key>
|
||||
|
||||
<key alias="allDocumentTypes">All Document types</key>
|
||||
|
||||
@@ -1051,7 +1051,9 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="yesDelete">Yes, delete</key>
|
||||
|
||||
<key alias="movedUnderneath">was moved underneath</key>
|
||||
<key alias="copiedUnderneath">was copied underneath</key>
|
||||
<key alias="folderToMove">Select the folder to move</key>
|
||||
<key alias="folderToCopy">Select the folder to copy</key>
|
||||
<key alias="structureBelow">to in the tree structure below</key>
|
||||
|
||||
<key alias="allDocumentTypes">All Document types</key>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<%@ Control Language="c#" AutoEventWireup="True" Codebehind="content.ascx.cs" Inherits="umbraco.cms.presentation.create.controls.content" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
|
||||
<asp:literal id="typeJs" runat="server"/>
|
||||
|
||||
<div><%=umbraco.ui.Text("name")%>:<br /></div>
|
||||
<asp:TextBox id="rename" Runat="server" CssClass="bigInput"></asp:TextBox><br /><br />
|
||||
<asp:RequiredFieldValidator id="RequiredFieldValidator1" ErrorMessage="*" ControlToValidate="rename" runat="server">*</asp:RequiredFieldValidator>
|
||||
|
||||
<span style="margin-left: -7px;"><%=umbraco.ui.Text("choose")%> <%=umbraco.ui.Text("documentType")%>:<br /></span>
|
||||
<asp:ListBox id="nodeType" Runat="server" cssClass="bigInput" Rows="1" SelectionMode="Single"></asp:ListBox>
|
||||
<asp:RequiredFieldValidator id="RequiredFieldValidator2" ErrorMessage="*" ControlToValidate="nodeType" runat="server">*</asp:RequiredFieldValidator>
|
||||
|
||||
<br />
|
||||
<!-- added to support missing postback on enter in IE -->
|
||||
<asp:TextBox runat="server" style="visibility:hidden;display:none;" ID="Textbox1"/>
|
||||
<div id="typeDescription" class="createDescription">
|
||||
<asp:Literal ID="descr" runat="server"></asp:Literal>
|
||||
</div>
|
||||
|
||||
<div style="margin-right: 15px;">
|
||||
<asp:Button id="sbmt" Runat="server" style="Width: 90px; margin-right: 6px;" onclick="sbmt_Click"></asp:Button>
|
||||
<em> <%= umbraco.ui.Text("or") %> </em>
|
||||
<a href="#" style="color: Blue; margin-left: 6px;" onclick="UmbClientMgr.closeModalWindow()"><%=umbraco.ui.Text("cancel")%></a>
|
||||
|
||||
<!--
|
||||
<input type="button" value="" onClick="if (confirm('<%=umbraco.ui.Text("areyousure")%>')) window.close()" style="width: 90px; margin-left: 6px;"/>
|
||||
-->
|
||||
</div>
|
||||
@@ -1,48 +0,0 @@
|
||||
<%@ Control Language="c#" AutoEventWireup="True" CodeBehind="member.ascx.cs" Inherits="umbraco.cms.presentation.create.controls.member"
|
||||
TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
|
||||
<asp:ValidationSummary runat="server" DisplayMode="BulletList" ID="validationSummary"
|
||||
CssClass="error"></asp:ValidationSummary>
|
||||
<asp:Literal ID="nameLiteral" runat="server"></asp:Literal>:<asp:RequiredFieldValidator
|
||||
ID="nameRequired" ErrorMessage="*" ControlToValidate="rename" runat="server">*</asp:RequiredFieldValidator>
|
||||
<br />
|
||||
<asp:TextBox ID="rename" runat="server" Width="350px" CssClass="bigInput"></asp:TextBox>
|
||||
<asp:Panel ID="memberChooser" runat="server">
|
||||
<%=umbraco.ui.Text("choose")%>
|
||||
<%=umbraco.ui.Text("membertype")%>:<asp:RequiredFieldValidator ID="memberTypeRequired" ErrorMessage="*" ControlToValidate="nodeType"
|
||||
runat="server">*</asp:RequiredFieldValidator><br />
|
||||
<asp:ListBox ID="nodeType" runat="server" Width="350px" CssClass="bigInput" Rows="1"
|
||||
SelectionMode="Single"></asp:ListBox>
|
||||
</asp:Panel>
|
||||
<p>
|
||||
Login Name:<asp:RequiredFieldValidator ID="loginRequired" ErrorMessage="*" ControlToValidate="Login"
|
||||
runat="server">*</asp:RequiredFieldValidator>
|
||||
<asp:CustomValidator ID="loginExistsCheck" runat="server" ErrorMessage="*" ControlToValidate="Login" ValidateEmptyText="false" OnServerValidate="LoginExistsCheck"></asp:CustomValidator>
|
||||
<br />
|
||||
<asp:TextBox ID="Login" runat="server" Width="350px" CssClass="bigInput"></asp:TextBox><br />
|
||||
</p>
|
||||
<p>
|
||||
E-mail:
|
||||
<asp:RequiredFieldValidator ID="emailRequired" ErrorMessage="*" ControlToValidate="Email"
|
||||
runat="server">*</asp:RequiredFieldValidator>
|
||||
<asp:CustomValidator ID="emailExistsCheck" runat="server" ErrorMessage="*" ControlToValidate="Email" ValidateEmptyText="false" OnServerValidate="EmailExistsCheck"></asp:CustomValidator>
|
||||
<asp:CustomValidator runat="server" ID="EmailValidator" OnServerValidate="EmailValidator_OnServerValidate"
|
||||
ControlToValidate="Email"
|
||||
ErrorMessage="Invalid email address"
|
||||
Display="None"/>
|
||||
<br />
|
||||
<asp:TextBox ID="Email" runat="server" Width="350px" CssClass="bigInput"></asp:TextBox><br />
|
||||
</p>
|
||||
<p>
|
||||
Password: <em>
|
||||
<asp:Literal runat="server" ID="PasswordRules"></asp:Literal></em><asp:RequiredFieldValidator
|
||||
ID="passwordRequired" ControlToValidate="Password" runat="server">*</asp:RequiredFieldValidator><br />
|
||||
<asp:TextBox ID="Password" runat="server" Width="350px" CssClass="bigInput"></asp:TextBox><br />
|
||||
</p>
|
||||
<!-- added to support missing postback on enter in IE -->
|
||||
<asp:TextBox runat="server" Style="visibility: hidden; display: none;" ID="Textbox1" />
|
||||
<div style="padding-top: 15px;">
|
||||
<asp:Button ID="sbmt" runat="server" Style="margin-top: 14px" Width="90" OnClick="sbmt_Click">
|
||||
</asp:Button>
|
||||
<em>
|
||||
<%= umbraco.ui.Text("or") %></em> <a href="#" style="color: blue" onclick="UmbClientMgr.closeModalWindow()"><%=umbraco.ui.Text("cancel")%></a>
|
||||
</div>
|
||||
@@ -1,32 +0,0 @@
|
||||
<%@ Control Language="c#" AutoEventWireup="True" Codebehind="nodeType.ascx.cs" Inherits="umbraco.cms.presentation.create.controls.nodeType" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
|
||||
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
|
||||
<cc1:Pane runat="server">
|
||||
|
||||
|
||||
<cc1:PropertyPanel runat="server" id="pp_name" text="Name">
|
||||
<asp:TextBox id="rename" Runat="server" CssClass="bigInput input-large-type input-block-level"></asp:TextBox>
|
||||
<asp:RequiredFieldValidator id="RequiredFieldValidator1" ErrorMessage="*" ControlToValidate="rename" runat="server">*</asp:RequiredFieldValidator>
|
||||
</cc1:PropertyPanel>
|
||||
|
||||
<cc1:PropertyPanel runat="server" text="Master Document Type" ID="pp_MasterDocumentType">
|
||||
<asp:ListBox id="masterType" Runat="server" cssClass="bigInput input-large-type input-block-level" Rows="1" SelectionMode="Single"></asp:ListBox>
|
||||
<asp:Literal ID="masterTypePreDefined" runat="server" Visible="false"></asp:Literal>
|
||||
</cc1:PropertyPanel>
|
||||
|
||||
<cc1:PropertyPanel runat="server">
|
||||
<asp:CheckBox ID="createTemplate" Runat="server" Checked="true" Text="Create matching template"></asp:CheckBox>
|
||||
</cc1:PropertyPanel>
|
||||
|
||||
|
||||
<asp:TextBox runat="server" style="visibility:hidden;display:none;" ID="Textbox1"/>
|
||||
|
||||
|
||||
<asp:CustomValidator ID="CustomValidation1" ErrorMessage="* A document type with this name/alias already exists" OnServerValidate="validationDoctypeName" ControlToValidate="rename" ForeColor="red" runat="server" />
|
||||
<asp:CustomValidator ID="CustomValidation2" ErrorMessage="<br/>* The name of the document type will result in an invalid alias" OnServerValidate="validationDoctypeAlias" ControlToValidate="rename" ForeColor="red" runat="server" />
|
||||
</cc1:Pane>
|
||||
|
||||
<cc1:Pane runat="server" CssClass="btn-toolbar umb-btn-toolbar">
|
||||
<a href="#" class="btn btn-link" onclick="UmbClientMgr.closeModalWindow()"><%=umbraco.ui.Text("cancel")%></a>
|
||||
<asp:Button id="sbmt" Runat="server" CssClass="btn btn-primary" onclick="sbmt_Click"></asp:Button>
|
||||
</cc1:Pane>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user