Compare commits

..

80 Commits

Author SHA1 Message Date
Mads Rasmussen 1dacbbdbf6 added dots to website/language selector 2016-03-16 11:09:06 +01:00
Mads Rasmussen f0b374c30b filter out selected item 2016-03-16 10:43:09 +01:00
Mads Rasmussen ec5feee1f3 WIP prototyping website/language selector 2016-03-16 09:26:34 +01:00
Simon Busborg 1d1d99ddad added variationsHelper service and toggler for content 2016-03-15 14:47:03 +01:00
Claus c306f94a6a Merge pull request #1154 from pynej/fix-stylesheet-tree-sync
Fix for issue causing the entire stylesheets tree to reload when …
2016-03-15 12:46:59 +01:00
Claus 11b2ec89fd Merge pull request #1167 from umbraco/temp-U4-8154
U4-8154 - bugfix Sql query expressions parsing
2016-03-15 12:36:52 +01:00
Claus 89596f00f1 Merge pull request #1151 from arknu/icon-transparency
Fix transparency for image icons in the tray
2016-03-15 09:54:36 +01:00
Claus 4fa6e70e72 Merge pull request #1140 from jamescoxhead/U4-7746
U4-7746 - use flat icon in partial views tree
2016-03-15 09:22:18 +01:00
Warren Buckley a5a0a84d46 Merge pull request #1163 from umbraco/temp-U4-7767
U4-7767 List View Filter needs debounce - many requests to handler me…
2016-03-14 16:12:19 +00:00
Warren Buckley 839431e6fa Merge pull request #1170 from umbraco/temp-U4-8157
U4-8157 Right-click on root node returns console error when it doesn'…
2016-03-14 14:28:39 +00:00
Stephan 5369a6fc56 Upgrade ModelsBuilder to 3.0.1 2016-03-14 13:37:49 +01:00
Claus 8a078e258f U4-8157 Right-click on root node returns console error when it doesn't has any actions
Ensured we don't use throw to stop the program flow if no menuUrl is defined on the node. It is a likely scenario that some root node don't have right click actions so its better to handle this.
2016-03-14 12:15:15 +01:00
Sebastiaan Janssen fb42574c34 Revert "U4-5334 Richtext editor inserts extra p - tags to html output" - apparently it does just as much harm as it does good
This reverts commit 9ad3b6a337.
2016-03-12 21:02:05 +01:00
Sebastiaan Janssen 9ad3b6a337 U4-5334 Richtext editor inserts extra p - tags to html output
#U4-5334 Fixed
2016-03-12 12:58:53 +01:00
Stephan 65b16fbfe5 U4-8154 - bugfix Sql query expressions parsing 2016-03-11 14:18:08 +01:00
Stephan 6ad2853bce Merge pull request #1165 from umbraco/temp-U4-7949
U4-7949 The task runner has completed YSOD when using the Umbraco Pac…
2016-03-10 18:29:08 +01:00
Sebastiaan Janssen b2407eab98 Merge pull request #1107 from bjarnef/dev-v7-tinymce-font-icons
Change icons for richtext editor config
2016-03-10 17:47:46 +01:00
Shannon 778c7a836b Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-03-10 15:52:43 +01:00
Shannon 11f9cdead0 U4-6366 Issue assigning member roles on MemberService.Saved event 2016-03-10 15:52:34 +01:00
Sebastiaan Janssen a1076d5443 Merge pull request #1160 from umbraco/temp-U4-6438
U4-6438 - fix dynamic extension methods when type loading goes bad
2016-03-10 15:49:15 +01:00
Shannon 4a11bf68f3 U4-7949 The task runner has completed YSOD when using the Umbraco Package installer 2016-03-10 15:23:52 +01:00
Sebastiaan Janssen fa64e73a43 Merge pull request #1164 from umbraco/temp-U4-5797
U4-5797 - fix PublishedContentType cache refresh for compositions
2016-03-10 14:04:46 +01:00
Stephan adf3e2dfe0 U4-5797 - fix PublishedContentType cache refresh for compositions 2016-03-10 13:59:50 +01:00
Shannon c4c86cf5ce U4-7767 List View Filter needs debounce - many requests to handler method 2016-03-10 13:02:20 +01:00
Sebastiaan Janssen 479aba8e1d Fixes unit test.. in the correct branch this time 2016-03-10 11:47:51 +01:00
Shannon 0c474e2aba U4-7670 True/false fields on Macro Picker don't save their setting nor read existing setting. - another null check required. 2016-03-10 10:06:20 +01:00
Shannon Deminick 4f5b34cdfe Merge pull request #1162 from pynej/codemirror-js-error
Fix for missing doc.setLine() function breaking code mirror editor.
2016-03-10 09:58:16 +01:00
Warren Buckley 0cb7f220ea Merge pull request #1149 from umbraco/temp-U4-4700
U4-4700 List View Doesn't Respect User Permissions
2016-03-10 08:52:38 +00:00
Jeremy Pyne 0995b2cb5a Fix for missing doc.setLine() function breaking code mirror editor. 2016-03-09 14:55:15 -05:00
Stephan 1b37475144 U4-6438 - fix dynamic extension methods when type loading goes bad 2016-03-09 15:55:41 +01:00
Shannon be0bacd895 Ensures all angular views are cache busted so browser cache is not an issue after upgrading. 2016-03-08 17:23:54 +01:00
Shannon a2564bd0c3 ensures that requests are only made for ids that haven't already been queried. 2016-03-08 16:18:33 +01:00
Shannon 402a5c9d56 fixes bool check 2016-03-08 15:57:59 +01:00
Shannon 2a2f22c7d9 fixes js null issue with boolean.controller 2016-03-08 15:53:45 +01:00
Shannon 372a768dca U4-4700 List view doesn't respect user permissions - makes the buttons show/hide based on the selected items instead of the current item. 2016-03-08 15:53:22 +01:00
Sebastiaan Janssen f6e48243a6 U4-8088 NuGet upgrade of UmbracoCms pacakage doesn't add ModelsBuilder keys to web.config 2016-03-08 13:39:35 +01:00
Warren Buckley 94ea677ec0 Merge pull request #1146 from umbraco/temp-U4-7641
U4-7641 - enable content type copy
2016-03-08 09:38:16 +00:00
Sebastiaan Janssen 55e7159f7d Forgot to remove them from the nuspec files 2016-03-08 10:35:57 +01:00
Sebastiaan Janssen 390a94e323 U4-8054 Issue with NuGet Uninstall.ps1 (running on updates)
#U4-8054 Fixed
2016-03-08 10:34:19 +01:00
Shannon Deminick 19fb920aa1 Merge pull request #1150 from umbraco/temp-U4-7823
U4-7823 - stop flooding the log with errors getting media 0
2016-03-07 17:58:49 +01:00
Shannon Deminick f35e1604ca Merge pull request #1141 from umbraco/temp-U4-8030
U4-8030 - Fix RenderModelBinder issue with surface
2016-03-07 17:53:31 +01:00
Shannon b9765c3bec fixes RenderModelBinder to use base implementation,adds unit tests 2016-03-07 17:52:28 +01:00
Shannon d5a57c505c adds RenderModelBinderTests 2016-03-07 16:53:57 +01:00
Shannon 5f365241a8 updates RenderModelBinder to simply check for IPublishedContent or IRenderModel 2016-03-07 16:29:40 +01:00
Shannon 9c121f0044 Fixes RenderModelBinder to inherit from DefaultModelBinder and use the default logic if the model in the route values is not IRenderModel 2016-03-07 16:26:30 +01:00
Shannon f13bc07ddc Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2016-03-07 15:13:41 +01:00
Shannon a707d23692 Allows for specifying explicit product names by overriding the property in MigrationStartupHander 2016-03-07 15:13:31 +01:00
Simon Busborg 0929b7d42c Fixes U4-8113 Styling for property labels affect package meta data labels 2016-03-07 14:55:18 +01:00
Simon Busborg 35a9272b68 Fixes U4-8036 Umbraco.MultiNodeTreePicker checkbox doesn't appear after selecting something from list view 2016-03-07 14:45:30 +01:00
Shannon Deminick 112453a032 Merge pull request #1144 from umbraco/temp-U4-8077
U4-8077 - ensure product name in migration event handlers
2016-03-07 14:09:29 +01:00
Simon Busborg bba7367ba6 Fixes U4-8058 Labels are changed to block-level elements 2016-03-07 12:12:35 +01:00
Jeremy Pyne 83e679ba5e Fix for issue causing the entire stylesheets tree to reload when selecting a item. 2016-03-02 16:00:33 -05:00
Asbjørn Riis-Knudsen 4d950fb4d4 Fix transparency for image icons in the tray 2016-02-28 17:40:58 +01:00
Stephan 0d191fb8bd U4-7823 - stop flooding the log with errors getting media 0 2016-02-26 11:35:24 +01:00
Warren Buckley c7a3efadb1 Remove debug JSON in the view 2016-02-25 21:09:12 +00:00
Warren Buckley 956425dfbf Now updated so the create button hides if we do not have the Create permission 'C' 2016-02-25 21:06:25 +00:00
Warren Buckley c616354522 After reading src code for contentEditorHelper.configureContentEditorButtons it makes the same assumption that if the publish action 'U' is present then the user can also unpublish aka 'Z' 2016-02-25 20:49:56 +00:00
Stephan 36246b96d4 Fix bug with permissions cache refresh 2016-02-25 17:39:34 +01:00
Stephan 7d8791ec86 Fix ActionButtonsResolver (need review) 2016-02-25 17:05:44 +01:00
Stephan f349a9ae3e U4-7641 - bugfix 2016-02-25 16:26:20 +01:00
Warren Buckley 2719e2c231 WIP - ListView that grabs the current nodes permission from the editorState & use a neater object to return to the view rather than the lovely Magic String CHARs. Need help understanding that I don't get all the permissions to be expected 2016-02-25 15:19:42 +00:00
Stephan dafde545b0 U4-7641 - bugfix + implement for media types 2016-02-25 16:02:04 +01:00
Stephan 610538261e U4-7641 - enable content type copy 2016-02-25 15:26:03 +01:00
Stephan 9f7b82e20f U4-8077 - ensure product name in migration event handlers 2016-02-24 13:59:15 +01:00
Stephan 04b3532e9d U4-8030 - Fix RenderModelBinder issue with surface 2016-02-22 18:38:06 +01:00
James Coxhead 01bcd3b623 Changed partial views icon to icon-article 2016-02-22 16:15:31 +00:00
James Coxhead 64fd95bd22 Updated tree icons for partial views and partial view macros 2016-02-22 16:13:25 +00:00
bjarnef 5176b68935 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7-tinymce-font-icons 2016-02-08 15:07:36 +01:00
bjarnef 0bfc5f1272 Change icons in tinymce config 2016-02-08 15:07:16 +01:00
bjarnef 39c18d4201 Merge branch 'dev-v7' of https://github.com/bjarnef/Umbraco-CMS into dev-v7 2016-02-05 15:54:48 +01:00
bjarnef 66ea8ae604 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-02-05 14:55:53 +01:00
bjarnef 6fc794ca2e Merge branch 'dev-v7' of https://github.com/bjarnef/Umbraco-CMS into dev-v7 2016-02-03 14:42:14 +01:00
bjarnef df958223b0 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-26 18:17:00 +01:00
bjarnef 1217d9f0b3 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-24 23:25:29 +01:00
bjarnef 1301897f39 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-22 22:02:51 +01:00
bjarnef 6d34fe416d Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-21 20:38:52 +01:00
bjarnef a884ece8b1 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-21 18:15:50 +01:00
bjarnef 0ffcc9b889 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-20 19:21:58 +01:00
bjarnef ee3131b63d Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-19 21:03:42 +01:00
bjarnef 4fd7182388 Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7 2016-01-19 20:56:36 +01:00
166 changed files with 3343 additions and 4496 deletions
-1
View File
@@ -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" />
-1
View File
@@ -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">
-48
View File
@@ -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 }
}
-39
View File
@@ -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);
}
}
+63 -24
View File
@@ -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 -1
View File
@@ -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);
}
}
+25
View File
@@ -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;
}
}
}
@@ -114,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);
}
}
@@ -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);
}
}
+59 -28
View File
@@ -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()
{
+2 -2
View File
@@ -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]
+2
View File
@@ -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" />
@@ -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)
{
}
}
}
}
+7 -7
View File
@@ -1,5 +1,5 @@
{
"env": {
"env": {
"browser": true
},
@@ -8,7 +8,7 @@
],
"rules": {
"eqeqeq": 2,
"eqeqeq": 2,
"curly": 2,
"no-unused-vars": 1,
@@ -18,8 +18,8 @@
"dot-notation": 1,
"no-use-before-define": 0,
"angular/ng_controller_as": 1,
"angular/ng_controller_as_vm": 1,
"angular/ng_controller_as": 1,
"angular/ng_controller_as_vm": 1,
"strict": 0,
@@ -32,8 +32,8 @@
"comma-spacing": 0,
"no-trailing-spaces": 0,
"eol-last": 0,
"no-underscore-dangle": 0,
"camelcase": 0
"no-underscore-dangle": 0,
"camelcase": 0
},
"globals": {
@@ -50,4 +50,4 @@
"Bloodhound", false
}
}
}
@@ -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:
+1 -1
View File
@@ -37,7 +37,7 @@
"grunt-ngdocs": "~0.1.2",
"grunt-open": "~0.2.0",
"grunt-postcss": "~0.6.0",
"grunt-recess": "~1.0.1",
"grunt-recess": "~0.3",
"karma": "~0.9",
"karma-chrome-launcher": "0.0.2",
"karma-coffee-preprocessor": "0.0.1",
+27 -7
View File
@@ -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
@@ -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
}
@@ -3,93 +3,11 @@
* @name umbraco.directives.directive:umbNavigation
* @restrict E
**/
function umbNavigationDirective(appState, $location) {
function umbNavigationDirective() {
return {
restrict: "E", // restrict to an element
replace: true, // replace the html element with the template
templateUrl: 'views/components/application/umb-navigation.html',
link: function (scope, element, attr, ctrl) {
scope.showTreeNavigation = appState.getGlobalState("showNavigation");
scope.searchClick = function() {
scope.searchOverlay = {
view: "search",
show: true,
submit: function(model) {
$location.path(model.selectedItem.editorPath);
scope.searchOverlay.show = false;
scope.searchOverlay = null;
},
close: function(oldModel) {
scope.searchOverlay.show = false;
scope.searchOverlay = null;
}
};
};
scope.avatarClick = function(){
if(scope.helpDialog) {
closeHelpDialog();
}
if(!scope.userDialog) {
scope.userDialog = {
view: "user",
show: true,
close: function(oldModel) {
closeUserDialog();
}
};
} else {
closeUserDialog();
}
};
function closeUserDialog() {
scope.userDialog.show = false;
scope.userDialog = null;
}
scope.helpClick = function(){
if(scope.userDialog) {
closeUserDialog();
}
if(!scope.helpDialog) {
scope.helpDialog = {
view: "help",
show: true,
close: function(oldModel) {
closeHelpDialog();
}
};
} else {
closeHelpDialog();
}
};
function closeHelpDialog() {
scope.helpDialog.show = false;
scope.helpDialog = null;
}
scope.showTree = function () {
scope.showTreeNavigation = appState.getGlobalState("showNavigation");
if(scope.showTreeNavigation === true) {
appState.setGlobalState("showNavigation", false);
} else {
appState.setGlobalState("showNavigation", true);
}
};
}
templateUrl: 'views/components/application/umb-navigation.html'
};
}
@@ -11,7 +11,7 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se
link: function (scope, element, attr, ctrl) {
//setup scope vars
scope.maxSections = 5;
scope.maxSections = 7;
scope.overflowingSections = 0;
scope.sections = [];
scope.currentSection = appState.getSectionState("currentSection");
@@ -34,25 +34,16 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se
sectionResource.getSections()
.then(function (result) {
scope.sections = result;
// hide overflowing sections
scope.totalSections = scope.sections.length;
if(scope.totalSections > scope.maxSections){
scope.needTray = true;
scope.overflowingSections = scope.maxSections - scope.totalSections;
}
// calculateHeight();
calculateHeight();
});
}
function calculateHeight(){
$timeout(function(){
//total height minus room for avatar and help icon
var height = $(window).width();
var height = $(window).height()-200;
scope.totalSections = scope.sections.length;
scope.maxSections = Math.floor(width / 70);
scope.maxSections = Math.floor(height / 70);
scope.needTray = false;
if(scope.totalSections > scope.maxSections){
@@ -93,7 +84,57 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se
});
//on page resize
// window.onresize = calculateHeight;
window.onresize = calculateHeight;
scope.avatarClick = function(){
if(scope.helpDialog) {
closeHelpDialog();
}
if(!scope.userDialog) {
scope.userDialog = {
view: "user",
show: true,
close: function(oldModel) {
closeUserDialog();
}
};
} else {
closeUserDialog();
}
};
function closeUserDialog() {
scope.userDialog.show = false;
scope.userDialog = null;
}
scope.helpClick = function(){
if(scope.userDialog) {
closeUserDialog();
}
if(!scope.helpDialog) {
scope.helpDialog = {
view: "help",
show: true,
close: function(oldModel) {
closeHelpDialog();
}
};
} else {
closeHelpDialog();
}
};
function closeHelpDialog() {
scope.helpDialog.show = false;
scope.helpDialog = null;
}
scope.sectionClick = function (event, section) {
@@ -1,30 +0,0 @@
(function() {
'use strict';
function TreeNavigation(appState) {
function link(scope, el, attr, ctrl) {
scope.showTreeNavigation = false;
scope.currentSection = appState.getSectionState("currentSection");
scope.$watch(function(){
return appState.getGlobalState("showNavigation");
}, function (newValue) {
scope.showTreeNavigation = newValue;
});
}
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/application/umb-tree-navigation.html',
link: link
};
return directive;
}
angular.module('umbraco.directives').directive('umbTreeNavigation', TreeNavigation);
})();
@@ -1,18 +0,0 @@
(function() {
'use strict';
function EditorSubView() {
var directive = {
transclude: true,
restrict: 'E',
replace: true,
templateUrl: 'views/components/editor/subview/umb-editor-sub-view.html'
};
return directive;
}
angular.module('umbraco.directives').directive('umbEditorSubView', EditorSubView);
})();
@@ -1,18 +0,0 @@
(function() {
'use strict';
function EditorSubViewContainer() {
var directive = {
transclude: true,
restrict: 'E',
replace: true,
templateUrl: 'views/components/editor/subview/umb-editor-sub-view-container.html'
};
return directive;
}
angular.module('umbraco.directives').directive('umbEditorSubViewContainer', EditorSubViewContainer);
})();
@@ -1,18 +0,0 @@
(function() {
'use strict';
function EditorSubViewContent() {
var directive = {
transclude: true,
restrict: 'E',
replace: true,
templateUrl: 'views/components/editor/subview/umb-editor-sub-view-content.html'
};
return directive;
}
angular.module('umbraco.directives').directive('umbEditorSubViewContent', EditorSubViewContent);
})();
@@ -1,18 +0,0 @@
(function() {
'use strict';
function EditorSubViewHeader() {
var directive = {
transclude: true,
restrict: 'E',
replace: true,
templateUrl: 'views/components/editor/subview/umb-editor-sub-view-header.html'
};
return directive;
}
angular.module('umbraco.directives').directive('umbEditorSubViewHeader', EditorSubViewHeader);
})();
@@ -1,18 +0,0 @@
(function() {
'use strict';
function EditorSubViewSidebar() {
var directive = {
transclude: true,
restrict: 'E',
replace: true,
templateUrl: 'views/components/editor/subview/umb-editor-sub-view-sidebar.html'
};
return directive;
}
angular.module('umbraco.directives').directive('umbEditorSubViewSidebar', EditorSubViewSidebar);
})();
@@ -5,20 +5,8 @@
function link(scope, el, attr, ctrl) {
scope.showVariationsQuickSwitchToggle = false;
scope.showVariationsQuickSwitch = false;
function activate() {
showVariationsQuickSwitch(scope.variations);
}
function showVariationsQuickSwitch(variations) {
if(variations && variations.length > 1 || variations && variations.length === 1 && variations[0].variations && variations[0].variations.length > 0) {
scope.showVariationsQuickSwitchToggle = true;
} else {
scope.showVariationsQuickSwitchToggle = false;
}
}
scope.variations = variationsHelper.getVariations();
scope.openIconPicker = function() {
scope.dialogModel = {
@@ -43,58 +31,6 @@
scope.toggleVariationsQuickSwitch = function() {
scope.showVariationsQuickSwitch = !scope.showVariationsQuickSwitch;
};
scope.hideVariationsQuickSwitch = function() {
scope.showVariationsQuickSwitch = false;
};
scope.toggleSubItems = function(item, $event) {
item.showSubItems = !item.showSubItems;
$event.preventDefault();
$event.stopPropagation();
};
scope.selectItem = function(item) {
if(scope.onSelectItem) {
for(var i = 0; i < scope.variations.length; i++) {
var language = scope.variations[i];
language.active = false;
if(language.variations && language.variations.length > 0) {
for(var variationIndex = 0; variationIndex < language.variations.length; variationIndex++) {
var variation = language.variations[variationIndex];
variation.active = false;
}
}
}
// set selected item to active
item.active = true;
scope.onSelectItem(item);
scope.showVariationsQuickSwitch = false;
}
};
scope.openInSplitView = function(item, $event) {
if(scope.onOpenInSplitView) {
scope.onOpenInSplitView(item);
scope.showVariationsQuickSwitch = false;
$event.preventDefault();
$event.stopPropagation();
}
};
scope.$watch('variations', function(newValue, oldValue){
showVariationsQuickSwitch(newValue);
}, true);
activate();
}
var directive = {
@@ -108,11 +44,6 @@
actions: "=",
name: "=",
nameLocked: "=",
variation: "=",
language: "=",
variations: "=",
onSelectItem: "=",
onOpenInSplitView: "=",
menu: "=",
icon: "=",
hideIcon: "@",
@@ -6,21 +6,10 @@
function link(scope, el, attr, ctrl) {
scope.showNavigation = true;
scope.showDropdown = false;
scope.maxNavigationItems = 5;
scope.overflowingNavigationsItems = 0;
scope.needDropdown = false;
scope.clickNavigationItem = function(selectedItem) {
setItemToActive(selectedItem);
runItemAction(selectedItem);
if(scope.showDropdown) {
scope.closeDropdown();
}
};
function runItemAction(selectedItem) {
@@ -51,29 +40,8 @@
scope.showNavigation = false;
}
hideOverflowingNavigationItems();
}
function hideOverflowingNavigationItems() {
scope.totalNavigationItems = scope.navigation.length;
if(scope.totalNavigationItems > scope.maxNavigationItems){
scope.needDropdown = true;
scope.overflowingNavigationsItems = scope.maxNavigationItems - scope.totalNavigationItems;
}
}
scope.toggleDropdown = function() {
scope.showDropdown = !scope.showDropdown;
};
scope.closeDropdown = function() {
scope.showDropdown = false;
};
activate();
}
@@ -3,6 +3,32 @@
function EditorSubViewsDirective() {
function link(scope, el, attr, ctrl) {
scope.activeView = {};
// set toolbar from selected navigation item
function setActiveView(items) {
for (var index = 0; index < items.length; index++) {
var item = items[index];
if (item.active && item.view) {
scope.activeView = item;
}
}
}
// watch for navigation changes
scope.$watch('subViews', function(newValue, oldValue) {
if (newValue) {
setActiveView(newValue);
}
}, true);
}
var directive = {
restrict: 'E',
replace: true,
@@ -10,7 +36,8 @@
scope: {
subViews: "=",
model: "="
}
},
link: link
};
return directive;
@@ -1,19 +0,0 @@
(function() {
'use strict';
function EditorToolbar() {
var directive = {
restrict: 'E',
replace: true,
transclude: true,
templateUrl: 'views/components/editor/umb-editor-toolbar.html'
};
return directive;
}
angular.module('umbraco.directives').directive('umbEditorToolbar', EditorToolbar);
})();
@@ -11,88 +11,22 @@ angular.module("umbraco.directives")
},
transclude: true,
restrict: 'E',
replace: true,
replace: true,
templateUrl: 'views/components/property/umb-property.html',
link: function(scope) {
scope.propertyAlias = Umbraco.Sys.ServerVariables.isDebuggingEnabled === true ? scope.property.alias : null;
scope.showDropdown = false;
scope.selectedVariation = {};
scope.variations = [
{
name: "Danish",
master: true,
selected: true
},
{
name: "German"
},
{
name: "Spanish"
},
{
name: "Finnish"
},
{
name: "Albanian"
},
{
name: "Russian"
},
{
name: "Norwegian"
},
{
name: "Swedish"
}
];
function activate() {
for(var i = 0; i < scope.variations.length; i++ ) {
var variation = scope.variations[i];
if(variation.selected) {
scope.property.variation = variation;
}
}
}
scope.toggleDropdown = function() {
scope.showDropdown = !scope.showDropdown;
};
scope.closeDropdown = function() {
scope.showDropdown = false;
};
scope.editContent = function() {
scope.property.variation = null;
scope.showDropdown = false;
};
scope.syncContent = function(selectedVariation) {
for(var i = 0; i < scope.variations.length; i++ ) {
var variation = scope.variations[i];
variation.selected = false;
}
selectedVariation.selected = true;
scope.property.variation = selectedVariation;
scope.showDropdown = false;
};
activate();
},
//Define a controller for this directive to expose APIs to other directives
controller: function ($scope, $timeout) {
var self = this;
//set the API properties/methods
self.property = $scope.property;
self.setPropertyError = function(errorMsg) {
$scope.property.propertyErrorMessage = errorMsg;
};
}
};
});
});
@@ -1,7 +1,7 @@
/**
* @ngdoc directive
* @function
* @name umbraco.directives.directive:umbPropertyEditor
* @name umbraco.directives.directive:umbPropertyEditor
* @requires formController
* @restrict E
**/
@@ -14,10 +14,10 @@ var _umbPropertyEditor = function (umbPropEditorHelper) {
isPreValue: "@",
preview: "@"
},
require: "^form",
restrict: 'E',
replace: true,
replace: true,
templateUrl: 'views/components/property/umb-property-editor.html',
link: function (scope, element, attrs, ctrl) {
@@ -33,7 +33,6 @@ var _umbPropertyEditor = function (umbPropEditorHelper) {
scope.$watch("model.view", function(val){
scope.propertyEditorView = umbPropEditorHelper.getViewPath(scope.model.view, scope.isPreValue);
});
}
};
};
@@ -13,7 +13,7 @@
el.find("a:first").tab('show');
//enable the tab drop
//el.tabdrop();
el.tabdrop();
});
@@ -29,7 +29,7 @@
scope.$on('$destroy', function () {
//ensure to destroy tabdrop (unbinds window resize listeners)
//el.tabdrop("destroy");
el.tabdrop("destroy");
unbindModelWatch();
@@ -1,112 +0,0 @@
(function() {
'use strict';
function Variations(iconHelper) {
function link(scope, el, attr, ctrl) {
scope.newVariation = {};
scope.segments = [
{
name: "Mobile",
id: 1
},
{
name: "Tablet",
id: 2
},
{
name: "Email Subscriber",
id: 3
},
{
name: "Email Campagin March 2016",
id: 4
},
{
name: "Codegarden Attendees",
id: 5
},
{
name: "Codegarden Attendees from abroad",
id: 6
}
];
scope.variationsSortableOptions = {
distance: 10,
tolerance: "pointer",
opacity: 0.7,
scroll: true,
cursor: "move",
zIndex: 6000
};
scope.showNewVariation = function(language) {
language.showNewVariation = true;
};
scope.hideNewVariation = function(language) {
language.showNewVariation = false;
};
scope.toggleEditVariation = function(selectedVariation) {
selectedVariation.editVariation = !selectedVariation.editVariation;
};
scope.createNewVariation = function(newVariation, language) {
var variation = angular.copy(language);
variation.variationName = newVariation.name;
variation.variationDescription = newVariation.description;
variation.segments = newVariation.segments;
variation.active = false;
language.variations.unshift(variation);
language.showNewVariation = false;
scope.newVariation = {
name: "",
description: "",
segments: []
};
};
scope.saveVariation = function(variation, language) {
variation.editVariation = false;
};
scope.deleteVariation = function(variation, language) {
var index = language.variations.indexOf(variation);
language.variations.splice(index, 1);
};
scope.hideEditVariation = function(variation) {
variation.editVariation = false;
};
}
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/umb-variations.html',
scope: {
variations: "=",
onClickVariation: "=",
onSaveVariation: "=",
onCloneVariation: "=",
onDeleteVariation: "="
},
link: link
};
return directive;
}
angular.module('umbraco.directives').directive('umbVariations', Variations);
})();
@@ -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 */
@@ -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);
/**
@@ -5,97 +5,7 @@
var variations = [];
/*
var variations = [
{
language: "Danish",
master: true,
published: true,
variations: [
{
name: "Mobile",
description: "Danish content for mobile",
published: true,
segments: [
{
name: "Mobile"
}
]
}
]
},
{
language: "Dutch",
published: true,
variations: [
{
name: "Mobile",
description: "Dutch content for mobile",
segments: [
{
name: "Mobile"
}
]
}
]
},
{
language: "English (United States)",
published: true,
variations: [
{
name: "Mobile",
description: "English content for mobile",
published: true,
segments: [
{
name: "Mobile"
}
]
},
{
name: "Job campaign: Front-end developer",
description: "Landing page for job thing 1",
published: true,
segments: [
{
name: "Front-end developer"
}
]
},
{
name: "Job campaign: Back-end developer",
description: "Landing page for job thing 2",
published: true,
segments: [
{
name: "Back-end developer"
}
]
}
]
},
{
language: "German",
published: true
},
{
language: "Italian",
published: true
},
{
language: "Spanish",
published: false
},
{
language: "Swedish",
published: false
}
];
*/
function setMaster(master) {
variations = [];
master.master = true;
variations.push(master);
}
@@ -129,6 +39,7 @@
variationClone.master = false;
variationClone.published = false;
variations.push(variationClone);
console.log(variations);
}
function deleteVariation(variation, event, index) {
@@ -8,7 +8,7 @@
* The main application controller
*
*/
function MainController($scope, $rootScope, $location, $routeParams, $timeout, $http, $log, appState, treeService, notificationsService, userService, navigationService, historyService, updateChecker, assetsService, eventsService, umbRequestHelper, tmhDynamicLocale, $templateCache) {
function MainController($scope, $rootScope, $location, $routeParams, $timeout, $http, $log, appState, treeService, notificationsService, userService, navigationService, historyService, updateChecker, assetsService, eventsService, umbRequestHelper, tmhDynamicLocale) {
//the null is important because we do an explicit bool check on this in the view
//the avatar is by default the umbraco logo
@@ -19,7 +19,7 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $
{ value: "assets/img/application/logo@3x.png" }
];
$scope.touchDevice = appState.getGlobalState("touchDevice");
$scope.splitView = {};
$scope.removeNotification = function (index) {
notificationsService.remove(index);
@@ -126,28 +126,6 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $
};
}));
evts.push(eventsService.on("splitView.open", function(name, view) {
var updateTime = Date.now();
$scope.splitView = {
id: view.id,
view: view.view + "?updated=" + updateTime,
show: true
};
}));
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
$scope.closeSplitView();
});
$scope.closeSplitView = function() {
$scope.splitView.show = false;
$scope.splitView.id = null;
$scope.splitView.view = null;
};
//ensure to unregister from all events!
$scope.$on('$destroy', function () {
for (var e in evts) {
@@ -163,4 +141,4 @@ angular.module('umbraco').controller("Umbraco.MainController", MainController).
config(function (tmhDynamicLocaleProvider) {
//Set url for locale files
tmhDynamicLocaleProvider.localeLocationPattern('lib/angular/1.1.5/i18n/angular-locale_{{locale}}.js');
});
});
@@ -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) {
@@ -41,10 +41,14 @@ body {
}
#contentwrapper, #contentcolumn {
// position: absolute;
// top: 0px; bottom: 0px; right: 0px; left: 80px;
// z-index: 10;
// margin: 0
position: absolute;
top: 0px; bottom: 0px; right: 0px; left: 80px;
z-index: 10;
margin: 0
}
#umb-notifications-wrapper {
left: 80px;
}
#contentcolumn {
@@ -59,6 +63,24 @@ body {
border: none;
}
#leftcolumn {
height: 100%;
z-index: 20;
width: 80px;
float: left;
position: absolute;
}
#applications {
z-index: 1000;
height: 100%;
left: 0px;
top: 0;
bottom: 0;
position: absolute;
text-align: center
}
#applications-tray {
z-index: 900;
left: 80px;
@@ -69,7 +91,6 @@ body {
text-align: center;
}
/*
#search-form {
display: block;
margin: 0;
@@ -81,37 +102,21 @@ body {
overflow: hidden;
.form-search {
display: -ms-flexbox;
display: -webkit-box;
display: -webkit-flex;
display: flex;
margin-top: 17px;
.umb-search-field {
width: auto;
min-width: 160px;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
border-left: none;
border-right: none;
border-top: none;
}
}
}
*/
.form-search {
display: flex;
//margin-top: 17px;
.umb-search-field {
width: auto;
min-width: 160px;
flex: 1;
border-left: none;
border-right: none;
border-top: none;
height: 60px;
box-sizing: border-box;
padding-left: 40px !important;
}
}
#navigation {
left: 80px;
@@ -194,10 +199,10 @@ body {
z-index:9999 !important;
}
// @media (min-width: 1101px) {
// #contentwrapper, #umb-notifications-wrapper {left: 440px;}
// #speechbubble {left: 360px;}
// }
@media (min-width: 1101px) {
#contentwrapper, #umb-notifications-wrapper {left: 440px;}
#speechbubble {left: 360px;}
}
//empty section modification
.emptySection #contentwrapper, .emptySection #umb-notifications-wrapper {left: 80px;}
@@ -1,228 +0,0 @@
.umb-navigation {
display: flex;
flex: 0 0 @navigationBarHeight;
align-items: center;
border-bottom: 1px solid @grayLight;
box-sizing: border-box;
}
.umb-navigation-link {
display: flex;
align-items: center;
padding: 0 20px;
height: 49px;
font-size: 13px;
cursor: pointer;
&:hover {
text-decoration: none;
background: @grayLighter;
}
&:focus {
text-decoration: none;
}
}
.umb-navigation-link.-current {
color: @blue;
}
.umb-navigation-link.open {
background: @grayLighter;
}
.umb-navigation__right {
display: flex;
align-items: center;
margin-left: auto;
}
#avatar-img {
border-radius: 50%;
margin: 0 0 0 10px;
}
.umb-sections__tray {
display: flex;
flex-direction: column;
align-items: flex-start;
position: absolute;
z-index: 1;
width: 220px;
top: @navigationBarHeight;
background: white;
transform: translate(-42px, 0px);
}
.umb-sections__tray .umb-navigation-link {
width: 100%;
box-sizing: border-box;
}
.umb-sections__tray .umb-navigation-link:hover {
background: #ececec;
}
.umb-navigation-more {
width: 22px;
height: auto;
}
.umb-navigation-more__path {
fill: @black;
}
// Tree Doors Downu
#mainwrapper {
display: flex;
flex-direction: column;
}
#contentwrapper {
display: flex;
flex-direction: row;
flex: 1 1 auto;
}
#contentcolumn {
flex: 1 1 100%;
position: relative;
}
// Editor blocks
.umb-editor-wrapper {
display: flex;
flex-direction: column;
height: ~"(calc(~'100vh' - ~'@{navigationBarHeight}'))";
}
.umb-editor-header {
flex: 0 0 @editorHeaderHeight;
display: flex;
align-items: center;
box-sizing: border-box;
}
.umb-editor-container {
flex: 1 1 auto;
box-sizing: border-box;
overflow-y: auto;
//display: flex;
//flex-direction: row;
}
.umb-editor-content {
padding: 30px 20px;
}
.umb-editor-container-test {
flex: 1 1 auto;
padding: 30px 20px;
overflow-y: auto;
}
.umb-editor-container-sidebar {
flex: 0 0 400px;
padding: 30px 20px;
border-left: 1px solid @grayLight;
overflow-y: auto;
}
.umb-editor-drawer {
flex: 0 0 31px;
}
.umb-tree-navigation {
display: flex;
flex-direction: column;
flex: 0 0 300px;
border-right: 1px solid @grayLight;
overflow-y: auto;
padding-bottom: 20px;
}
.umb-panel-header-content-wrapper {
width: 100%;
}
.umb-toggle-tree {
display: flex;
align-items: center;
justify-content: center;
height: 49px;
width: 20px;
padding: 0 20px;
cursor: pointer;
transition: background-color 80ms ease;
}
.umb-toggle-icon {
margin: 0 auto 0 0;
width: 20px;
height: 2px;
background-color: @grayLight;
transition: all 80ms ease;
display: block;
}
.umb-toggle-icon:before,
.umb-toggle-icon:after {
content: '';
width: 20px;
height: 2px;
display: block;
background-color: @grayLight;
transition: all 80ms ease;
}
.umb-toggle-icon:before {
transform: translate(0, -5px);
width: 15px;
}
.umb-toggle-icon:after {
transform: translate(0, 3px);
width: 9px;
}
.umb-toggle-tree:hover,
.umb-toggle-tree.-open {
background: @grayLighter;
}
.umb-toggle-tree:hover .umb-toggle-icon,
.umb-toggle-tree:hover .umb-toggle-icon:before,
.umb-toggle-tree:hover .umb-toggle-icon:after {
background-color: @grayMed;
}
.umb-toggle-tree.-open .umb-toggle-icon,
.umb-toggle-tree.-open .umb-toggle-icon:before,
.umb-toggle-tree.-open .umb-toggle-icon:after {
width: 20px;
background-color: @grayMed;
}
@@ -59,7 +59,6 @@
@import "application/grid.less";
@import "application/shadows.less";
@import "application/animations.less";
@import "application/umb-navigation.less";
// Belle styles
@import "buttons.less";
@@ -85,8 +84,6 @@
@import "components/umb-sub-views.less";
@import "components/umb-editor-navigation.less";
@import "components/umb-editor-sub-views.less";
@import "components/editor/subviews/umb-editor-sub-view.less";
@import "components/editor/umb-editor-toolbar.less";
@import "components/editor/subheader/umb-editor-sub-header.less";
@import "components/umb-grid-selector.less";
@import "components/umb-child-selector.less";
@@ -111,9 +108,8 @@
@import "components/umb-empty-state.less";
@import "components/umb-property-editor.less";
@import "components/umb-iconpicker.less";
@import "components/umb-variations.less";
@import "components/umb-splitview.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";
@@ -4,29 +4,30 @@
.umb-editor-wrapper{
background: white;
// position: absolute;
// top: 0px; bottom: 0px; left: 0px; right: 0px;
position: absolute;
top: 0px; bottom: 0px; left: 0px; right: 0px;
}
.umb-editor-header {
//background: @grayLighter;
.umb-editor-header{
background: @grayLighter;
border-bottom: 1px solid @grayLight;
//position: absolute;
// height: 99px;
//top: 0px;
//right: 0px;
//left: 0px;
position: absolute;
height: 99px;
top: 0px;
right: 0px;
left: 0px;
}
.umb-editor-container {
// top: 101px;
// left: 0px;
// right: 0px;
// bottom: 52px;
// position: absolute;
// clear: both;
// overflow: auto;
top: 101px;
left: 0px;
right: 0px;
bottom: 52px;
position: absolute;
clear: both;
overflow: auto;
}
.umb-editor-wrapper.-no-footer .umb-editor-container {
@@ -38,18 +39,17 @@
}
.umb-editor-drawer{
//margin: 0;
margin: 0;
padding: 10px 20px;
//z-index: 999;
//position: absolute;
//bottom: 0px;
//left: 0px;
//right: 0px;
z-index: 999;
position: absolute;
bottom: 0px;
left: 0px;
right: 0px;
height: 31px;
//background: @grayLighter;
background: @grayLighter;
border-top: 1px solid @grayLight;
flex: 0 0 @editorFooterHeight;
box-sizing: border-box;
}
@@ -61,187 +61,3 @@
.umb-editor-actions li{
display: inline-block;
}
.umb-editor-header__published-state {
width: 10px;
height: 10px;
}
/* ----- LANGUAGE AND VARIATION */
.umb-editor-header__selected-variations {
display: flex;
flex-direction: row;
margin-top: 6px;
margin-bottom: -4px;
}
.umb-editor-header__selected-variation {
display: flex;
flex-direction: row;
font-size: 12px;
color: #9e9ea6;
}
.umb-editor-header__selected-variation:first-child {
margin-right: 10px;
}
.umb-editor-header__selected-variation-icon {
margin-right: 5px;
}
/* --- VARIATIONS --- */
.umb-variations-quick-switcher__toggle {
position: absolute;
top: 0;
right: 0;
display: flex;
align-items: center;
border: 1px solid #ECECEC;
padding-left: 20px;
padding-right: 20px;
height: 30px;
box-sizing: border-box;
}
.umb-variations-quick-switcher__toggle.-active,
.umb-variations-quick-switcher__toggle.-active:hover {
background: @blue;
border-color: @blue;
color: @white;
}
.umb-variations-quick-switcher__toggle:hover {
background-color: @grayLighter;
border-color: @grayLight;
}
.umb-variations-quick-switcher__toggle:hover,
.umb-variations-quick-switcher__toggle:focus {
text-decoration: none;
}
.umb-variations-quick-switcher__toggle-icon {
margin-right: 5px;
}
.umb-variations-quick-switcher__toggle-arrow {
}
.umb-variations-quick-switcher_variations {
position: absolute;
top: 30px;
left: 0;
right: 0;
z-index: 6200;
background-color: #ffffff;
max-height: 300px;
overflow-y: auto;
list-style: none;
margin-left: 0;
margin-bottom: 0;
}
.umb-variations-quick-switcher_variation > li {
border-left: 4px solid transparent;
box-sizing: border-box;
}
.umb-variations-quick-switcher_variation > li:hover {
border-color: @grayLighter;
}
.umb-variations-quick-switcher_variation > li.-active,
.umb-variations-quick-switcher_variation > li.-active:hover {
border-left-color: @blue;
}
.umb-variations-quick-switcher_variation li.-active,
.umb-variations-quick-switcher_variation li.-active:hover {
background-color: fade(@blueDark, 4%);
}
.umb-variations-quick-switcher__variation {
display: flex;
flex-direction: row;
align-items: center;
height: 60px;
padding: 0 15px;
}
.umb-variations-quick-switcher__variation-stroke {
border-left: 1px solid @grayLight;
padding-left: 10px;
}
.umb-variations-quick-switcher__subnav {
list-style: none;
margin-left: 0;
margin-bottom: 0;
}
.umb-variations-quick-switcher__variation:last-child {
border-bottom: none;
}
.umb-variations-quick-switcher__variation:hover,
.umb-variations-quick-switcher__variation:focus {
text-decoration: none;
outline: none;
}
.umb-variations-quick-switcher__variation:hover,
.umb-variations-quick-switcher__variation.-active {
background-color: @grayLighter;
}
.umb-variations-quick-switcher__variation.-active {
background-color: rgb(238, 246, 254);
}
.umb-variations-quick-switcher__variation-published-state {
display: block;
width: 6px;
height: 6px;
border-radius: 50%;
background-color: @grayLight;
margin-right: 10px;
}
.umb-variations-quick-switcher__variation-toggle {
font-size: 13px;
margin-left: auto;
opacity: .5;
padding: 5px 10px;
}
.umb-variations-quick-switcher__variation-toggle:hover {
opacity: 1;
}
.umb-variations-quick-switcher__variation-published-state.-published {
background-color: @green;
}
.umb-variations-quick-switcher__variation-name {
font-size: 13px;
font-weight: bold;
}
.umb-variations-quick-switcher__variation-icon {
color: @grayLight;
margin-right: 5px;
}
.umb-variations-quick-switcher__variation-description {
font-size: 11px;
color: @gray;
margin-left: 5px;
}
@@ -1,107 +0,0 @@
.umb-editor-sub-view {
display: flex;
flex-direction: column;
height: ~"(calc(~'100vh' - ~'@{navigationBarHeight}' - ~'@{editorHeaderHeight}' - ~'@{editorFooterHeight}'))";
}
.umb-editor-sub-view-header {
display: flex;
flex-direction: row;
border-bottom: 1px solid rgba(217,217,217, .6);
flex: 0 0 @editorSubViewHeaderHeight;
padding: 0 20px;
align-items: center;
box-sizing: border-box;
background: @grayLighter;
}
.umb-editor-sub-view-header__content-left {
margin-right: auto;
}
.umb-editor-sub-view-header__content-right {
margin-left: auto;
}
.umb-editor-sub-view-container {
flex: 1 1 auto;
display: flex;
flex-direction: row;
background: #F9F9F9;
}
.umb-editor-sub-view-content {
flex: 1 1 auto;
padding: 30px 20px;
overflow-y: auto;
position: relative;
}
.umb-editor-sub-view-sidebar {
flex: 0 0 400px;
border-left: 1px solid @grayLight;
display: flex;
flex-direction: column;
background: @white;
}
.umb-editor-sub-view-sidebar-header {
flex: 0 0 auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
padding: 20px 0;
}
.umb-editor-sub-view-sidebar-header i {
margin-left: auto;
cursor: pointer;
color: @grayMed;
}
.umb-editor-sub-view-sidebar-header i:hover {
color: @black;
}
.umb-editor-sub-view-sidebar-title {
font-size: 16px;
font-weight: bold;
color: @black;
display: flex;
width: 100%;
}
.umb-editor-sub-view-sidebar-container {
overflow-y: auto;
flex: 1 1 auto;
box-sizing: border-box;
padding-top: 20px;
padding-bottom: 20px;
}
.umb-editor-sub-view-sidebar-footer {
flex: 0 0 @editorFooterHeight;
background: @grayLighter;
display: flex;
align-items: center;
}
.umb-editor-sub-view-sidebar-header,
.umb-editor-sub-view-sidebar-container,
.umb-editor-sub-view-sidebar-footer {
padding-right: 20px;
padding-left: 20px;
}
@@ -1,19 +0,0 @@
.umb-editor-toolbar {
padding: 0 20px;
flex: 0 0 50px;
display: flex;
align-items: center;
border-bottom: 1px solid @grayLight;
justify-content: space-between;
}
.editor-toolbar-properties {
font-size: 20px;
color: @grayMed;
}
.editor-toolbar-properties:hover,
.editor-toolbar-properties:focus {
color: @grayDark !important;
text-decoration: none;
}
@@ -1,7 +1,7 @@
.umb-notifications {
z-index: 1000;
position: absolute;
bottom: @editorFooterHeight;
bottom: 52px;
left: 0;
right: 0;
border-bottom: none;
@@ -152,19 +152,30 @@
}
}
/* ---------- OVERLAY FULL ---------- */
.umb-overlay.umb-overlay-full {
left: 0;
right: 0;
top: @navigationBarHeight;
/* ---------- 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-full .umb-overlay-header {
display: none;
.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);
}
@@ -1,41 +1,14 @@
.umb-sub-views-nav {
list-style: none;
margin: 0;
display: flex;
flex-wrap: wrap;
align-items: flex-end;
justify-content: flex-end;
}
.umb-sub-views-nav-items {
display: flex;
justify-content: center;
height: 61px;
}
.umb-sub-views-nav-items .umb-navigation-more {
height: 20px;
margin: 0;
margin: 0;
}
.umb-sub-views-nav-item {
text-align: center;
padding: 10px;
margin-left: 20px;
cursor: pointer;
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-items: center;
max-width: 100%;
text-overflow: ellipsis;
box-sizing: border-box;
display: block;
}
.umb-sub-views-nav-item:focus {
@@ -62,23 +35,5 @@
}
.umb-sub-views-nav-item-text {
font-size: 11px;
vertical-align: baseline;
margin: 10px 0 0 0;
line-height: 1;
white-space: nowrap;
}
// drop down
.umb-sub-views-nav__dropdown {
position: absolute;
right: 20px;
background: #fff;
margin-top: 10px;
z-index: 1;
padding: 10px 20px;
display: flex;
justify-content: flex-end;
width: auto;
font-size: 11px;
}
@@ -4,8 +4,9 @@
// drop zone
// tall and small version - animate height
.dropzone {
height: 500px;
height: 400px;
width: 100%;
padding: 50px 0;
border: 1px dashed @grayLight;
text-align: center;
color: @gray;
@@ -14,12 +15,11 @@
-webkit-transition: height 0.8s;
-moz-transition: height 0.8s;
transition: height 0.8s;
box-sizing: border-box;
.illustration {
width: 300px;
}
&.is-small {
height: 200px;
height: 100px;
.illustration {
width: 200px;
}
@@ -1,146 +1,3 @@
.umb-property-editor.-not-clickable {
pointer-events: none;
}
.umb-property-editor {
position: relative;
}
.umb-property-editor__overlay {
background-color: rgba(255,255,255, .65);
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
}
.umb-property-editor__overlay-label {
font-size: 16px;
font-weight: bold;
color: #;
background: #ffffff;
padding: 10px 20px;
color: @grayLight;
}
.umb-property .control-label {
font-size: 14px;
}
.umb-property .control-label small {
font-size: 11px;
line-height: 17px;
margin-top: 5px;
margin-bottom: 10px;
}
.umb-property-editor__dropdown-toggling {
z-index: 1;
position: relative;
}
.umb-property-editor__dropdown-toggling.-active {
z-index: 10;
}
.umb-property-editor__dropdown-toggling.-active .umb-property-editor__dropdown-toggle {
color: @blue;
}
.umb-property-editor__dropdown-toggle {
display: inline-flex;
align-items: center;
width: auto;
box-sizing: border-box;
font-weight: bold;
font-size: 12px;
cursor: pointer;
margin-top: 5px;
}
.umb-property-editor__dropdown-toggle:hover {
color: @blue;
}
.umb-property-editor__dropdown-toggle i,
.umb-property-editor__dropdown-link i {
margin-right: 5px;
font-size: 12px;
}
.umb-property-editor__dropdown {
position: absolute;
z-index: 10;
min-width: 250px;
background: #ffffff;
margin-top: 5px;
}
.umb-property-editor__dropdown-items {
list-style: none;
margin-bottom: 0;
margin-left: 0;
font-size: 12px;
font-weight: normal;
max-height: 165px;
overflow-y: auto;
}
.umb-property-editor__dropdown-filter {
padding: 5px;
}
.umb-property-editor__dropdown-filter input[type="search"] {
font-size: 12px;
}
.umb-property-editor__dropdown-link.-sync-off {
border-bottom: 1px solid @grayLight;
padding: 10px;
font-size: 12px;
}
.umb-property-editor__dropdown-link.-sync-off:hover {
background: rgba(217,217,217, .35);
}
.umb-property-editor__dropdown-link {
padding: 5px 10px;
display: flex;
align-items: center;
box-sizing: border-box;
}
.umb-property-editor__dropdown-link:hover {
background-color: @grayLighter;
text-decoration: none;
}
@@ -1,41 +0,0 @@
/* split view */
.splitview--views {
display: flex;
}
.splitview--view {
position: relative;
flex: 1 1 100%;
}
.splitview--divider {
flex: 0 0 8px;
background: @white;
border-right: 1px solid @grayLight;
border-left: 1px solid @grayLight;
box-shadow: 0 0 4px rgba(0,0,0,0.1);
position: relative;
z-index: 1;
}
.splitview--close {
position: absolute;
bottom: 50px;
left: 50%;
transform: translate3d(-50%, -50%, 0);
z-index: 100;
font-size: 14px;
font-weight: bold;
padding: 8px 18px;
background: rgba(0,0,0,0.05);
border-radius: 6px;
cursor: pointer;
&:hover {
background: rgba(0,0,0,0.1);
}
}
@@ -1,119 +1,15 @@
.umb-tabs-nav {
list-style: none;
margin: 0;
.umb-nav-tabs {
position: absolute;
z-index: 10;
}
// Sub view header tabs
.umb-editor-sub-view-header .umb-tabs-nav {
display: flex;
flex-wrap: wrap;
.umb-nav-tabs.-padding-left {
padding-left: 20px;
}
.umb-editor-sub-view-header .umb-tabs-nav__tab a {
padding: 4px 10px;
font-size: 12px;
font-weight: bold;
border-radius: 6px;
margin-right: 15px;
}
.umb-editor-sub-view-header .umb-tabs-nav__tab a:hover,
.umb-editor-sub-view-header .umb-tabs-nav__tab a:active,
.umb-editor-sub-view-header .umb-tabs-nav__tab a:focus {
text-decoration: none !important;
background: rgba(0,0,0,0.05);
}
.umb-editor-sub-view-header .umb-tabs-nav__tab.active a {
background: @blue;
color: white;
text-decoration: none;
}
// Sidebar tabs
.umb-editor-sub-view-sidebar .umb-tabs-nav {
display: flex;
width: 100%;
border-bottom: 1px solid @grayLight;
padding-top: 25px;
}
.umb-editor-sub-view-sidebar .umb-tabs-nav__tab {
border-bottom: 3px solid transparent;
padding-bottom: 8px;
margin-right: 0;
flex: 1 1 100%;
font-size: 14px;
color: @grayMed;
}
.umb-editor-sub-view-sidebar .umb-tabs-nav__tab:hover,
.umb-editor-sub-view-sidebar .umb-tabs-nav__tab.-active {
text-decoration: none !important;
border-color: @blue;
color: @black;
}
.umb-editor-sub-view-sidebar .umb-tabs-nav__tab:focus,
.umb-editor-sub-view-sidebar .umb-tabs-nav__tab:active {
text-decoration: none !important;
}
// Umb activity demo css
.umb-activity {
padding: 0;
margin: 0;
}
.umb-activity-item {
border: 1px solid transparent;
padding: 10px;
list-style: none;
font-weight: bold;
cursor: pointer;
}
.umb-activity-item:hover {
border-color: @grayLight;
}
.umb-activity-item:hover .umb-activity-item-rollback {
color: @blue;
text-decoration: none;
}
.umb-activity-item-name {
display: block;
width: 100%;
font-size: 15px;
margin-bottom: 5px;
}
.umb-activity-item-rollback {
font-size: 13px;
color: @grayMed;
font-weight: normal;
}
.umb-activity-item .umb-activity-item-rollback:hover {
color: @blueDark;
}
.umb-activity-item + .umb-activity-item {
margin-top: 5px;
.umb-tab-content {
padding-top: 20px;
position: relative;
top: 22px;
border-top: 1px solid @grayLight;
}
@@ -1,356 +0,0 @@
.umb-variations {
max-width: 100%;
padding: 0 20px;
margin-right: auto;
margin-left: auto;
}
.umb-variations__title-wrapper {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-bottom: 20px;
}
.umb-variations__title {
font-size: 16px;
font-weight: bold;
color: @black;
}
.umb-variations__help-text {
line-height: 1.6em;
display: block;
color: @grayMed;
margin-bottom: 20px;
}
.umb-variations__filter {
margin-bottom: 10px;
}
.umb-varations__published-state {
width: 6px;
height: 6px;
border-radius: 50%;
background-color: @grayLight;
margin-right: 10px;
}
.umb-varations__published-state.-published {
background-color: @green;
}
/* ---------- VARIATIONS LANG GROUP ---------- */
.umb-varations__lang-group {
background: @white;
border: 1px solid @grayLight;
margin-bottom: 30px;
}
.umb-varations__lang-group-info {
padding: 20px 15px;
display: flex;
}
.umb-varations__lang-group-info__name {
font-size: 15px;
font-weight: bold;
display: flex;
align-items: center;
flex-direction: row;
flex: 1 1 auto;
}
.umb-varations__lang-group-info__link:hover {
text-decoration: underline;
cursor: pointer;
}
.umb-varations__lang-group-info__name i {
margin-right: 5px;
}
.umb-varations__lang-group-info__name small {
margin-left: 5px;
color: @grayMed;
font-weight: normal;
font-size: 13px;
}
.umb-varations__lang-group .umb-variations__action span {
font-size: 13px;
margin-left: 5px;
font-weight: bold;
}
.umb-varations__lang-group-info .umb-variations__action {
color: @blue;
display: flex;
}
.umb-varations__lang-group-info .umb-variations__action:hover {
color: @blueDark;
}
.umb-variations__no-variations {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 20px 40px;
}
.umb-variations__no-variations-message {
display: block;
margin-bottom: 20px;
font-size: 14px;
line-height: 22px;
color: #999;
}
/* ---------- VARIATIONS LIST ---------- */
.umb-variations__list {
list-style: none;
margin: 0;
}
.umb-variations__list-item-wrapper {
display: flex;
flex-direction: column;
}
.umb-variations__list-item {
padding: 15px;
flex: 3 1 auto;
border-top: 1px solid @grayLight;
background: #ffffff;
}
.umb-variations__list-item.-edit-mode {
background: @grayLighter;
border-top-color: #e7e7e7;
}
.umb-variations__list-item.-edit-mode + .umb-variations__edit-list-item {
border-top-color: @grayLighter;
}
.umb-variations__list-item__edit {
padding: 4px 10px;
border-radius: 6px;
font-size: 12px;
font-weight: bold;
background: rgba(0, 0, 0, 0.05);
}
.umb-variations__list-item__edit:hover {
background: rgba(0, 0, 0, 0.09);
cursor: pointer;
}
.umb-variations__variation-top-bar {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-between;
align-items: center;
}
.umb-variations__published-state {
width: 10px;
height: 10px;
border-radius: 20px;
background-color: @grayLight;
margin-right: 10px;
}
.umb-variations__published-state.-published {
background-color: @green;
}
.umb-variations__name-wrapper {
display: flex;
align-items: center;
flex-direction: row;
flex: 1 1 auto;
}
.umb-variations__name {
font-size: 13px;
font-weight: bold;
color: @black;
}
.umb-variations__name:hover {
text-decoration: underline;
cursor: pointer;
}
.umb-variations__name-icon {
margin-right: 5px;
}
.umb-variations__edit-form {
width: 100%;
}
.umb-variations__name-input:focus,
.umb-variations__name-input:active {
outline: none;
}
.umb-variations__description {
margin-bottom: 0;
margin-left: 5px;
resize: none;
font-size: 12px;
color: @grayMed;
}
.umb-variations__description-input {
resize: none;
}
.umb-variations__actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
}
.umb-variations__action {
font-size: 18px;
cursor: pointer;
display: flex;
align-items: center;
flex-direction: row;
}
.umb-variations__action + .umb-variations__action {
margin-left: 20px;
}
.umb-variations__action:hover {
color: @blue;
}
/* --- CREATE VARIATION --- */
.umb-variation__create-title {
color: @black;
font-weight: bold;
font-size: 24px;
margin-bottom: 10px;
}
.umb-variation__create-form-description {
resize: none;
min-height: 100px;
}
.umb-variation__create-form {
display: flex;
flex-direction: column;
}
.umb-variation__create-form label,
.umb-variations__edit-form label {
font-weight: bold;
}
.umb-variation__create-form-actions {
display: flex;
justify-content: flex-end;
}
.umb-variations__edit-form + .umb-variations__actions {
margin-top: 30px;
}
/* */
.form-group-actions {
margin-top: 10px;
margin-bottom: 0;
}
.umb-variations__edit-list-item {
display: flex;
flex-direction: column;
width: 100%;
padding: 20px 30px;
box-sizing: border-box;
background-color: @white;
border-top: 1px solid @grayLight;
}
/* MATCHES */
.umb-variations__matches {
list-style: none;
margin-bottom: 0;
margin-left: 0;
}
.umb-variations__match {
background: @grayLighter;
padding: 10px 15px;
cursor: grab;
border-left: 2px solid @blue;
margin-bottom: 5px;
}
/* TAGS */
.umb-variations__tags {
display: flex;
flex-wrap: wrap;
}
.umb-variations__tag {
display: flex;
flex: 0 0 100%;
overflow: hidden;
box-sizing: border-box;
text-overflow: ellipsis;
font-size: 13px;
}
.umb-variations__tag + .umb-variations__tag {
margin-top: 5px;
}
.umb-variations__tag .checkbox {
margin-right: 5px;
}
.umb-variations__tag .checkbox:checked + span {
font-weight: bold;
}
/* FORM */
.umb-variations__form-group {
margin-bottom: 10px;
}
.umb-variations__label {
font-weight: bold;
color: @black;
}
.umb-variations__label + .umb-variations__tags {
margin-top: 10px;
}
@@ -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;
}
+5 -11
View File
@@ -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;
}
@@ -49,7 +49,6 @@ label.control-label {
.form-search {
position: relative;
padding: 0;
margin-bottom: 0;
}
.form-search a{
text-decoration:none;
@@ -66,8 +65,8 @@ label.control-label {
}
.form-search .icon, .form-search .icon-search {
position: absolute;
top: 23px;
left: 20px;
top: 6px;
left: 4px;
color: @grayLight;
}
@@ -165,7 +164,7 @@ textarea {
// Identify controls by their labels
label {
display: block;
display: inline-block;
margin-bottom: 5px;
}
@@ -208,11 +207,6 @@ input.-full-width-input {
height: 30px;
}
textarea.-full-width-textarea {
width: 100%;
box-sizing: border-box;
}
// Reset appearance properties for textual inputs and textarea
// Declare width for legacy (can't be on input[type=*] selectors or it's too specific)
input,
+1 -1
View File
@@ -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 {
+61 -69
View File
@@ -2,11 +2,11 @@
// -------------------------
.umb-panel {
background: white;
// position: absolute;
// top: 0px;
// bottom: 0px;
// left: 0px;
// right: 0px;
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
.umb-panel-nobody {
@@ -17,21 +17,21 @@
.umb-panel-header {
background: @grayLighter;
border-bottom: 1px solid @grayLight;
// position: absolute;
// height: 99px;
// top: 0px;
// right: 0px;
// left: 0px;
position: absolute;
height: 99px;
top: 0px;
right: 0px;
left: 0px;
}
.umb-panel-body {
// top: 101px;
// left: 0px;
// right: 0px;
// bottom: 0px;
// position: absolute;
// clear: both;
// overflow: auto;
top: 101px;
left: 0px;
right: 0px;
bottom: 0px;
position: absolute;
clear: both;
overflow: auto;
}
.umb-panel-body.no-header {
@@ -356,7 +356,7 @@
.umb-panel-header-content-wrapper {
display: flex;
flex-direction: column;
// height: 100px;
height: 100px;
padding: 0 20px;
}
@@ -366,18 +366,15 @@
flex: 1;
}
/*
.umb-panel-header-content.-top-position {
position: relative;
top: -12px;
}
*/
.umb-panel-header-left-side {
display: flex;
flex: 1;
flex-direction: row;
align-items: center;
}
.umb-panel-header-icon {
@@ -499,68 +496,63 @@ input.umb-panel-header-description {
// Large Search
.large-search {
font-size: 18px;
padding-top: 20px;
padding-bottom: 10px;
border-bottom: 1px solid @grayLight;
display: flex;
flex-direction: row;
align-items: center;
/* --- VARIATIONS --- */
.umb-variations-quick-switcher__toggle {
position: absolute;
top: 6px;
right: 10px;
font-size: 16px;
}
.large-search,
.umb-tree.large-search-results {
width: 100%;
max-width: 960px;
min-width: auto;
margin: 0 auto;
.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;
}
.large-search .umb-search-field {
border-bottom: none;
font-size: 22px;
text-indent: 10px;
padding-left: 0 !important;
line-height: 60px;
.umb-variations-quick-switcher__variation {
display: flex;
flex-direction: row;
align-items: center;
padding: 10px 15px;
}
.large-search .icon-search {
color: @black;
position: static;
font-size: 22px;
.umb-variations-quick-switcher__variation:last-child {
border-bottom: none;
}
.umb-tree.large-search-results .umb-search-group-item-link {
padding: 10px 0;
display: flex;
flex-direction: row;
align-items: center;
min-height: 60px;
.umb-variations-quick-switcher__variation:hover,
.umb-variations-quick-switcher__variation:focus {
background-color: @grayLighter;
text-decoration: none;
outline: none;
}
.umb-tree.large-search-results .umb-search-group-item-info {
display: flex;
flex-direction: column;
align-items: flex-start;
position: relative;
overflow: visible;
.umb-variations-quick-switcher__variation-published-state {
display: block;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: @grayLight;
margin-right: 10px;
}
.umb-tree.large-search-results .umb-search-group-item-link .icon {
font-size: 24px;
.umb-variations-quick-switcher__variation-published-state.-published {
background-color: @green;
}
.umb-tree.large-search-results .umb-search-group-item-name {
font-size: 16px;
font-weight: bold;
.umb-variations-quick-switcher__variation-name {
font-size: 12px;
font-weight: bold;
}
.umb-tree.large-search-results .search-subtitle {
padding-left: 0;
.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
@@ -196,6 +199,7 @@ ul.color-picker li a {
flex-wrap: wrap;
padding: 2px;
margin: 5px;
background: white;
border: 1px solid #f8f8f8;
}
@@ -1,39 +1,26 @@
// Sections
// -------------------------
.umb-sections {
//margin: 0;
//display: block;
//background: @blackLight;
display: flex;
flex-direction: row;
flex-wrap: wrap;
//height: 100%;
//width: 80px;
//border-right: 1px solid @grayDark;
ul.sections {
margin: 0;
display: block;
background: @blackLight;
height: 100%;
width: 80px;
border-right: 1px solid @grayDark;
}
.umb-sections__section {
//border-left: 4px @blackLight solid;
//-webkit-transition: all .3s linear;
//-moz-transition: all .3s linear;
//transition: all .3s linear;
ul.sections li {
display: block;
border-left: 4px @blackLight solid;
-webkit-transition: all .3s linear;
-moz-transition: all .3s linear;
transition: all .3s linear;
}
.umb-sections__section:hover {
background: #E2E2E2;
text-decoration: none;
}
.umb-sections__section.-current,
.umb-sections__section:focus {
outline: none;
text-decoration: none;
color: @blue;
}
/*
ul.sections li [class^="icon-"]:before,
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;
@@ -41,15 +28,13 @@ ul.sections li [class*=" icon-"]:before{
-moz-transition: all .3s linear;
transition: all .3s linear;
}
*/
/*
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 [class*=" icon-"]:before,
ul.sections:hover li img.icon-section {
opacity: 1
}
*/
/*
ul.sections li a {
display: block;
text-decoration: none;
@@ -60,7 +45,7 @@ ul.sections li a {
width: 100%;
height: 100%;
margin: 0 0 0 -4px;
cursor: pointer; // make sure IE10 displays pointer cursor for expand and help sections.
cursor: pointer; // make sure IE10 displays pointer cursor for expand and help sections.
}
ul.sections a span {
@@ -76,12 +61,11 @@ ul.sections a span {
ul.sections:hover a span {
opacity: 1
}
*/
// Avatar, Section & Help icons
// -------------------------
/*
ul.sections li.avatar {
height: 75px;
padding: 22px 0 2px 0;
@@ -102,8 +86,7 @@ ul.sections li.avatar a img {
border-radius: 50%;
width: 30px;
}
*/
/*
.faded ul.sections li {
opacity: 0.4
}
@@ -120,7 +103,7 @@ ul.sections li.current a{
padding-left: 0px;
}
ul.sections li.help {
ul.sections li.help {
margin: 0;
position: absolute;
bottom: 0;
@@ -132,11 +115,9 @@ ul.sections li.help {
ul.sections li.help a {
border-bottom: none;
}
*/
// Section slide-out tray for additional apps
// -------------------------
li.expand a, li.expand{border: none !Important;}
li.expand {
@@ -146,7 +127,7 @@ li.expand {
-o-transition: all 1s !important;
-moz-transition: all 1s !important;
transition: all 1s !important;
&:before {
-ms-transform: rotate(180deg) !important; /* IE 9 */
-webkit-transform: rotate(180deg) !important; /* Chrome, Safari, Opera */
@@ -168,7 +149,7 @@ ul.sections-tray {
& > li {
// 5px (instead of 4px) because of vertical border
border-left-width: 5px;
&.current, &:hover {
border-left-width: 5px;
}
@@ -7,15 +7,6 @@
// --------------------------------------------------
//
// -------------------------
@navigationBarHeight: 50px;
@editorHeaderHeight: 80px;
@editorFooterHeight: 50px;
@editorSubViewHeaderHeight: 50px;
// Grays
// -------------------------
@black: #000;
@@ -20,36 +20,28 @@
hide-alias="true">
</umb-editor-header>
<umb-editor-toolbar umb-tabs>
<umb-tabs-nav ng-if="dashboard.tabs" model="dashboard.tabs"></umb-tabs-nav>
</umb-editor-toolbar>
<umb-editor-container>
<div class="umb-editor-content">
<umb-tabs-content view="true">
<umb-tab id="tab{{tab.id}}" ng-repeat="tab in dashboard.tabs" rel="{{tab.id}}">
<umb-tabs-content view="true">
<umb-tab id="tab{{tab.id}}" ng-repeat="tab in dashboard.tabs" rel="{{tab.id}}">
<div ng-repeat="property in tab.properties" ng-switch on="property.serverSide">
<div ng-repeat="property in tab.properties" ng-switch on="property.serverSide">
<div class="span12 clearfix" ng-switch-when="false">
<h3 ng-show="property.caption">{{property.caption}}</h3>
<div ng-include="property.path"></div>
</div>
<div ng-switch-when="false">
<h3 ng-show="property.caption">{{property.caption}}</h3>
<div ng-include="property.path"></div>
</div>
<div class="span12 umb-dashboard-control clearfix" ng-switch-when="true">
<h3 ng-show="property.caption">{{property.caption}}</h3>
<div class="span12 umb-dashboard-control clearfix" ng-switch-when="true">
<h3 ng-show="property.caption">{{property.caption}}</h3>
<iframe ng-src="dashboard/usercontrolproxy.aspx?ctrl={{ property.path}}"></iframe>
</div>
<iframe ng-src="dashboard/usercontrolproxy.aspx?ctrl={{ property.path}}"></iframe>
</div>
</div>
</div>
</umb-tab>
</umb-tabs-content>
</div>
</umb-tab>
</umb-tabs-content>
</umb-editor-container>
@@ -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>
@@ -1,132 +0,0 @@
(function() {
"use strict";
function SearchOverlay($scope, searchService, $log, $location, navigationService, $q) {
$scope.searchTerm = null;
$scope.searchResults = [];
$scope.isSearching = false;
$scope.selectedResult = -1;
$scope.navigateResults = function(ev) {
//38: up 40: down, 13: enter
switch (ev.keyCode) {
case 38:
iterateResults(true);
break;
case 40:
iterateResults(false);
break;
case 13:
if ($scope.model.selectedItem) {
$scope.selectItem($scope.model.selectedItem);
}
break;
}
};
$scope.selectItem = function(selectedItem) {
$scope.model.selectedItem = selectedItem;
$scope.model.submit($scope.model);
};
var group = undefined;
var groupIndex = -1;
var itemIndex = -1;
$scope.model.selectedItem = undefined;
function iterateResults(up) {
//default group
if (!group) {
group = $scope.groups[0];
groupIndex = 0;
}
if (up) {
if (itemIndex === 0) {
if (groupIndex === 0) {
gotoGroup($scope.groups.length - 1, true);
} else {
gotoGroup(groupIndex - 1, true);
}
} else {
gotoItem(itemIndex - 1);
}
} else {
if (itemIndex < group.results.length - 1) {
gotoItem(itemIndex + 1);
} else {
if (groupIndex === $scope.groups.length - 1) {
gotoGroup(0);
} else {
gotoGroup(groupIndex + 1);
}
}
}
}
function gotoGroup(index, up) {
groupIndex = index;
group = $scope.groups[groupIndex];
if (up) {
gotoItem(group.results.length - 1);
} else {
gotoItem(0);
}
}
function gotoItem(index) {
itemIndex = index;
$scope.model.selectedItem = group.results[itemIndex];
}
//used to cancel any request in progress if another one needs to take it's place
var canceler = null;
$scope.$watch("searchTerm", _.debounce(function(newVal, oldVal) {
$scope.$apply(function() {
if ($scope.searchTerm) {
if (newVal !== null && newVal !== undefined && newVal !== oldVal) {
$scope.isSearching = true;
//navigationService.showSearch();
$scope.model.selectedItem = undefined;
//a canceler exists, so perform the cancelation operation and reset
if (canceler) {
console.log("CANCELED!");
canceler.resolve();
canceler = $q.defer();
} else {
canceler = $q.defer();
}
searchService.searchAll({
term: $scope.searchTerm,
canceler: canceler
}).then(function(result) {
$scope.groups = _.filter(result, function(group) {
return group.results.length > 0;
});
//set back to null so it can be re-created
canceler = null;
});
}
} else {
$scope.isSearching = false;
//navigationService.hideSearch();
$scope.model.selectedItem = undefined;
}
});
}, 200));
}
angular.module("umbraco").controller("Umbraco.Overlays.SearchOverlay", SearchOverlay);
})();
@@ -1,50 +0,0 @@
<div ng-controller="Umbraco.Overlays.SearchOverlay">
<!-- Search form -->
<form class="form-search large-search" novalidate>
<i class="icon-search"></i>
<input type="text"
id="search-field"
ng-model="searchTerm"
class="umb-search-field search-query search-input"
localize="placeholder"
placeholder="@placeholders_search"
ng-keydown="navigateResults($event)"
umb-auto-focus
autocomplete="off" />
</form>
<!-- Search results --->
<ul class="umb-tree large-search-results">
<li class="root">
<div>
<h5 class="umb-tree-header"><localize key="general_searchResults">Search results</localize></h5>
</div>
<ul class="umb-search-group" ng-repeat="group in groups">
<li ng-repeat="result in group.results" ng-class="{'current':model.selectedItem == result}">
<div class="umb-search-group-item">
<a class="umb-search-group-item-link" ng-class="{'first':$first}" ng-click="selectItem(result)">
<i class="icon umb-tree-icon sprTree {{result.icon}}"></i>
<div class="umb-search-group-item-info">
<div class="umb-search-group-item-name">
{{result.name}}
</div>
<small class="search-subtitle" ng-show="result.subTitle">
{{result.subTitle}}
</small>
</div>
</a>
</div>
</li>
</ul>
</li>
</ul>
</div>
@@ -1,66 +1,116 @@
<div
class="umb-navigation"
ng-controller="Umbraco.NavigationController"
ng-mouseleave="leaveTree($event)"
ng-mouseenter="enterTree($event)">
<div id="leftcolumn" ng-controller="Umbraco.NavigationController"
ng-mouseleave="leaveTree($event)" ng-mouseenter="enterTree($event)">
<div class="umb-toggle-tree"
ng-click="showTree()"
ng-class="{'-open':showTreeNavigation}">
<div class="umb-toggle-icon"></div>
</div>
<umb-sections
ng-if="authenticated"
sections="sections">
<umb-sections sections="sections" ng-if="authenticated">
</umb-sections>
<div class="umb-navigation__right">
<!-- navigation container -->
<div id="navigation" ng-show="showNavigation" class="fill umb-modalcolumn" ng-animate="'slide'" nav-resize>
<div class="search">
<a class="umb-navigation-link" href class="help" hotkey="ctrl+shift+s" ng-click="searchClick()" prevent-default>
<span>Search</span>
</a>
<div ng-swipe-left="nav.hideNavigation()" class="navigation-inner-container span6">
<!-- the search -->
<div ng-controller="Umbraco.SearchController" ng-if="authenticated">
<!-- Search form -->
<div id="search-form">
<div class="umb-modalcolumn-header">
<form class="form-search" novalidate>
<i class="icon-search"></i>
<input type="text"
hotkey="ctrl+space"
id="search-field"
ng-model="searchTerm"
class="umb-search-field search-query search-input"
localize="placeholder"
placeholder="@placeholders_search"
ng-keydown="navigateResults($event)"/>
</form>
</div>
</div>
<!-- Search results -->
<div id="search-results" class="umb-modalcolumn-body" ng-show="showSearchResults">
<ul class="umb-tree">
<li class="root">
<div>
<h5 class="umb-tree-header"><localize key="general_searchResults">Search results</localize></h5>
</div>
<ul class="umb-search-group" ng-repeat="group in groups">
<li ng-repeat="result in group.results" ng-class="{'current':selectedItem == result}">
<div class="umb-search-group-item">
<a class="umb-search-group-item-link" ng-class="{'first':$first}" ng-click="searchHide()" ng-href="#/{{result.editorPath}}">
<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-show="result.subTitle">
{{result.subTitle}}
</small>
</a>
<a href ng-click="searchShowMenu($event, {node: result})" class="umb-options"><i></i><i></i><i></i></a>
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
<umb-website-selector
websites="websites"
on-create-website="createWebsite"
on-click-website="clickWebsite">
</umb-website-selector>
<!-- the tree -->
<div id="tree" ng-if="authenticated && websites.length > 0">
<umb-tree
cachekey="_"
eventhandler="treeEventHandler"
section="{{currentSection}}" >
</umb-tree>
</div>
</div>
<div class="help">
<a class="umb-navigation-link" href class="help" hotkey="ctrl+shift+h" ng-click="helpClick()" prevent-default>
<span><localize key="sections_help">Help</localize></span>
</a>
</div>
<div class="offset6" id="navOffset" style="z-index: 10">
<div>
<a class="umb-navigation-link" href="#" ng-click="avatarClick()" hotkey="ctrl+shift+u" title="{{user.name}}" prevent-default>
<span>{{user.name}}</span>
<img id="avatar-img" ng-src="{{avatar[0].value}}" ng-srcset="{{avatar[1].value}} 2x, {{avatar[2].value}} 3x" />
</a>
</div>
<!-- The context menu -->
<div id='contextMenu' class="umb-modalcolumn fill shadow" ng-swipe-left="nav.hideMenu()" ng-show="showContextMenu" ng-animate="'slide'">
<umb-context-menu
menu-dialog-title="{{menuDialogTitle}}"
current-section="{{currentSection}}"
current-node="menuNode"
menu-actions="menuActions">
</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'
ng-swipe-left="nav.hideDialog()"
ng-show="showContextMenuDialog" ng-animate="'slide'">
<div class='umb-modalcolumn-header'>
<h1>{{menuDialogTitle}}</h1>
</div>
<div class='umb-modalcolumn-body'>
</div>
</div>
</div>
</div>
<!-- navigation container -->
<umb-overlay
ng-if="searchOverlay.show"
model="searchOverlay"
view="searchOverlay.view"
position="full">
</umb-overlay>
<umb-overlay
ng-if="helpDialog.show"
model="helpDialog"
view="helpDialog.view"
position="right">
</umb-overlay>
<umb-overlay
ng-if="userDialog.show"
model="userDialog"
view="userDialog.view"
position="right">
</umb-overlay>
</div>
@@ -1,45 +1,62 @@
<div>
<nav class="umb-sections">
<a
class="umb-navigation-link"
href="#/{{section.alias}}"
ng-repeat="section in sections | limitTo: maxSections"
ng-class="{'-current': section.alias == currentSection}"
ng-dblclick="sectionDblClick(section)"
ng-click="sectionClick($event, section)"
prevent-default>
<span class="umb-sections__section-name">{{section.name}}</span>
</a>
<span class="umb-navigation-link expand"
ng-class="{ 'open': showTray === true }"
ng-show="needTray"
href ng-click="trayClick()">
<svg class="umb-navigation-more" viewBox="0 0 24 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path class="umb-navigation-more__path" d="M2.76923077,5.53846154 C4.29863469,5.53846154 5.53846154,4.29863469 5.53846154,2.76923077 C5.53846154,1.23982685 4.29863469,0 2.76923077,0 C1.23982685,0 0,1.23982685 0,2.76923077 C0,4.29863469 1.23982685,5.53846154 2.76923077,5.53846154 Z M12,5.53846154 C13.5294039,5.53846154 14.7692308,4.29863469 14.7692308,2.76923077 C14.7692308,1.23982685 13.5294039,0 12,0 C10.4705961,0 9.23076923,1.23982685 9.23076923,2.76923077 C9.23076923,4.29863469 10.4705961,5.53846154 12,5.53846154 Z M21.2307692,5.53846154 C22.7601732,5.53846154 24,4.29863469 24,2.76923077 C24,1.23982685 22.7601732,0 21.2307692,0 C19.7013653,0 18.4615385,1.23982685 18.4615385,2.76923077 C18.4615385,4.29863469 19.7013653,5.53846154 21.2307692,5.53846154 Z"></path>
</g>
</svg>
<div class="umb-sections__tray shadow-depth-2"
ng-show="showTray">
<a class="umb-navigation-link"
ng-repeat="section in sections | limitTo: overflowingSections"
ng-class="{'-current': section.alias == currentSection}"
href="#/{{section.alias}}"
<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>
</div>
</span>
<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>
</nav>
<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>
@@ -1,74 +0,0 @@
<div class="umb-tree-navigation" ng-show="showTreeNavigation">
<!-- the search
<div ng-controller="Umbraco.SearchController" ng-if="authenticated">
-->
<!-- Search form
<form class="form-search" novalidate>
<i class="icon-search"></i>
<input type="text"
hotkey="ctrl+space"
id="search-field"
ng-model="searchTerm"
class="umb-search-field search-query search-input"
localize="placeholder"
placeholder="@placeholders_search"
ng-keydown="navigateResults($event)"/>
</form>
-->
<!-- Search results
<div ng-show="showSearchResults">
<ul class="umb-tree">
<li class="root">
<div>
<h5 class="umb-tree-header"><localize key="general_searchResults">Search results</localize></h5>
</div>
<ul class="umb-search-group" ng-repeat="group in groups">
<li ng-repeat="result in group.results" ng-class="{'current':selectedItem == result}">
<div class="umb-search-group-item">
<a class="umb-search-group-item-link" ng-class="{'first':$first}" ng-click="searchHide()" ng-href="#/{{result.editorPath}}">
<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-show="result.subTitle">
{{result.subTitle}}
</small>
</a>
<a href ng-click="searchShowMenu($event, {node: result})" class="umb-options"><i></i><i></i><i></i></a>
</div>
</li>
</ul>
</li>
</ul>
</div>
-->
<!--
</div>
--->
<!--
<div ng-show="!showSearchResults">
<umb-tree
cachekey="_"
eventhandler="treeEventHandler"
section="{{currentSection}}" >
</umb-tree>
</div>
--->
<umb-tree
cachekey="_"
eventhandler="treeEventHandler"
section="{{currentSection}}" >
</umb-tree>
</div>
@@ -1 +0,0 @@
<div class="umb-editor-sub-view-container" ng-transclude></div>
@@ -1 +0,0 @@
<div class="umb-editor-sub-view-content" ng-transclude></div>
@@ -1 +0,0 @@
<div class="umb-editor-sub-view-header" ng-transclude></div>
@@ -1 +0,0 @@
<div class="umb-editor-sub-view-sidebar" ng-transclude></div>
@@ -1 +0,0 @@
<div class="umb-editor-sub-view" ng-transclude></div>
@@ -1,8 +1,6 @@
<div
class="umb-editor-container"
ng-class="{'-stop-scrolling': numberOfOverlays > 0}"
ng-transclude>
<!--
<umb-overlay-backdrop></umb-overlay-backdrop>
-->
</div>
<div class="umb-editor-container umb-panel-body umb-scrollable row-fluid" ng-class="{'-stop-scrolling': numberOfOverlays > 0}">
<umb-overlay-backdrop></umb-overlay-backdrop>
<div class="umb-pane">
<div ng-transclude></div>
</div>
</div>
@@ -1,4 +1,4 @@
<div class="umb-editor-header">
<div class="umb-panel-header">
<div class="umb-panel-header-content-wrapper">
@@ -15,10 +15,6 @@
<div class="umb-panel-header-title-wrapper">
<!--
<div class="umb-editor-header__published-state"></div>
--->
<ng-form name="headerNameForm">
<input
type="text"
@@ -29,70 +25,16 @@
ng-show="!nameLocked"
ng-model="name"
ng-class="{'name-is-empty': $parent.name===null || $parent.name===''}"
ng-disabled="variation"
umb-auto-focus
autocomplete="off"
required />
<div class="umb-editor-header__selected-variations" ng-if="language || variation">
<div class="umb-editor-header__selected-variation" ng-if="language && variations.length > 1">
<i class="umb-editor-header__selected-variation-icon icon-umb-translation"></i>
<div>{{ language }}</div>
</div>
<div class="umb-editor-header__selected-variation" ng-if="variation">
<i class="umb-editor-header__selected-variation-icon icon-documents"></i>
<div>{{ variation }}</div>
</div>
</div>
</ng-form>
<a class="umb-variations-quick-switcher__toggle" href="" ng-if="showVariationsQuickSwitchToggle" ng-click="toggleVariationsQuickSwitch()" ng-class="{'-active' : showVariationsQuickSwitch}">
<span class="umb-variations-quick-switcher__toggle-arrow">&dtrif;</span>
</a>
<ul class="umb-variations-quick-switcher_variations shadow-depth-2" ng-if="showVariationsQuickSwitch" on-outside-click="hideVariationsQuickSwitch()">
<!-- Multiple languages -->
<li ng-repeat="variation in variations" ng-class="{'-active' : variation.showSubItems}">
<a class="umb-variations-quick-switcher__variation" href ng-if="variations.length === 1" ng-click="selectItem(variation)" ng-class="{'-active': variation.active}">
<span class="umb-variations-quick-switcher__variation-published-state" ng-class="{'-published': variation.published}"></span>
<span class="umb-variations-quick-switcher__variation-name">{{variation.name}}</span>
<span class="umb-variations-quick-switcher__variation-description">(Original)</span>
</a>
<a class="umb-variations-quick-switcher__variation" href ng-if="variations.length > 1" ng-click="selectItem(variation)" ng-class="{'-active': variation.active}">
<span class="umb-variations-quick-switcher__variation-published-state" ng-class="{'-published': variation.published}"></span>
<i class="umb-variations-quick-switcher__variation-icon icon-umb-translation"></i>
<span class="umb-variations-quick-switcher__variation-name">{{variation.language}}</span>
<!--
<span class="umb-variations-quick-switcher__variation-toggle" ng-if="variation.variations" ng-click="toggleSubItems(variation, $event)">variations &dtrif;</span>
--->
<span class="umb-variations-quick-switcher__variation-toggle" ng-if="onOpenInSplitView && !variation.active" ng-click="openInSplitView(variation, $event)">Open in splitview</span>
</a>
<ul class="umb-variations-quick-switcher__subnav">
<li ng-repeat="test in variation.variations">
<a class="umb-variations-quick-switcher__variation" href ng-click="selectItem(test)" ng-class="{'-active': test.active}">
<span class="umb-variations-quick-switcher__variation-published-state" ng-class="{'-published': test.published}"></span>
<i class="umb-variations-quick-switcher__variation-icon icon-documents"></i>
<span class="umb-variations-quick-switcher__variation-name">{{ test.variationName }}</span>
<span class="umb-variations-quick-switcher__variation-description" ng-if="test.variationDescription">({{ test.variationDescription }})</span>
<span class="umb-variations-quick-switcher__variation-toggle" ng-if="onOpenInSplitView && !test.active" ng-click="openInSplitView(test, $event)">Open in splitview</span>
</a>
</li>
</ul>
</li>
</ul>
<div class="umb-panel-header-name" ng-if="nameLocked">{{ name }}</div>
<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"
@@ -117,7 +59,7 @@
</div>
<!-- <umb-tabs-nav ng-if="tabs" model="tabs"></umb-tabs-nav> -->
<umb-tabs-nav ng-if="tabs" model="tabs"></umb-tabs-nav>
</div>
@@ -1,37 +1,15 @@
<div>
<ul class="umb-sub-views-nav" ng-if="showNavigation">
<li ng-repeat="item in navigation | limitTo: maxNavigationItems" class="umb-sub-views-nav-items">
<a tabindex="-1" class="umb-sub-views-nav-item" href="" ng-click="clickNavigationItem(item)" hotkey="{{$index+1}}" ng-class="{'is-active': item.active, '-has-error': item.hasError}">
<i class="icon {{ item.icon }}"></i>
<span class="umb-sub-views-nav-item-text">{{ item.name }}</span>
</a>
</li>
<li class="umb-sub-views-nav-items" ng-if="needDropdown" ng-click="toggleDropdown()">
<a href="" class="umb-sub-views-nav-item">
<svg class="umb-navigation-more" viewBox="0 0 24 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path class="umb-navigation-more__path" d="M2.76923077,5.53846154 C4.29863469,5.53846154 5.53846154,4.29863469 5.53846154,2.76923077 C5.53846154,1.23982685 4.29863469,0 2.76923077,0 C1.23982685,0 0,1.23982685 0,2.76923077 C0,4.29863469 1.23982685,5.53846154 2.76923077,5.53846154 Z M12,5.53846154 C13.5294039,5.53846154 14.7692308,4.29863469 14.7692308,2.76923077 C14.7692308,1.23982685 13.5294039,0 12,0 C10.4705961,0 9.23076923,1.23982685 9.23076923,2.76923077 C9.23076923,4.29863469 10.4705961,5.53846154 12,5.53846154 Z M21.2307692,5.53846154 C22.7601732,5.53846154 24,4.29863469 24,2.76923077 C24,1.23982685 22.7601732,0 21.2307692,0 C19.7013653,0 18.4615385,1.23982685 18.4615385,2.76923077 C18.4615385,4.29863469 19.7013653,5.53846154 21.2307692,5.53846154 Z"></path>
</g>
</svg>
<span class="umb-sub-views-nav-item-text">More</span>
</a>
</li>
</ul>
<div class="umb-sub-views-nav__dropdown shadow-depth-2" ng-if="showDropdown" on-outside-click="closeDropdown()">
<ul class="umb-sub-views-nav">
<li ng-repeat="item in navigation | limitTo: overflowingNavigationsItems" class="umb-sub-views-nav-items">
<a tabindex="-1" class="umb-sub-views-nav-item" href="" ng-click="clickNavigationItem(item)" hotkey="{{$index+1}}" ng-class="{'is-active': item.active, '-has-error': item.hasError}">
<i class="icon {{ item.icon }}"></i>
<span class="umb-sub-views-nav-item-text">{{ item.name }}</span>
</a>
</li>
</ul>
</div>
<ul class="umb-sub-views-nav" ng-if="showNavigation">
<li ng-repeat="item in navigation">
<a tabindex="-1"
class="umb-sub-views-nav-item"
href=""
ng-click="clickNavigationItem(item)"
hotkey="{{$index+1}}"
ng-class="{'is-active': item.active, '-has-error': item.hasError}">
<i class="icon {{ item.icon }}"></i>
<span class="umb-sub-views-nav-item-text">{{ item.name }}</span>
</a>
</li>
</ul>
</div>
@@ -3,7 +3,7 @@
id="sub-view-{{$index}}"
ng-repeat="subView in subViews"
ng-include="subView.view"
ng-show="subView.active"
ng-show="activeView.name == subView.name"
ng-class="'sub-view-' + subView.name"
val-sub-view>
</div>
@@ -1 +0,0 @@
<div class="umb-editor-toolbar" ng-transclude></div>
@@ -1,4 +1,4 @@
<div class="umb-panel umb-editor-wrapper"
<div class="umb-panel umb-editor-wrapper animated -half-second fadeIn"
ng-class="{
'-no-footer': footer === 'false'
}"
@@ -1,8 +1,3 @@
<div class="umb-property-editor" ng-class="{'-not-clickable': preview}">
<!--
<div class="umb-property-editor__overlay" ng-if="model.variation">
<div class="umb-property-editor__overlay-label">Gets content from {{model.variation.name}}</div>
</div>
--->
<div ng-include="propertyEditorView"></div>
</div>
@@ -1,46 +1,14 @@
<div class="umb-property">
<ng-form name="propertyForm">
<div class="control-group umb-control-group" ng-class="{hidelabel:property.hideLabel}" >
<val-property-msg property="property"></val-property-msg>
<div class="umb-el-wrap">
<label class="control-label" ng-hide="property.hideLabel" for="{{property.alias}}" ng-attr-title="{{propertyAlias}}">
{{property.label}}
<small ng-if="property.description" ng-bind-html="property.description"></small>
<!--
<div class="umb-property-editor__dropdown-toggling" ng-class="{'-active' : showDropdown}">
<div class="umb-property-editor__dropdown-toggle" ng-click="toggleDropdown()">
<div ng-if="property.variation"><i class="icon-sync"></i>from {{ property.variation.name }} &dtrif;</div>
<div ng-if="!property.variation"><i class="icon-sync"></i>from &dtrif;</div>
</div>
<div class="umb-property-editor__dropdown shadow-depth-2" ng-if="showDropdown" on-outside-click="closeDropdown()">
<div class="umb-property-editor__dropdown-item">
<a class="umb-property-editor__dropdown-link -sync-off" ng-click="editContent()" href="">
<i class="icon-sync"></i>Off
</a>
</div>
<div class="umb-property-editor__dropdown-filter" ng-if="variations.length > 9">
<input type="search"class="-full-width-input" placeholder="Search for variants" ng-model="searchTerm" umb-auto-focus>
</div>
<ul class="umb-property-editor__dropdown-items">
<li class="umb-property-editor__dropdown-item" ng-repeat="variation in variations | filter:searchTerm">
<a class="umb-property-editor__dropdown-link" ng-click="syncContent(variation)" href="">{{ variation.name }}</a>
</li>
</ul>
</div>
</div>
--->
<small ng-bind-html="property.description"></small>
</label>
<div class="controls" ng-transclude>
@@ -48,4 +16,4 @@
</div>
</div>
</ng-form>
</div>
</div>
@@ -1,5 +1,5 @@
<ul class="umb-tabs-nav">
<li class="umb-tabs-nav__tab" ng-class="{'tab-error': tabHasError}" ng-repeat="tab in model" val-tab>
<a data-toggle="tab" href="#tab{{tab.id}}">{{ tab.label }}</a>
</li>
<ul class="nav nav-tabs umb-nav-tabs">
<li ng-class="{'tab-error': tabHasError}" ng-repeat="tab in model" val-tab>
<a data-toggle="tab" href="#tab{{tab.id}}">{{ tab.label }}</a>
</li>
</ul>
@@ -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>

Some files were not shown because too many files have changed in this diff Show More