Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8c264b0815 | |||
| 12ecc5d650 | |||
| 26dce2c99d | |||
| 4649811abd | |||
| 6af5795a1d | |||
| 68f6e27d20 | |||
| ef035df8b8 | |||
| 35e6a64e73 | |||
| 5bb6ffc654 | |||
| 30905a9442 | |||
| ccfec9e092 | |||
| a2007a96af | |||
| 0879bdb90e | |||
| 1f483bc95c | |||
| e1df9d7a00 | |||
| 41718cb7d5 | |||
| 75d6e02c63 | |||
| c1d09c2516 | |||
| ed429786ca | |||
| 88f108bf2e | |||
| 437bf6bea1 | |||
| 6eb678b821 | |||
| 4d3af9284f | |||
| 38d531894f | |||
| c434558378 | |||
| 777276d2e9 | |||
| b63ff54c19 | |||
| 96f1189fc6 | |||
| 2250389cc2 | |||
| 6a2b6ba75b | |||
| 0a43530852 |
+1
-1
@@ -157,8 +157,8 @@ build.tmp/
|
||||
build/hooks/
|
||||
build/temp/
|
||||
|
||||
/src/Umbraco.Web.UI.Client/src/common/**/build/temp/
|
||||
|
||||
|
||||
# eof
|
||||
/src/Umbraco.Web.UI.Client/TESTS-*.xml
|
||||
/src/ApiDocs/api/*
|
||||
|
||||
@@ -54,5 +54,6 @@
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Core\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -59,6 +59,8 @@
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Web\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Examine\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Examine" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
<!-- config transforms -->
|
||||
<!-- beware! config transforms not supported by PackageReference -->
|
||||
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
|
||||
<file src="tools\serilog.config.install.xdt" target="Content\config\serilog.config.install.xdt" />
|
||||
<file src="tools\ClientDependency.config.install.xdt" target="Content\config\ClientDependency.config.install.xdt" />
|
||||
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
|
||||
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" /> <!-- FIXME: Content\ !! and then... transform?! -->
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">>
|
||||
<appSettings>
|
||||
|
||||
<add key="serilog:using:File" value="Umbraco.Core" xdt:Transform="SetAttributes(value)" xdt:Locator="Match(key)"/>
|
||||
<add key="serilog:write-to:File.shared" xdt:Transform="Remove" xdt:Locator="Match(key)"/>
|
||||
|
||||
</appSettings>
|
||||
</configuration>
|
||||
+3
-55
@@ -11,11 +11,6 @@
|
||||
[Alias("loc")]
|
||||
[switch] $local = $false,
|
||||
|
||||
# enable docfx
|
||||
[Parameter(Mandatory=$false)]
|
||||
[Alias("doc")]
|
||||
[switch] $docfx = $false,
|
||||
|
||||
# keep the build directories, don't clear them
|
||||
[Parameter(Mandatory=$false)]
|
||||
[Alias("c")]
|
||||
@@ -36,7 +31,7 @@
|
||||
$ubuild = &"$PSScriptRoot\build-bootstrap.ps1"
|
||||
if (-not $?) { return }
|
||||
$ubuild.Boot($PSScriptRoot,
|
||||
@{ Local = $local; WithDocFx = $docfx },
|
||||
@{ Local = $local; },
|
||||
@{ Continue = $continue })
|
||||
if ($ubuild.OnError()) { return }
|
||||
|
||||
@@ -392,13 +387,13 @@
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.Core.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
-Symbols -SymbolPackageFormat snupkg -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmscore.log"
|
||||
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmscore.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Core." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.Web.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
-Symbols -SymbolPackageFormat snupkg -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmsweb.log"
|
||||
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmsweb.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Web." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.nuspec" `
|
||||
@@ -429,52 +424,6 @@
|
||||
Write-Host "Prepare Azure Gallery"
|
||||
$this.CopyFile("$($this.SolutionRoot)\build\Azure\azuregalleryrelease.ps1", $this.BuildOutput)
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("BuildCSharpDocs",
|
||||
{
|
||||
Write-Host "Building C# Documentation"
|
||||
|
||||
$src = "$($this.SolutionRoot)\src"
|
||||
$tmp = $this.BuildTemp
|
||||
$out = $this.BuildOutput
|
||||
$DocFxJson = Join-Path -Path $src "\ApiDocs\docfx.json"
|
||||
$DocFxSiteOutput = Join-Path -Path $tmp "\_site\*.*"
|
||||
|
||||
# run DocFx
|
||||
$DocFx = $this.BuildEnv.DocFx
|
||||
|
||||
& $DocFx metadata $DocFxJson
|
||||
& $DocFx build $DocFxJson
|
||||
|
||||
# zip it
|
||||
& $this.BuildEnv.Zip a -tzip -r "$out\csharp-docs.zip" $DocFxSiteOutput
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("BuildAngularDocs",
|
||||
{
|
||||
Write-Host "Building Angular Documentation"
|
||||
|
||||
$src = "$($this.SolutionRoot)\src"
|
||||
$out = $this.BuildOutput
|
||||
|
||||
# Check if the solution has been built
|
||||
if (!(Test-Path "$src\Umbraco.Web.UI.Client\node_modules")) {throw "Umbraco needs to be built before generating the Angular Docs"}
|
||||
|
||||
Push-Location "$src\Umbraco.Web.UI.Client"
|
||||
|
||||
"Generating the docs and waiting before executing the next commands"
|
||||
& gulp docs | Out-Null
|
||||
|
||||
Pop-Location
|
||||
|
||||
# change baseUrl
|
||||
$BaseUrl = "https://our.umbraco.com/apidocs/v8/ui/"
|
||||
$IndexPath = "$src\Umbraco.Web.UI.Client\docs\api\index.html"
|
||||
(Get-Content $IndexPath).replace('location.href.replace(rUrl, indexFile)', "`'" + $BaseUrl + "`'") | Set-Content $IndexPath
|
||||
|
||||
# zip it
|
||||
& $this.BuildEnv.Zip a -tzip -r "$out\ui-docs.zip" "$src\Umbraco.Web.UI.Client\docs\api\*.*"
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("Build",
|
||||
{
|
||||
@@ -507,7 +456,6 @@
|
||||
if ($this.OnError()) { return }
|
||||
$this.PostPackageHook()
|
||||
if ($this.OnError()) { return }
|
||||
|
||||
Write-Host "Done"
|
||||
})
|
||||
|
||||
|
||||
+24
-10
@@ -2,20 +2,21 @@
|
||||
"metadata": [
|
||||
{
|
||||
"src": [
|
||||
{
|
||||
"src": "../",
|
||||
{
|
||||
"files": [
|
||||
"Umbraco.Core/Umbraco.Core.csproj",
|
||||
"Umbraco.Web/Umbraco.Web.csproj"
|
||||
],
|
||||
"exclude": [
|
||||
"**/obj/**",
|
||||
"**/bin/**"
|
||||
]
|
||||
"**/bin/**",
|
||||
"_site/**"
|
||||
],
|
||||
"cwd": "../src"
|
||||
}
|
||||
],
|
||||
"dest": "api",
|
||||
"filter": "docfx.filter.yml"
|
||||
"dest": "../apidocs/api",
|
||||
"filter": "../apidocs/docfx.filter.yml"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
@@ -34,7 +35,19 @@
|
||||
"*.md"
|
||||
],
|
||||
"exclude": [
|
||||
"obj/**"
|
||||
"obj/**",
|
||||
"_site/**"
|
||||
]
|
||||
}
|
||||
],
|
||||
"resource": [
|
||||
{
|
||||
"files": [
|
||||
"images/**"
|
||||
],
|
||||
"exclude": [
|
||||
"obj/**",
|
||||
"_site/**"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -44,7 +57,8 @@
|
||||
"**.md"
|
||||
],
|
||||
"exclude": [
|
||||
"obj/**"
|
||||
"obj/**",
|
||||
"_site/**"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -53,9 +67,9 @@
|
||||
"_enableSearch": true,
|
||||
"_disableContribution": false
|
||||
},
|
||||
"dest": "../../build.tmp/_site",
|
||||
"dest": "_site",
|
||||
"template": [
|
||||
"default", "umbracotemplate"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,23 +70,7 @@ namespace Umbraco.Core.Composing
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<Type> PrepareComposerTypes()
|
||||
{
|
||||
var requirements = GetRequirements();
|
||||
|
||||
// only for debugging, this is verbose
|
||||
//_logger.Debug<Composers>(GetComposersReport(requirements));
|
||||
|
||||
var sortedComposerTypes = SortComposers(requirements);
|
||||
|
||||
// bit verbose but should help for troubleshooting
|
||||
//var text = "Ordered Composers: " + Environment.NewLine + string.Join(Environment.NewLine, sortedComposerTypes) + Environment.NewLine;
|
||||
_logger.Debug<Composers>("Ordered Composers: {SortedComposerTypes}", sortedComposerTypes);
|
||||
|
||||
return sortedComposerTypes;
|
||||
}
|
||||
|
||||
internal Dictionary<Type, List<Type>> GetRequirements(bool throwOnMissing = true)
|
||||
private IEnumerable<Type> PrepareComposerTypes()
|
||||
{
|
||||
// create a list, remove those that cannot be enabled due to runtime level
|
||||
var composerTypeList = _composerTypes
|
||||
@@ -105,69 +89,25 @@ namespace Umbraco.Core.Composing
|
||||
// enable or disable composers
|
||||
EnableDisableComposers(composerTypeList);
|
||||
|
||||
void GatherInterfaces<TAttribute>(Type type, Func<TAttribute, Type> getTypeInAttribute, HashSet<Type> iset, List<Type> set2)
|
||||
where TAttribute : Attribute
|
||||
{
|
||||
foreach (var attribute in type.GetCustomAttributes<TAttribute>())
|
||||
{
|
||||
var typeInAttribute = getTypeInAttribute(attribute);
|
||||
if (typeInAttribute != null && // if the attribute references a type ...
|
||||
typeInAttribute.IsInterface && // ... which is an interface ...
|
||||
typeof(IComposer).IsAssignableFrom(typeInAttribute) && // ... which implements IComposer ...
|
||||
!iset.Contains(typeInAttribute)) // ... which is not already in the list
|
||||
{
|
||||
// add it to the new list
|
||||
iset.Add(typeInAttribute);
|
||||
set2.Add(typeInAttribute);
|
||||
|
||||
// add all its interfaces implementing IComposer
|
||||
foreach (var i in typeInAttribute.GetInterfaces().Where(x => typeof(IComposer).IsAssignableFrom(x)))
|
||||
{
|
||||
iset.Add(i);
|
||||
set2.Add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gather interfaces too
|
||||
var interfaces = new HashSet<Type>(composerTypeList.SelectMany(x => x.GetInterfaces().Where(y => typeof(IComposer).IsAssignableFrom(y))));
|
||||
composerTypeList.AddRange(interfaces);
|
||||
var list1 = composerTypeList;
|
||||
while (list1.Count > 0)
|
||||
{
|
||||
var list2 = new List<Type>();
|
||||
foreach (var t in list1)
|
||||
{
|
||||
GatherInterfaces<ComposeAfterAttribute>(t, a => a.RequiredType, interfaces, list2);
|
||||
GatherInterfaces<ComposeBeforeAttribute>(t, a => a.RequiringType, interfaces, list2);
|
||||
}
|
||||
composerTypeList.AddRange(list2);
|
||||
list1 = list2;
|
||||
}
|
||||
|
||||
// sort the composers according to their dependencies
|
||||
var requirements = new Dictionary<Type, List<Type>>();
|
||||
foreach (var type in composerTypeList)
|
||||
requirements[type] = null;
|
||||
foreach (var type in composerTypeList) requirements[type] = null;
|
||||
foreach (var type in composerTypeList)
|
||||
{
|
||||
GatherRequirementsFromAfterAttribute(type, composerTypeList, requirements, throwOnMissing);
|
||||
GatherRequirementsFromBeforeAttribute(type, composerTypeList, requirements);
|
||||
GatherRequirementsFromRequireAttribute(type, composerTypeList, requirements);
|
||||
GatherRequirementsFromRequiredByAttribute(type, composerTypeList, requirements);
|
||||
}
|
||||
|
||||
return requirements;
|
||||
}
|
||||
// only for debugging, this is verbose
|
||||
//_logger.Debug<Composers>(GetComposersReport(requirements));
|
||||
|
||||
internal IEnumerable<Type> SortComposers(Dictionary<Type, List<Type>> requirements)
|
||||
{
|
||||
// sort composers
|
||||
var graph = new TopoGraph<Type, KeyValuePair<Type, List<Type>>>(kvp => kvp.Key, kvp => kvp.Value);
|
||||
graph.AddItems(requirements);
|
||||
List<Type> sortedComposerTypes;
|
||||
try
|
||||
{
|
||||
sortedComposerTypes = graph.GetSortedItems().Select(x => x.Key).Where(x => !x.IsInterface).ToList();
|
||||
sortedComposerTypes = graph.GetSortedItems().Select(x => x.Key).ToList();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -177,37 +117,40 @@ namespace Umbraco.Core.Composing
|
||||
throw;
|
||||
}
|
||||
|
||||
// bit verbose but should help for troubleshooting
|
||||
//var text = "Ordered Composers: " + Environment.NewLine + string.Join(Environment.NewLine, sortedComposerTypes) + Environment.NewLine;
|
||||
_logger.Debug<Composers>("Ordered Composers: {SortedComposerTypes}", sortedComposerTypes);
|
||||
|
||||
return sortedComposerTypes;
|
||||
}
|
||||
|
||||
internal static string GetComposersReport(Dictionary<Type, List<Type>> requirements)
|
||||
private static string GetComposersReport(Dictionary<Type, List<Type>> requirements)
|
||||
{
|
||||
var text = new StringBuilder();
|
||||
text.AppendLine("Composers & Dependencies:");
|
||||
text.AppendLine(" < compose before");
|
||||
text.AppendLine(" > compose after");
|
||||
text.AppendLine(" : implements");
|
||||
text.AppendLine(" = depends");
|
||||
text.AppendLine();
|
||||
|
||||
bool HasReq(IEnumerable<Type> types, Type type)
|
||||
=> types.Any(x => type.IsAssignableFrom(x) && !x.IsInterface);
|
||||
|
||||
foreach (var kvp in requirements)
|
||||
{
|
||||
var type = kvp.Key;
|
||||
|
||||
text.AppendLine(type.FullName);
|
||||
foreach (var attribute in type.GetCustomAttributes<ComposeAfterAttribute>())
|
||||
{
|
||||
var weak = !(attribute.RequiredType.IsInterface ? attribute.Weak == false : attribute.Weak != true);
|
||||
text.AppendLine(" > " + attribute.RequiredType +
|
||||
(weak ? " (weak" : " (strong") + (HasReq(requirements.Keys, attribute.RequiredType) ? ", found" : ", missing") + ")");
|
||||
}
|
||||
text.AppendLine(" -> " + attribute.RequiredType + (attribute.Weak.HasValue
|
||||
? (attribute.Weak.Value ? " (weak)" : (" (strong" + (requirements.ContainsKey(attribute.RequiredType) ? ", missing" : "") + ")"))
|
||||
: ""));
|
||||
foreach (var attribute in type.GetCustomAttributes<ComposeBeforeAttribute>())
|
||||
text.AppendLine(" < " + attribute.RequiringType);
|
||||
text.AppendLine(" -< " + attribute.RequiringType);
|
||||
foreach (var i in type.GetInterfaces())
|
||||
{
|
||||
text.AppendLine(" : " + i.FullName);
|
||||
foreach (var attribute in i.GetCustomAttributes<ComposeAfterAttribute>())
|
||||
text.AppendLine(" -> " + attribute.RequiredType + (attribute.Weak.HasValue
|
||||
? (attribute.Weak.Value ? " (weak)" : (" (strong" + (requirements.ContainsKey(attribute.RequiredType) ? ", missing" : "") + ")"))
|
||||
: ""));
|
||||
foreach (var attribute in i.GetCustomAttributes<ComposeBeforeAttribute>())
|
||||
text.AppendLine(" -< " + attribute.RequiringType);
|
||||
}
|
||||
if (kvp.Value != null)
|
||||
foreach (var t in kvp.Value)
|
||||
text.AppendLine(" = " + t);
|
||||
@@ -278,16 +221,16 @@ namespace Umbraco.Core.Composing
|
||||
types.Remove(kvp.Key);
|
||||
}
|
||||
|
||||
private static void GatherRequirementsFromAfterAttribute(Type type, ICollection<Type> types, IDictionary<Type, List<Type>> requirements, bool throwOnMissing = true)
|
||||
private static void GatherRequirementsFromRequireAttribute(Type type, ICollection<Type> types, IDictionary<Type, List<Type>> requirements)
|
||||
{
|
||||
// get 'require' attributes
|
||||
// these attributes are *not* inherited because we want to "custom-inherit" for interfaces only
|
||||
var afterAttributes = type
|
||||
var requireAttributes = type
|
||||
.GetInterfaces().SelectMany(x => x.GetCustomAttributes<ComposeAfterAttribute>()) // those marking interfaces
|
||||
.Concat(type.GetCustomAttributes<ComposeAfterAttribute>()); // those marking the composer
|
||||
|
||||
// what happens in case of conflicting attributes (different strong/weak for same type) is not specified.
|
||||
foreach (var attr in afterAttributes)
|
||||
foreach (var attr in requireAttributes)
|
||||
{
|
||||
if (attr.RequiredType == type) continue; // ignore self-requirements (+ exclude in implems, below)
|
||||
|
||||
@@ -295,13 +238,13 @@ namespace Umbraco.Core.Composing
|
||||
// unless strong, and then require at least one enabled composer implementing that interface
|
||||
if (attr.RequiredType.IsInterface)
|
||||
{
|
||||
var implems = types.Where(x => x != type && attr.RequiredType.IsAssignableFrom(x) && !x.IsInterface).ToList();
|
||||
var implems = types.Where(x => x != type && attr.RequiredType.IsAssignableFrom(x)).ToList();
|
||||
if (implems.Count > 0)
|
||||
{
|
||||
if (requirements[type] == null) requirements[type] = new List<Type>();
|
||||
requirements[type].AddRange(implems);
|
||||
}
|
||||
else if (attr.Weak == false && throwOnMissing) // if explicitly set to !weak, is strong, else is weak
|
||||
else if (attr.Weak == false) // if explicitly set to !weak, is strong, else is weak
|
||||
throw new Exception($"Broken composer dependency: {type.FullName} -> {attr.RequiredType.FullName}.");
|
||||
}
|
||||
// requiring a class = require that the composer is enabled
|
||||
@@ -313,28 +256,28 @@ namespace Umbraco.Core.Composing
|
||||
if (requirements[type] == null) requirements[type] = new List<Type>();
|
||||
requirements[type].Add(attr.RequiredType);
|
||||
}
|
||||
else if (attr.Weak != true && throwOnMissing) // if not explicitly set to weak, is strong
|
||||
else if (attr.Weak != true) // if not explicitly set to weak, is strong
|
||||
throw new Exception($"Broken composer dependency: {type.FullName} -> {attr.RequiredType.FullName}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void GatherRequirementsFromBeforeAttribute(Type type, ICollection<Type> types, IDictionary<Type, List<Type>> requirements)
|
||||
private static void GatherRequirementsFromRequiredByAttribute(Type type, ICollection<Type> types, IDictionary<Type, List<Type>> requirements)
|
||||
{
|
||||
// get 'required' attributes
|
||||
// these attributes are *not* inherited because we want to "custom-inherit" for interfaces only
|
||||
var beforeAttributes = type
|
||||
var requiredAttributes = type
|
||||
.GetInterfaces().SelectMany(x => x.GetCustomAttributes<ComposeBeforeAttribute>()) // those marking interfaces
|
||||
.Concat(type.GetCustomAttributes<ComposeBeforeAttribute>()); // those marking the composer
|
||||
|
||||
foreach (var attr in beforeAttributes)
|
||||
foreach (var attr in requiredAttributes)
|
||||
{
|
||||
if (attr.RequiringType == type) continue; // ignore self-requirements (+ exclude in implems, below)
|
||||
|
||||
// required by an interface = by any enabled composer implementing this that interface
|
||||
if (attr.RequiringType.IsInterface)
|
||||
{
|
||||
var implems = types.Where(x => x != type && attr.RequiringType.IsAssignableFrom(x) && !x.IsInterface).ToList();
|
||||
var implems = types.Where(x => x != type && attr.RequiringType.IsAssignableFrom(x)).ToList();
|
||||
foreach (var implem in implems)
|
||||
{
|
||||
if (requirements[implem] == null) requirements[implem] = new List<Type>();
|
||||
|
||||
@@ -6,50 +6,30 @@ namespace Umbraco.Core.Composing
|
||||
/// <summary>
|
||||
/// Provides a base class for collections of types.
|
||||
/// </summary>
|
||||
public abstract class TypeCollectionBuilderBase<TBuilder, TCollection, TConstraint> : ICollectionBuilder<TCollection, Type>
|
||||
where TBuilder : TypeCollectionBuilderBase<TBuilder, TCollection, TConstraint>
|
||||
public abstract class TypeCollectionBuilderBase<TCollection, TConstraint> : ICollectionBuilder<TCollection, Type>
|
||||
where TCollection : class, IBuilderCollection<Type>
|
||||
{
|
||||
private readonly HashSet<Type> _types = new HashSet<Type>();
|
||||
|
||||
protected abstract TBuilder This { get; }
|
||||
|
||||
private static Type Validate(Type type, string action)
|
||||
private Type Validate(Type type, string action)
|
||||
{
|
||||
if (!typeof(TConstraint).IsAssignableFrom(type))
|
||||
throw new InvalidOperationException($"Cannot {action} type {type.FullName} as it does not inherit from/implement {typeof(TConstraint).FullName}.");
|
||||
return type;
|
||||
}
|
||||
|
||||
public TBuilder Add(Type type)
|
||||
{
|
||||
_types.Add(Validate(type, "add"));
|
||||
return This;
|
||||
}
|
||||
public void Add(Type type) => _types.Add(Validate(type, "add"));
|
||||
|
||||
public TBuilder Add<T>()
|
||||
{
|
||||
Add(typeof(T));
|
||||
return This;
|
||||
}
|
||||
public void Add<T>() => Add(typeof(T));
|
||||
|
||||
public TBuilder Add(IEnumerable<Type> types)
|
||||
public void Add(IEnumerable<Type> types)
|
||||
{
|
||||
foreach (var type in types) Add(type);
|
||||
return This;
|
||||
}
|
||||
|
||||
public TBuilder Remove(Type type)
|
||||
{
|
||||
_types.Remove(Validate(type, "remove"));
|
||||
return This;
|
||||
}
|
||||
public void Remove(Type type) => _types.Remove(Validate(type, "remove"));
|
||||
|
||||
public TBuilder Remove<T>()
|
||||
{
|
||||
Remove(typeof(T));
|
||||
return This;
|
||||
}
|
||||
public void Remove<T>() => Remove(typeof(T));
|
||||
|
||||
public TCollection CreateCollection(IFactory factory)
|
||||
{
|
||||
|
||||
@@ -315,7 +315,7 @@ namespace Umbraco.Core.Configuration
|
||||
var hash = hashString.GenerateHash();
|
||||
var siteTemp = System.IO.Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", hash);
|
||||
|
||||
return _localTempPath = siteTemp;
|
||||
return _localTempPath = System.IO.Path.Combine(siteTemp, "umbraco.config");
|
||||
|
||||
//case LocalTempStorage.Default:
|
||||
//case LocalTempStorage.Unknown:
|
||||
|
||||
@@ -10,18 +10,6 @@ namespace Umbraco.Core
|
||||
///</summary>
|
||||
public static class EnumerableExtensions
|
||||
{
|
||||
internal static bool HasDuplicates<T>(this IEnumerable<T> items, bool includeNull)
|
||||
{
|
||||
var hs = new HashSet<T>();
|
||||
foreach (var item in items)
|
||||
{
|
||||
if ((item != null || includeNull) && !hs.Add(item))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Wraps this object instance into an IEnumerable{T} consisting of a single item.
|
||||
/// </summary>
|
||||
@@ -112,7 +100,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if all items in the other collection exist in this collection
|
||||
/// </summary>
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Serilog;
|
||||
using Serilog.Configuration;
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
using Serilog.Formatting;
|
||||
using Serilog.Formatting.Compact;
|
||||
using Umbraco.Core.Logging.Serilog.Enrichers;
|
||||
|
||||
@@ -13,7 +9,6 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
{
|
||||
public static class LoggerConfigExtensions
|
||||
{
|
||||
private const string AppDomainId = "AppDomainId";
|
||||
/// <summary>
|
||||
/// This configures Serilog with some defaults
|
||||
/// Such as adding ProcessID, Thread, AppDomain etc
|
||||
@@ -33,14 +28,14 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
.Enrich.WithProcessId()
|
||||
.Enrich.WithProcessName()
|
||||
.Enrich.WithThreadId()
|
||||
.Enrich.WithProperty(AppDomainId, AppDomain.CurrentDomain.Id)
|
||||
.Enrich.WithProperty("AppDomainId", AppDomain.CurrentDomain.Id)
|
||||
.Enrich.WithProperty("AppDomainAppId", HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty))
|
||||
.Enrich.WithProperty("MachineName", Environment.MachineName)
|
||||
.Enrich.With<Log4NetLevelMapperEnricher>()
|
||||
.Enrich.With<HttpSessionIdEnricher>()
|
||||
.Enrich.With<HttpRequestNumberEnricher>()
|
||||
.Enrich.With<HttpRequestIdEnricher>();
|
||||
|
||||
|
||||
return logConfig;
|
||||
}
|
||||
|
||||
@@ -55,51 +50,15 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
//Main .txt logfile - in similar format to older Log4Net output
|
||||
//Ends with ..txt as Date is inserted before file extension substring
|
||||
logConfig.WriteTo.File($@"{AppDomain.CurrentDomain.BaseDirectory}\App_Data\Logs\UmbracoTraceLog.{Environment.MachineName}..txt",
|
||||
shared: true,
|
||||
rollingInterval: RollingInterval.Day,
|
||||
restrictedToMinimumLevel: minimumLevel,
|
||||
retainedFileCountLimit: null, //Setting to null means we keep all files - default is 31 days
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss,fff} [P{ProcessId}/D{AppDomainId}/T{ThreadId}] {Log4NetLevel} {SourceContext} - {Message:lj}{NewLine}{Exception}");
|
||||
shared: true,
|
||||
rollingInterval: RollingInterval.Day,
|
||||
restrictedToMinimumLevel: minimumLevel,
|
||||
retainedFileCountLimit: null, //Setting to null means we keep all files - default is 31 days
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss,fff} [P{ProcessId}/D{AppDomainId}/T{ThreadId}] {Log4NetLevel} {SourceContext} - {Message:lj}{NewLine}{Exception}");
|
||||
|
||||
return logConfig;
|
||||
}
|
||||
|
||||
|
||||
/// <remarks>
|
||||
/// Used in config - If renamed or moved to other assembly the config file also has be updated.
|
||||
/// </remarks>
|
||||
public static LoggerConfiguration File(this LoggerSinkConfiguration configuration, ITextFormatter formatter,
|
||||
string path,
|
||||
LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose,
|
||||
LoggingLevelSwitch levelSwitch = null,
|
||||
long? fileSizeLimitBytes = 1073741824,
|
||||
TimeSpan? flushToDiskInterval = null,
|
||||
RollingInterval rollingInterval = RollingInterval.Infinite,
|
||||
bool rollOnFileSizeLimit = false,
|
||||
int? retainedFileCountLimit = 31,
|
||||
Encoding encoding = null
|
||||
)
|
||||
{
|
||||
return configuration.Async(
|
||||
asyncConfiguration => asyncConfiguration.Map(AppDomainId, (_,mapConfiguration) =>
|
||||
mapConfiguration.File(
|
||||
formatter,
|
||||
path,
|
||||
restrictedToMinimumLevel,
|
||||
fileSizeLimitBytes,
|
||||
levelSwitch,
|
||||
buffered:true,
|
||||
shared:false,
|
||||
flushToDiskInterval,
|
||||
rollingInterval,
|
||||
rollOnFileSizeLimit,
|
||||
retainedFileCountLimit,
|
||||
encoding),
|
||||
sinkMapCountLimit:0)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Outputs a CLEF format JSON log at /App_Data/Logs/
|
||||
/// </summary>
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
///<summary>
|
||||
/// Implements <see cref="ILogger"/> on top of Serilog.
|
||||
///</summary>
|
||||
public class SerilogLogger : ILogger, IDisposable
|
||||
public class SerilogLogger : ILogger
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize a new instance of the <see cref="SerilogLogger"/> class with a configuration file.
|
||||
@@ -271,10 +271,5 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
{
|
||||
LoggerFor(reporting).Verbose(messageTemplate, propertyValues);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
for (var day = startDate.Date; day.Date <= endDate.Date; day = day.AddDays(1))
|
||||
{
|
||||
//Filename ending to search for (As could be multiple)
|
||||
var filesToFind = GetSearchPattern(day);
|
||||
var filesToFind = $"*{day:yyyyMMdd}.json";
|
||||
|
||||
var filesForCurrentDay = Directory.GetFiles(logDirectory, filesToFind);
|
||||
|
||||
@@ -52,11 +52,6 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
return logSizeAsMegabytes <= FileSizeCap;
|
||||
}
|
||||
|
||||
private string GetSearchPattern(DateTime day)
|
||||
{
|
||||
return $"*{day:yyyyMMdd}*.json";
|
||||
}
|
||||
|
||||
protected override IReadOnlyList<LogEvent> GetLogs(DateTimeOffset startDate, DateTimeOffset endDate, ILogFilter filter, int skip, int take)
|
||||
{
|
||||
var logs = new List<LogEvent>();
|
||||
@@ -71,7 +66,7 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
for (var day = startDate.Date; day.Date <= endDate.Date; day = day.AddDays(1))
|
||||
{
|
||||
//Filename ending to search for (As could be multiple)
|
||||
var filesToFind = GetSearchPattern(day);
|
||||
var filesToFind = $"*{day:yyyyMMdd}.json";
|
||||
|
||||
var filesForCurrentDay = Directory.GetFiles(logDirectory, filesToFind);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -30,16 +29,11 @@ namespace Umbraco.Core.Mapping
|
||||
/// </remarks>
|
||||
public class UmbracoMapper
|
||||
{
|
||||
// note
|
||||
//
|
||||
// the outer dictionary *can* be modified, see GetCtor and GetMap, hence have to be ConcurrentDictionary
|
||||
// the inner dictionaries are never modified and therefore can be simple Dictionary
|
||||
private readonly Dictionary<Type, Dictionary<Type, Func<object, MapperContext, object>>> _ctors
|
||||
= new Dictionary<Type, Dictionary<Type, Func<object, MapperContext, object>>>();
|
||||
|
||||
private readonly ConcurrentDictionary<Type, Dictionary<Type, Func<object, MapperContext, object>>> _ctors
|
||||
= new ConcurrentDictionary<Type, Dictionary<Type, Func<object, MapperContext, object>>>();
|
||||
|
||||
private readonly ConcurrentDictionary<Type, Dictionary<Type, Action<object, object, MapperContext>>> _maps
|
||||
= new ConcurrentDictionary<Type, Dictionary<Type, Action<object, object, MapperContext>>>();
|
||||
private readonly Dictionary<Type, Dictionary<Type, Action<object, object, MapperContext>>> _maps
|
||||
= new Dictionary<Type, Dictionary<Type, Action<object, object, MapperContext>>>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoMapper"/> class.
|
||||
@@ -107,12 +101,16 @@ namespace Umbraco.Core.Mapping
|
||||
|
||||
private Dictionary<Type, Func<object, MapperContext, object>> DefineCtors(Type sourceType)
|
||||
{
|
||||
return _ctors.GetOrAdd(sourceType, _ => new Dictionary<Type, Func<object, MapperContext, object>>());
|
||||
if (!_ctors.TryGetValue(sourceType, out var sourceCtor))
|
||||
sourceCtor = _ctors[sourceType] = new Dictionary<Type, Func<object, MapperContext, object>>();
|
||||
return sourceCtor;
|
||||
}
|
||||
|
||||
private Dictionary<Type, Action<object, object, MapperContext>> DefineMaps(Type sourceType)
|
||||
{
|
||||
return _maps.GetOrAdd(sourceType, _ => new Dictionary<Type, Action<object, object, MapperContext>>());
|
||||
if (!_maps.TryGetValue(sourceType, out var sourceMap))
|
||||
sourceMap = _maps[sourceType] = new Dictionary<Type, Action<object, object, MapperContext>>();
|
||||
return sourceMap;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -328,8 +326,6 @@ namespace Umbraco.Core.Mapping
|
||||
if (_ctors.TryGetValue(sourceType, out var sourceCtor) && sourceCtor.TryGetValue(targetType, out var ctor))
|
||||
return ctor;
|
||||
|
||||
// we *may* run this more than once but it does not matter
|
||||
|
||||
ctor = null;
|
||||
foreach (var (stype, sctors) in _ctors)
|
||||
{
|
||||
@@ -351,8 +347,6 @@ namespace Umbraco.Core.Mapping
|
||||
if (_maps.TryGetValue(sourceType, out var sourceMap) && sourceMap.TryGetValue(targetType, out var map))
|
||||
return map;
|
||||
|
||||
// we *may* run this more than once but it does not matter
|
||||
|
||||
map = null;
|
||||
foreach (var (stype, smap) in _maps)
|
||||
{
|
||||
|
||||
@@ -83,25 +83,17 @@ namespace Umbraco.Core.Migrations.Expressions.Create
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey() => PrimaryKey(true);
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey(bool clustered)
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey()
|
||||
{
|
||||
var expression = new CreateConstraintExpression(_context, ConstraintType.PrimaryKey);
|
||||
expression.Constraint.IsPrimaryKeyClustered = clustered;
|
||||
return new CreateConstraintBuilder(expression);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey(string primaryKeyName) => PrimaryKey(primaryKeyName, true);
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey(string primaryKeyName, bool clustered)
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey(string primaryKeyName)
|
||||
{
|
||||
var expression = new CreateConstraintExpression(_context, ConstraintType.PrimaryKey);
|
||||
expression.Constraint.ConstraintName = primaryKeyName;
|
||||
expression.Constraint.IsPrimaryKeyClustered = clustered;
|
||||
return new CreateConstraintBuilder(expression);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Migrations.Expressions.Create.Expressions
|
||||
var constraintType = (Constraint.IsPrimaryKeyConstraint) ? "PRIMARY KEY" : "UNIQUE";
|
||||
|
||||
if (Constraint.IsPrimaryKeyConstraint && SqlSyntax.SupportsClustered())
|
||||
constraintType += Constraint.IsPrimaryKeyClustered ? " CLUSTERED" : " NONCLUSTERED";
|
||||
constraintType += " CLUSTERED";
|
||||
|
||||
if (Constraint.IsNonUniqueConstraint)
|
||||
constraintType = string.Empty;
|
||||
|
||||
@@ -68,16 +68,6 @@ namespace Umbraco.Core.Migrations.Expressions.Create
|
||||
/// </summary>
|
||||
ICreateConstraintOnTableBuilder PrimaryKey(string primaryKeyName);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a Create Primary Key expression.
|
||||
/// </summary>
|
||||
ICreateConstraintOnTableBuilder PrimaryKey(bool clustered);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a Create Primary Key expression.
|
||||
/// </summary>
|
||||
ICreateConstraintOnTableBuilder PrimaryKey(string primaryKeyName, bool clustered);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a Create Unique Constraint expression.
|
||||
/// </summary>
|
||||
|
||||
@@ -226,8 +226,6 @@ namespace Umbraco.Core.Migrations.Install
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 32, UniqueId = 32.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLockoutDate, Name = Constants.Conventions.Member.LastLockoutDateLabel, SortOrder = 4, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 33, UniqueId = 33.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLoginDate, Name = Constants.Conventions.Member.LastLoginDateLabel, SortOrder = 5, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 34, UniqueId = 34.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastPasswordChangeDate, Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, SortOrder = 6, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 35, UniqueId = 35.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = null, Alias = Constants.Conventions.Member.PasswordQuestion, Name = Constants.Conventions.Member.PasswordQuestionLabel, SortOrder = 7, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 36, UniqueId = 36.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = null, Alias = Constants.Conventions.Member.PasswordAnswer, Name = Constants.Conventions.Member.PasswordAnswerLabel, SortOrder = 8, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing });
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ using Umbraco.Core.Migrations.Upgrade.V_7_12_0;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_7_14_0;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_0_0;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_0_1;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_1_0;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade
|
||||
{
|
||||
@@ -140,7 +139,6 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
To<RenameLabelAndRichTextPropertyEditorAliases>("{E0CBE54D-A84F-4A8F-9B13-900945FD7ED9}");
|
||||
To<MergeDateAndDateTimePropertyEditor>("{78BAF571-90D0-4D28-8175-EF96316DA789}");
|
||||
To<ChangeNuCacheJsonFormat>("{80C0A0CB-0DD5-4573-B000-C4B7C313C70D}");
|
||||
To<ConvertTinyMceAndGridMediaUrlsToLocalLink>("{B69B6E8C-A769-4044-A27E-4A4E18D1645A}");
|
||||
|
||||
//FINAL
|
||||
|
||||
|
||||
@@ -79,8 +79,7 @@ HAVING COUNT(v2.id) <> 1").Any())
|
||||
// transform column versionId from guid to integer (contentVersion.id)
|
||||
if (ColumnType(PreTables.PropertyData, "versionId") == "uniqueidentifier")
|
||||
{
|
||||
Alter.Table(PreTables.PropertyData).AddColumn("versionId2").AsInt32().Nullable().Do();
|
||||
|
||||
Database.Execute($"ALTER TABLE {PreTables.PropertyData} ADD COLUMN versionId2 INT NULL;");
|
||||
// SQLCE does not support UPDATE...FROM
|
||||
var temp = Database.Fetch<dynamic>($"SELECT id, versionId FROM {PreTables.ContentVersion}");
|
||||
foreach (var t in temp)
|
||||
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Migrations.PostMigrations;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0
|
||||
{
|
||||
public class ConvertTinyMceAndGridMediaUrlsToLocalLink : MigrationBase
|
||||
{
|
||||
private readonly IMediaService _mediaService;
|
||||
|
||||
public ConvertTinyMceAndGridMediaUrlsToLocalLink(IMigrationContext context, IMediaService mediaService) : base(context)
|
||||
{
|
||||
_mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService));
|
||||
}
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
var mediaLinkPattern = new Regex(
|
||||
@"(<a[^>]*href="")(\/ media[^""\?]*)([^>]*>)",
|
||||
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
|
||||
var sqlPropertyData = Sql()
|
||||
.Select<PropertyDataDto>(x => x.Id, x => x.TextValue)
|
||||
.AndSelect<DataTypeDto>(x => x.EditorAlias)
|
||||
.From<PropertyDataDto>()
|
||||
.InnerJoin<PropertyTypeDto>().On<PropertyDataDto, PropertyTypeDto>((left, right) => left.PropertyTypeId == right.Id)
|
||||
.InnerJoin<DataTypeDto>().On<PropertyTypeDto, DataTypeDto>((left, right) => left.DataTypeId == right.NodeId)
|
||||
.Where<DataTypeDto>(x =>
|
||||
x.EditorAlias == Constants.PropertyEditors.Aliases.TinyMce ||
|
||||
x.EditorAlias == Constants.PropertyEditors.Aliases.Grid);
|
||||
|
||||
var properties = Database.Fetch<PropertyDataDto>(sqlPropertyData);
|
||||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var value = property.TextValue;
|
||||
if (string.IsNullOrWhiteSpace(value)) continue;
|
||||
|
||||
if (property.PropertyTypeDto.DataTypeDto.EditorAlias == Constants.PropertyEditors.Aliases.Grid)
|
||||
{
|
||||
var obj = JsonConvert.DeserializeObject<JObject>(value);
|
||||
var allControls = obj.SelectTokens("$.sections..rows..areas..controls");
|
||||
|
||||
foreach (var control in allControls.SelectMany(c => c))
|
||||
{
|
||||
var controlValue = control["value"];
|
||||
if (controlValue.Type == JTokenType.String)
|
||||
{
|
||||
control["value"] = UpdateMediaUrls(mediaLinkPattern, controlValue.Value<string>());
|
||||
}
|
||||
}
|
||||
|
||||
property.TextValue = JsonConvert.SerializeObject(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
property.TextValue = UpdateMediaUrls(mediaLinkPattern, value);
|
||||
}
|
||||
|
||||
Database.Update(property, x => x.TextValue);
|
||||
}
|
||||
|
||||
Context.AddPostMigration<RebuildPublishedSnapshot>();
|
||||
}
|
||||
|
||||
private string UpdateMediaUrls(Regex mediaLinkPattern, string value)
|
||||
{
|
||||
return mediaLinkPattern.Replace(value, match =>
|
||||
{
|
||||
// match groups:
|
||||
// - 1 = from the beginning of the a tag until href attribute value begins
|
||||
// - 2 = the href attribute value excluding the querystring (if present)
|
||||
// - 3 = anything after group 2 until the a tag is closed
|
||||
var href = match.Groups[2].Value;
|
||||
|
||||
var media = _mediaService.GetMediaByPath(href);
|
||||
return media == null
|
||||
? match.Value
|
||||
: $"{match.Groups[1].Value}/{{localLink:{media.GetUdi()}}}{match.Groups[3].Value}";
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,21 +95,6 @@ namespace Umbraco.Core.Models
|
||||
|
||||
protected void PropertyTypesChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
//enable this to detect duplicate property aliases. We do want this, however making this change in a
|
||||
//patch release might be a little dangerous
|
||||
|
||||
////detect if there are any duplicate aliases - this cannot be allowed
|
||||
//if (e.Action == NotifyCollectionChangedAction.Add
|
||||
// || e.Action == NotifyCollectionChangedAction.Replace)
|
||||
//{
|
||||
// var allAliases = _noGroupPropertyTypes.Concat(PropertyGroups.SelectMany(x => x.PropertyTypes)).Select(x => x.Alias);
|
||||
// if (allAliases.HasDuplicates(false))
|
||||
// {
|
||||
// var newAliases = string.Join(", ", e.NewItems.Cast<PropertyType>().Select(x => x.Alias));
|
||||
// throw new InvalidOperationException($"Other property types already exist with the aliases: {newAliases}");
|
||||
// }
|
||||
//}
|
||||
|
||||
OnPropertyChanged(nameof(PropertyTypes));
|
||||
}
|
||||
|
||||
@@ -403,16 +388,15 @@ namespace Umbraco.Core.Models
|
||||
var group = PropertyGroups[propertyGroupName];
|
||||
if (group == null) return;
|
||||
|
||||
// first remove the group
|
||||
PropertyGroups.RemoveItem(propertyGroupName);
|
||||
|
||||
// Then re-assign the group's properties to no group
|
||||
// re-assign the group's properties to no group
|
||||
foreach (var property in group.PropertyTypes)
|
||||
{
|
||||
property.PropertyGroupId = null;
|
||||
_noGroupPropertyTypes.Add(property);
|
||||
}
|
||||
|
||||
// actually remove the group
|
||||
PropertyGroups.RemoveItem(propertyGroupName);
|
||||
OnPropertyChanged(nameof(PropertyGroups));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Models
|
||||
public class PropertyCollection : KeyedCollection<string, Property>, INotifyCollectionChanged, IDeepCloneable
|
||||
{
|
||||
private readonly object _addLocker = new object();
|
||||
|
||||
internal Action OnAdd;
|
||||
internal Func<Property, bool> AdditionValidator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -49,12 +49,10 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
internal void Reset(IEnumerable<Property> properties)
|
||||
{
|
||||
//collection events will be raised in each of these calls
|
||||
Clear();
|
||||
|
||||
//collection events will be raised in each of these calls
|
||||
foreach (var property in properties)
|
||||
Add(property);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -62,9 +60,8 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
protected override void SetItem(int index, Property property)
|
||||
{
|
||||
var oldItem = index >= 0 ? this[index] : property;
|
||||
base.SetItem(index, property);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, property, oldItem));
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, property, index));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -123,8 +120,10 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
//collection events will be raised in InsertItem with Add
|
||||
base.Add(property);
|
||||
|
||||
OnAdd?.Invoke();
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, property));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
private readonly ReaderWriterLockSlim _addLocker = new ReaderWriterLockSlim();
|
||||
|
||||
// TODO: this doesn't seem to be used anywhere
|
||||
internal Action OnAdd;
|
||||
|
||||
internal PropertyGroupCollection()
|
||||
{ }
|
||||
|
||||
@@ -34,19 +37,16 @@ namespace Umbraco.Core.Models
|
||||
/// <remarks></remarks>
|
||||
internal void Reset(IEnumerable<PropertyGroup> groups)
|
||||
{
|
||||
//collection events will be raised in each of these calls
|
||||
Clear();
|
||||
|
||||
//collection events will be raised in each of these calls
|
||||
foreach (var group in groups)
|
||||
Add(group);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
protected override void SetItem(int index, PropertyGroup item)
|
||||
{
|
||||
var oldItem = index >= 0 ? this[index] : item;
|
||||
base.SetItem(index, item);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, oldItem));
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
|
||||
}
|
||||
|
||||
protected override void RemoveItem(int index)
|
||||
@@ -84,7 +84,6 @@ namespace Umbraco.Core.Models
|
||||
if (keyExists)
|
||||
throw new Exception($"Naming conflict: Changing the name of PropertyGroup '{item.Name}' would result in duplicates");
|
||||
|
||||
//collection events will be raised in SetItem
|
||||
SetItem(IndexOfKey(item.Id), item);
|
||||
return;
|
||||
}
|
||||
@@ -97,14 +96,16 @@ namespace Umbraco.Core.Models
|
||||
var exists = Contains(key);
|
||||
if (exists)
|
||||
{
|
||||
//collection events will be raised in SetItem
|
||||
SetItem(IndexOfKey(key), item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
//collection events will be raised in InsertItem
|
||||
|
||||
base.Add(item);
|
||||
OnAdd?.Invoke();
|
||||
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -19,6 +19,9 @@ namespace Umbraco.Core.Models
|
||||
[IgnoreDataMember]
|
||||
private readonly ReaderWriterLockSlim _addLocker = new ReaderWriterLockSlim();
|
||||
|
||||
// TODO: This doesn't seem to be used
|
||||
[IgnoreDataMember]
|
||||
internal Action OnAdd;
|
||||
|
||||
internal PropertyTypeCollection(bool supportsPublishing)
|
||||
{
|
||||
@@ -40,44 +43,36 @@ namespace Umbraco.Core.Models
|
||||
/// <remarks></remarks>
|
||||
internal void Reset(IEnumerable<PropertyType> properties)
|
||||
{
|
||||
//collection events will be raised in each of these calls
|
||||
Clear();
|
||||
|
||||
//collection events will be raised in each of these calls
|
||||
foreach (var property in properties)
|
||||
Add(property);
|
||||
Add(property);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
protected override void SetItem(int index, PropertyType item)
|
||||
{
|
||||
item.SupportsPublishing = SupportsPublishing;
|
||||
var oldItem = index >= 0 ? this[index] : item;
|
||||
base.SetItem(index, item);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, oldItem));
|
||||
item.PropertyChanged += Item_PropertyChanged;
|
||||
base.SetItem(index, item);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
|
||||
}
|
||||
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
var removed = this[index];
|
||||
base.RemoveItem(index);
|
||||
removed.PropertyChanged -= Item_PropertyChanged;
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removed));
|
||||
}
|
||||
|
||||
protected override void InsertItem(int index, PropertyType item)
|
||||
{
|
||||
item.SupportsPublishing = SupportsPublishing;
|
||||
base.InsertItem(index, item);
|
||||
base.InsertItem(index, item);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
|
||||
item.PropertyChanged += Item_PropertyChanged;
|
||||
}
|
||||
|
||||
protected override void ClearItems()
|
||||
{
|
||||
base.ClearItems();
|
||||
foreach (var item in this)
|
||||
item.PropertyChanged -= Item_PropertyChanged;
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
@@ -96,7 +91,6 @@ namespace Umbraco.Core.Models
|
||||
var exists = Contains(key);
|
||||
if (exists)
|
||||
{
|
||||
//collection events will be raised in SetItem
|
||||
SetItem(IndexOfKey(key), item);
|
||||
return;
|
||||
}
|
||||
@@ -109,8 +103,10 @@ namespace Umbraco.Core.Models
|
||||
item.SortOrder = this.Max(x => x.SortOrder) + 1;
|
||||
}
|
||||
|
||||
//collection events will be raised in InsertItem
|
||||
base.Add(item);
|
||||
OnAdd?.Invoke();
|
||||
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -119,17 +115,6 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a property changes on a PropertyType that exists in this collection
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void Item_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
var propType = (PropertyType)sender;
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, propType, propType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this collection contains a <see cref="Property"/> whose alias matches the specified PropertyType.
|
||||
/// </summary>
|
||||
|
||||
@@ -18,6 +18,5 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
|
||||
public string ConstraintName { get; set; }
|
||||
public string TableName { get; set; }
|
||||
public ICollection<string> Columns = new HashSet<string>();
|
||||
public bool IsPrimaryKeyClustered { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,20 +379,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
return "variantName";
|
||||
}
|
||||
|
||||
// content type alias is invariant
|
||||
if(ordering.OrderBy.InvariantEquals("contentTypeAlias"))
|
||||
{
|
||||
var joins = Sql()
|
||||
.InnerJoin<ContentTypeDto>("ctype").On<ContentDto, ContentTypeDto>((content, contentType) => content.ContentTypeId == contentType.NodeId, aliasRight: "ctype");
|
||||
|
||||
// see notes in ApplyOrdering: the field MUST be selected + aliased
|
||||
sql = Sql(InsertBefore(sql, "FROM", ", " + SqlSyntax.GetFieldName<ContentTypeDto>(x => x.Alias, "ctype") + " AS ordering "), sql.Arguments);
|
||||
|
||||
sql = InsertJoins(sql, joins);
|
||||
|
||||
return "ordering";
|
||||
}
|
||||
|
||||
// previously, we'd accept anything and just sanitize it - not anymore
|
||||
throw new NotSupportedException($"Ordering by {ordering.OrderBy} not supported.");
|
||||
}
|
||||
|
||||
@@ -240,25 +240,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
propertyIx++;
|
||||
}
|
||||
contentType.NoGroupPropertyTypes = noGroupPropertyTypes;
|
||||
|
||||
// ensure builtin properties
|
||||
if (contentType is MemberType memberType)
|
||||
{
|
||||
// ensure that the group exists (ok if it already exists)
|
||||
memberType.AddPropertyGroup(Constants.Conventions.Member.StandardPropertiesGroupName);
|
||||
|
||||
// ensure that property types exist (ok if they already exist)
|
||||
foreach (var (alias, propertyType) in builtinProperties)
|
||||
{
|
||||
var added = memberType.AddPropertyType(propertyType, Constants.Conventions.Member.StandardPropertiesGroupName);
|
||||
|
||||
if (added)
|
||||
{
|
||||
var access = new MemberTypePropertyProfileAccess(false, false, false);
|
||||
memberType.MemberTypePropertyTypes[alias] = access;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +264,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
if (contentType is MemberType memberType)
|
||||
{
|
||||
var access = new MemberTypePropertyProfileAccess(dto.ViewOnProfile, dto.CanEdit, dto.IsSensitive);
|
||||
memberType.MemberTypePropertyTypes[dto.Alias] = access;
|
||||
memberType.MemberTypePropertyTypes.Add(dto.Alias, access);
|
||||
}
|
||||
|
||||
return new PropertyType(dto.DataTypeDto.EditorAlias, storageType, readonlyStorageType, dto.Alias)
|
||||
|
||||
@@ -13,15 +13,12 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// </summary>
|
||||
public class ConfigurationEditor : IConfigurationEditor
|
||||
{
|
||||
private IDictionary<string, object> _defaultConfiguration;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConfigurationEditor"/> class.
|
||||
/// </summary>
|
||||
public ConfigurationEditor()
|
||||
{
|
||||
Fields = new List<ConfigurationField>();
|
||||
_defaultConfiguration = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -64,10 +61,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
|
||||
/// <inheritdoc />
|
||||
[JsonProperty("defaultConfig")]
|
||||
public virtual IDictionary<string, object> DefaultConfiguration {
|
||||
get => _defaultConfiguration;
|
||||
internal set => _defaultConfiguration = value;
|
||||
}
|
||||
public virtual IDictionary<string, object> DefaultConfiguration => new Dictionary<string, object>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual object DefaultConfigurationObject => DefaultConfiguration;
|
||||
|
||||
@@ -173,13 +173,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// </summary>
|
||||
protected virtual IConfigurationEditor CreateConfigurationEditor()
|
||||
{
|
||||
var editor = new ConfigurationEditor();
|
||||
// pass the default configuration if this is not a property value editor
|
||||
if((Type & EditorType.PropertyValue) == 0)
|
||||
{
|
||||
editor.DefaultConfiguration = _defaultConfiguration;
|
||||
}
|
||||
return editor;
|
||||
return new ConfigurationEditor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
public class DropDownFlexibleConfiguration : ValueListConfiguration
|
||||
internal class DropDownFlexibleConfiguration : ValueListConfiguration
|
||||
{
|
||||
[ConfigurationField("multiple", "Enable multiple choice", "boolean", Description = "When checked, the dropdown will be a select multiple / combo box style dropdown.")]
|
||||
public bool Multiple { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,18 +9,18 @@
|
||||
public bool EnableRange { get; set; }
|
||||
|
||||
[ConfigurationField("initVal1", "Initial value", "number")]
|
||||
public decimal InitialValue { get; set; }
|
||||
public int InitialValue { get; set; }
|
||||
|
||||
[ConfigurationField("initVal2", "Initial value 2", "number", Description = "Used when range is enabled")]
|
||||
public decimal InitialValue2 { get; set; }
|
||||
public int InitialValue2 { get; set; }
|
||||
|
||||
[ConfigurationField("minVal", "Minimum value", "number")]
|
||||
public decimal MinimumValue { get; set; }
|
||||
public int MinimumValue { get; set; }
|
||||
|
||||
[ConfigurationField("maxVal", "Maximum value", "number")]
|
||||
public decimal MaximumValue { get; set; }
|
||||
public int MaximumValue { get; set; }
|
||||
|
||||
[ConfigurationField("step", "Step increments", "number")]
|
||||
public decimal StepIncrements { get; set; }
|
||||
public int StepIncrements { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
@@ -316,16 +315,8 @@ namespace Umbraco.Core.Services
|
||||
/// <summary>
|
||||
/// Empties the recycle bin.
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use EmptyRecycleBin with explicit indication of user ID instead")]
|
||||
OperationResult EmptyRecycleBin();
|
||||
|
||||
/// <summary>
|
||||
/// Empties the Recycle Bin by deleting all <see cref="IContent"/> that resides in the bin
|
||||
/// </summary>
|
||||
/// <param name="userId">Optional Id of the User emptying the Recycle Bin</param>
|
||||
OperationResult EmptyRecycleBin(int userId = Constants.Security.SuperUserId);
|
||||
|
||||
/// <summary>
|
||||
/// Sorts documents.
|
||||
/// </summary>
|
||||
|
||||
@@ -162,16 +162,8 @@ namespace Umbraco.Core.Services
|
||||
/// <summary>
|
||||
/// Empties the Recycle Bin by deleting all <see cref="IMedia"/> that resides in the bin
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use EmptyRecycleBin with explicit indication of user ID instead")]
|
||||
OperationResult EmptyRecycleBin();
|
||||
|
||||
/// <summary>
|
||||
/// Empties the Recycle Bin by deleting all <see cref="IMedia"/> that resides in the bin
|
||||
/// </summary>
|
||||
/// <param name="userId">Optional Id of the User emptying the Recycle Bin</param>
|
||||
OperationResult EmptyRecycleBin(int userId = Constants.Security.SuperUserId);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all media of specified type. All children of deleted media is moved to Recycle Bin.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Events;
|
||||
@@ -1889,8 +1888,9 @@ namespace Umbraco.Core.Services.Implement
|
||||
content.ParentId = parentId;
|
||||
|
||||
// get the level delta (old pos to new pos)
|
||||
// note that recycle bin (id:-20) level is 0!
|
||||
var levelDelta = 1 - content.Level + (parent?.Level ?? 0);
|
||||
var levelDelta = parent == null
|
||||
? 1 - content.Level + (parentId == Constants.System.RecycleBinContent ? 1 : 0)
|
||||
: parent.Level + 1 - content.Level;
|
||||
|
||||
var paths = new Dictionary<int, string>();
|
||||
|
||||
@@ -1939,14 +1939,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
/// <summary>
|
||||
/// Empties the Recycle Bin by deleting all <see cref="IContent"/> that resides in the bin
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use EmptyRecycleBin with explicit indication of user ID instead")]
|
||||
public OperationResult EmptyRecycleBin() => EmptyRecycleBin(Constants.Security.SuperUserId);
|
||||
|
||||
/// <summary>
|
||||
/// Empties the Recycle Bin by deleting all <see cref="IContent"/> that resides in the bin
|
||||
/// </summary>
|
||||
public OperationResult EmptyRecycleBin(int userId = Constants.Security.SuperUserId)
|
||||
public OperationResult EmptyRecycleBin()
|
||||
{
|
||||
var nodeObjectType = Constants.ObjectTypes.Document;
|
||||
var deleted = new List<IContent>();
|
||||
@@ -1981,7 +1974,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
recycleBinEventArgs.RecycleBinEmptiedSuccessfully = true; // oh my?!
|
||||
scope.Events.Dispatch(EmptiedRecycleBin, this, recycleBinEventArgs);
|
||||
scope.Events.Dispatch(TreeChanged, this, deleted.Select(x => new TreeChange<IContent>(x, TreeChangeTypes.Remove)).ToEventArgs());
|
||||
Audit(AuditType.Delete, userId, Constants.System.RecycleBinContent, "Recycle bin emptied");
|
||||
Audit(AuditType.Delete, 0, Constants.System.RecycleBinContent, "Recycle bin emptied");
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
@@ -2885,16 +2878,25 @@ namespace Umbraco.Core.Services.Implement
|
||||
{
|
||||
foreach (var property in blueprint.Properties)
|
||||
{
|
||||
var propertyCulture = property.PropertyType.VariesByCulture() ? culture : null;
|
||||
content.SetValue(property.Alias, property.GetValue(propertyCulture), propertyCulture);
|
||||
if (property.PropertyType.VariesByCulture())
|
||||
{
|
||||
content.SetValue(property.Alias, property.GetValue(culture), culture);
|
||||
}
|
||||
else
|
||||
{
|
||||
content.SetValue(property.Alias, property.GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
content.Name = blueprint.Name;
|
||||
if (!string.IsNullOrEmpty(culture))
|
||||
{
|
||||
content.SetCultureInfo(culture, blueprint.GetCultureName(culture), now);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
@@ -1034,12 +1034,10 @@ namespace Umbraco.Core.Services.Implement
|
||||
//strip the @inherits if it's there
|
||||
snippetContent = StripPartialViewHeader(snippetContent);
|
||||
|
||||
//Update Model.Content to be Model when used as PartialView
|
||||
//Update Model.Content. to be Model. when used as PartialView
|
||||
if (partialViewType == PartialViewType.PartialView)
|
||||
{
|
||||
snippetContent = snippetContent
|
||||
.Replace("Model.Content.", "Model.")
|
||||
.Replace("(Model.Content)", "(Model)");
|
||||
snippetContent = snippetContent.Replace("Model.Content.", "Model.");
|
||||
}
|
||||
|
||||
var content = $"{partialViewHeader}{Environment.NewLine}{snippetContent}";
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -290,7 +289,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
scope.Events.Dispatch(Saved, this, saveEventArgs);
|
||||
scope.Events.Dispatch(TreeChanged, this, new TreeChange<IMedia>(media, TreeChangeTypes.RefreshNode).ToEventArgs());
|
||||
}
|
||||
|
||||
|
||||
if (withIdentity == false)
|
||||
return;
|
||||
|
||||
@@ -717,7 +716,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
#endregion
|
||||
|
||||
#region Delete
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Permanently deletes an <see cref="IMedia"/> object
|
||||
/// </summary>
|
||||
@@ -976,8 +975,9 @@ namespace Umbraco.Core.Services.Implement
|
||||
media.ParentId = parentId;
|
||||
|
||||
// get the level delta (old pos to new pos)
|
||||
// note that recycle bin (id:-20) level is 0!
|
||||
var levelDelta = 1 - media.Level + (parent?.Level ?? 0);
|
||||
var levelDelta = parent == null
|
||||
? 1 - media.Level + (parentId == Constants.System.RecycleBinMedia ? 1 : 0)
|
||||
: parent.Level + 1 - media.Level;
|
||||
|
||||
var paths = new Dictionary<int, string>();
|
||||
|
||||
@@ -1024,15 +1024,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
/// <summary>
|
||||
/// Empties the Recycle Bin by deleting all <see cref="IMedia"/> that resides in the bin
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use EmptyRecycleBin with explicit indication of user ID instead")]
|
||||
public OperationResult EmptyRecycleBin() => EmptyRecycleBin(Constants.Security.SuperUserId);
|
||||
|
||||
/// <summary>
|
||||
/// Empties the Recycle Bin by deleting all <see cref="IMedia"/> that resides in the bin
|
||||
/// </summary>
|
||||
/// <param name="userId">Optional Id of the User emptying the Recycle Bin</param>
|
||||
public OperationResult EmptyRecycleBin(int userId = Constants.Security.SuperUserId)
|
||||
public OperationResult EmptyRecycleBin()
|
||||
{
|
||||
var nodeObjectType = Constants.ObjectTypes.Media;
|
||||
var deleted = new List<IMedia>();
|
||||
@@ -1071,7 +1063,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
args.CanCancel = false;
|
||||
scope.Events.Dispatch(EmptiedRecycleBin, this, args);
|
||||
scope.Events.Dispatch(TreeChanged, this, deleted.Select(x => new TreeChange<IMedia>(x, TreeChangeTypes.Remove)).ToEventArgs());
|
||||
Audit(AuditType.Delete, userId, Constants.System.RecycleBinMedia, "Empty Media recycle bin");
|
||||
Audit(AuditType.Delete, 0, Constants.System.RecycleBinMedia, "Empty Media recycle bin");
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
|
||||
@@ -55,12 +55,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- note: NuGet deals with transitive references now -->
|
||||
<PackageReference Include="Serilog.Sinks.Async">
|
||||
<Version>1.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Serilog.Sinks.Map">
|
||||
<Version>1.0.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Umbraco.Code">
|
||||
<Version>1.0.5</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
@@ -225,7 +219,6 @@
|
||||
<Compile Include="Mapping\MapDefinitionCollectionBuilder.cs" />
|
||||
<Compile Include="Mapping\IMapDefinition.cs" />
|
||||
<Compile Include="Mapping\UmbracoMapper.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_1_0\ConvertTinyMceAndGridMediaUrlsToLocalLink.cs" />
|
||||
<Compile Include="Models\CultureImpact.cs" />
|
||||
<Compile Include="Models\PublishedContent\ILivePublishedModelFactory.cs" />
|
||||
<Compile Include="Persistence\Dtos\PropertyTypeCommonDto.cs" />
|
||||
|
||||
@@ -159,7 +159,6 @@ namespace Umbraco.Tests.Cache
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
TestObjects.GetGlobalSettings(),
|
||||
new UrlProviderCollection(Enumerable.Empty<IUrlProvider>()),
|
||||
new MediaUrlProviderCollection(Enumerable.Empty<IMediaUrlProvider>()),
|
||||
Mock.Of<IUserService>());
|
||||
|
||||
// just assert it does not throw
|
||||
|
||||
@@ -81,7 +81,6 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
new WebSecurity(_httpContextFactory.HttpContext, Current.Services.UserService, globalSettings),
|
||||
umbracoSettings,
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
Enumerable.Empty<IMediaUrlProvider>(),
|
||||
globalSettings,
|
||||
new TestVariationContextAccessor());
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Compose;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.IO;
|
||||
@@ -300,19 +299,11 @@ namespace Umbraco.Tests.Components
|
||||
composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
Composed.Clear();
|
||||
Assert.Throws<Exception>(() => composers.Compose());
|
||||
Console.WriteLine("throws:");
|
||||
composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
var requirements = composers.GetRequirements(false);
|
||||
Console.WriteLine(Composers.GetComposersReport(requirements));
|
||||
|
||||
types = new[] { typeof(Composer2) };
|
||||
composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
Composed.Clear();
|
||||
Assert.Throws<Exception>(() => composers.Compose());
|
||||
Console.WriteLine("throws:");
|
||||
composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
requirements = composers.GetRequirements(false);
|
||||
Console.WriteLine(Composers.GetComposersReport(requirements));
|
||||
|
||||
types = new[] { typeof(Composer12) };
|
||||
composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
@@ -358,25 +349,6 @@ namespace Umbraco.Tests.Components
|
||||
Assert.AreEqual(typeof(Composer27), Composed[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllComposers()
|
||||
{
|
||||
var typeLoader = new TypeLoader(AppCaches.Disabled.RuntimeCache, IOHelper.MapPath("~/App_Data/TEMP"), Mock.Of<IProfilingLogger>());
|
||||
|
||||
var register = MockRegister();
|
||||
var composition = new Composition(register, typeLoader, Mock.Of<IProfilingLogger>(), MockRuntimeState(RuntimeLevel.Run));
|
||||
|
||||
var types = typeLoader.GetTypes<IComposer>().Where(x => x.FullName.StartsWith("Umbraco.Core.") || x.FullName.StartsWith("Umbraco.Web"));
|
||||
var composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
var requirements = composers.GetRequirements();
|
||||
var report = Composers.GetComposersReport(requirements);
|
||||
Console.WriteLine(report);
|
||||
var composerTypes = composers.SortComposers(requirements);
|
||||
|
||||
foreach (var type in composerTypes)
|
||||
Console.WriteLine(type);
|
||||
}
|
||||
|
||||
#region Compothings
|
||||
|
||||
public class TestComposerBase : IComposer
|
||||
|
||||
@@ -27,7 +27,10 @@ namespace Umbraco.Tests.Composing
|
||||
public void Initialize()
|
||||
{
|
||||
// this ensures it's reset
|
||||
_typeLoader = new TypeLoader(NoAppCache.Instance, IOHelper.MapPath("~/App_Data/TEMP"), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()), false);
|
||||
_typeLoader = new TypeLoader(NoAppCache.Instance, IOHelper.MapPath("~/App_Data/TEMP"), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
foreach (var file in Directory.GetFiles(IOHelper.MapPath(SystemDirectories.TempData.EnsureEndsWith('/') + "TypesCache")))
|
||||
File.Delete(file);
|
||||
|
||||
// for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
// TODO: Should probably update this so it only searches this assembly and add custom types to be found
|
||||
|
||||
@@ -381,9 +381,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
}
|
||||
}
|
||||
|
||||
public override IPublishedContent GetById(bool preview, Udi nodeId)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
{
|
||||
return GetXml(preview).CreateNavigator().MoveToId(contentId.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
@@ -97,9 +97,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override IPublishedContent GetById(bool preview, Udi nodeId)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
{
|
||||
return GetUmbracoMedia(contentId) != null;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -110,68 +108,6 @@ namespace Umbraco.Tests.Mapping
|
||||
var target = mapper.Map<IEnumerable<ContentPropertyDto>>(source);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Explicit]
|
||||
public void ConcurrentMap()
|
||||
{
|
||||
var definitions = new MapDefinitionCollection(new IMapDefinition[]
|
||||
{
|
||||
new MapperDefinition1(),
|
||||
new MapperDefinition3(),
|
||||
});
|
||||
var mapper = new UmbracoMapper(definitions);
|
||||
|
||||
// the mapper currently has a map from Thing1 to Thing2
|
||||
// because Thing3 inherits from Thing1, it will map a Thing3 instance,
|
||||
// and register a new map from Thing3 to Thing2,
|
||||
// thus modifying its internal dictionaries
|
||||
|
||||
// if timing is good, and mapper does have non-concurrent dictionaries, it fails
|
||||
// practically, to reproduce, one needs to add a 1s sleep in the mapper's loop
|
||||
// hence, this test is explicit
|
||||
|
||||
var thing3 = new Thing3 { Value = "value" };
|
||||
var thing4 = new Thing4();
|
||||
Exception caught = null;
|
||||
|
||||
void ThreadLoop()
|
||||
{
|
||||
// keep failing at mapping - and looping through the maps
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
mapper.Map<Thing2>(thing4);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
caught = e;
|
||||
Console.WriteLine($"{e.GetType().Name} {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("done");
|
||||
}
|
||||
|
||||
var thread = new Thread(ThreadLoop);
|
||||
thread.Start();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"{DateTime.Now:O} mapping");
|
||||
var thing2 = mapper.Map<Thing2>(thing3);
|
||||
Console.WriteLine($"{DateTime.Now:O} mapped");
|
||||
|
||||
Assert.IsNotNull(thing2);
|
||||
Assert.AreEqual("value", thing2.Value);
|
||||
}
|
||||
finally
|
||||
{
|
||||
thread.Join();
|
||||
}
|
||||
}
|
||||
|
||||
private class Thing1
|
||||
{
|
||||
public string Value { get; set; }
|
||||
@@ -185,9 +121,6 @@ namespace Umbraco.Tests.Mapping
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
private class Thing4
|
||||
{ }
|
||||
|
||||
private class MapperDefinition1 : IMapDefinition
|
||||
{
|
||||
public void DefineMaps(UmbracoMapper mapper)
|
||||
@@ -211,18 +144,5 @@ namespace Umbraco.Tests.Mapping
|
||||
private static void Map(Property source, ContentPropertyDto target, MapperContext context)
|
||||
{ }
|
||||
}
|
||||
|
||||
private class MapperDefinition3 : IMapDefinition
|
||||
{
|
||||
public void DefineMaps(UmbracoMapper mapper)
|
||||
{
|
||||
// just some random things so that the mapper contains things
|
||||
mapper.Define<int, object>();
|
||||
mapper.Define<string, object>();
|
||||
mapper.Define<double, object>();
|
||||
mapper.Define<UmbracoMapper, object>();
|
||||
mapper.Define<Property, object>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,47 +15,13 @@ namespace Umbraco.Tests.Models
|
||||
[TestFixture]
|
||||
public class ContentTypeTests : UmbracoTestBase
|
||||
{
|
||||
[Test]
|
||||
[Ignore("Ignoring this test until we actually enforce this, see comments in ContentTypeBase.PropertyTypesChanged")]
|
||||
public void Cannot_Add_Duplicate_Property_Aliases()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateBasicContentType();
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(new PropertyTypeCollection(false, new[]
|
||||
{
|
||||
new PropertyType("testPropertyEditor", ValueStorageType.Nvarchar){ Alias = "myPropertyType" }
|
||||
})));
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
contentType.PropertyTypeCollection.Add(
|
||||
new PropertyType("testPropertyEditor", ValueStorageType.Nvarchar) { Alias = "myPropertyType" }));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("Ignoring this test until we actually enforce this, see comments in ContentTypeBase.PropertyTypesChanged")]
|
||||
public void Cannot_Update_Duplicate_Property_Aliases()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateBasicContentType();
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(new PropertyTypeCollection(false, new[]
|
||||
{
|
||||
new PropertyType("testPropertyEditor", ValueStorageType.Nvarchar){ Alias = "myPropertyType" }
|
||||
})));
|
||||
|
||||
contentType.PropertyTypeCollection.Add(new PropertyType("testPropertyEditor", ValueStorageType.Nvarchar) { Alias = "myPropertyType2" });
|
||||
|
||||
var toUpdate = contentType.PropertyTypeCollection["myPropertyType2"];
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => toUpdate.Alias = "myPropertyType");
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Deep_Clone_Content_Type_Sort()
|
||||
{
|
||||
var contentType = new ContentTypeSort(new Lazy<int>(() => 3), 4, "test");
|
||||
var clone = (ContentTypeSort)contentType.DeepClone();
|
||||
var clone = (ContentTypeSort) contentType.DeepClone();
|
||||
Assert.AreNotSame(clone, contentType);
|
||||
Assert.AreEqual(clone, contentType);
|
||||
Assert.AreEqual(clone.Id.Value, contentType.Id.Value);
|
||||
@@ -88,7 +54,7 @@ namespace Umbraco.Tests.Models
|
||||
contentType.Id = 10;
|
||||
contentType.CreateDate = DateTime.Now;
|
||||
contentType.CreatorId = 22;
|
||||
contentType.SetDefaultTemplate(new Template((string)"Test Template", (string)"testTemplate")
|
||||
contentType.SetDefaultTemplate(new Template((string) "Test Template", (string) "testTemplate")
|
||||
{
|
||||
Id = 88
|
||||
});
|
||||
@@ -151,12 +117,12 @@ namespace Umbraco.Tests.Models
|
||||
{
|
||||
group.Id = ++i;
|
||||
}
|
||||
contentType.AllowedTemplates = new[] { new Template((string)"Name", (string)"name") { Id = 200 }, new Template((string)"Name2", (string)"name2") { Id = 201 } };
|
||||
contentType.AllowedTemplates = new[] { new Template((string) "Name", (string) "name") { Id = 200 }, new Template((string) "Name2", (string) "name2") { Id = 201 } };
|
||||
contentType.AllowedContentTypes = new[] { new ContentTypeSort(new Lazy<int>(() => 888), 8, "sub"), new ContentTypeSort(new Lazy<int>(() => 889), 9, "sub2") };
|
||||
contentType.Id = 10;
|
||||
contentType.CreateDate = DateTime.Now;
|
||||
contentType.CreatorId = 22;
|
||||
contentType.SetDefaultTemplate(new Template((string)"Test Template", (string)"testTemplate")
|
||||
contentType.SetDefaultTemplate(new Template((string) "Test Template", (string) "testTemplate")
|
||||
{
|
||||
Id = 88
|
||||
});
|
||||
@@ -201,12 +167,12 @@ namespace Umbraco.Tests.Models
|
||||
{
|
||||
group.Id = ++i;
|
||||
}
|
||||
contentType.AllowedTemplates = new[] { new Template((string)"Name", (string)"name") { Id = 200 }, new Template((string)"Name2", (string)"name2") { Id = 201 } };
|
||||
contentType.AllowedContentTypes = new[] { new ContentTypeSort(new Lazy<int>(() => 888), 8, "sub"), new ContentTypeSort(new Lazy<int>(() => 889), 9, "sub2") };
|
||||
contentType.AllowedTemplates = new[] { new Template((string) "Name", (string) "name") { Id = 200 }, new Template((string) "Name2", (string) "name2") { Id = 201 } };
|
||||
contentType.AllowedContentTypes = new[] {new ContentTypeSort(new Lazy<int>(() => 888), 8, "sub"), new ContentTypeSort(new Lazy<int>(() => 889), 9, "sub2")};
|
||||
contentType.Id = 10;
|
||||
contentType.CreateDate = DateTime.Now;
|
||||
contentType.CreatorId = 22;
|
||||
contentType.SetDefaultTemplate(new Template((string)"Test Template", (string)"testTemplate")
|
||||
contentType.SetDefaultTemplate(new Template((string) "Test Template", (string) "testTemplate")
|
||||
{
|
||||
Id = 88
|
||||
});
|
||||
@@ -298,12 +264,12 @@ namespace Umbraco.Tests.Models
|
||||
{
|
||||
propertyType.Id = ++i;
|
||||
}
|
||||
contentType.AllowedTemplates = new[] { new Template((string)"Name", (string)"name") { Id = 200 }, new Template((string)"Name2", (string)"name2") { Id = 201 } };
|
||||
contentType.AllowedTemplates = new[] { new Template((string) "Name", (string) "name") { Id = 200 }, new Template((string) "Name2", (string) "name2") { Id = 201 } };
|
||||
contentType.AllowedContentTypes = new[] { new ContentTypeSort(new Lazy<int>(() => 888), 8, "sub"), new ContentTypeSort(new Lazy<int>(() => 889), 9, "sub2") };
|
||||
contentType.Id = 10;
|
||||
contentType.CreateDate = DateTime.Now;
|
||||
contentType.CreatorId = 22;
|
||||
contentType.SetDefaultTemplate(new Template((string)"Test Template", (string)"testTemplate")
|
||||
contentType.SetDefaultTemplate(new Template((string) "Test Template", (string) "testTemplate")
|
||||
{
|
||||
Id = 88
|
||||
});
|
||||
|
||||
@@ -171,6 +171,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//NOTE: This tests for left join logic (rev 7b14e8eacc65f82d4f184ef46c23340c09569052)
|
||||
[Test]
|
||||
public void Can_Get_All_Members_When_No_Properties_Assigned()
|
||||
@@ -199,6 +200,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Can_Get_Member_Type_By_Id()
|
||||
{
|
||||
@@ -231,114 +233,22 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
// See: https://github.com/umbraco/Umbraco-CMS/issues/4963#issuecomment-483516698
|
||||
[Test]
|
||||
public void Bug_Changing_Built_In_Member_Type_Property_Type_Aliases_Results_In_Exception()
|
||||
{
|
||||
var stubs = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
|
||||
|
||||
var provider = TestObjects.GetScopeProvider(Logger);
|
||||
using (provider.CreateScope())
|
||||
{
|
||||
var repository = CreateRepository(provider);
|
||||
|
||||
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType("mtype");
|
||||
|
||||
// created without the stub properties
|
||||
Assert.AreEqual(1, memberType.PropertyGroups.Count);
|
||||
Assert.AreEqual(3, memberType.PropertyTypes.Count());
|
||||
|
||||
// saving *new* member type adds the stub properties
|
||||
repository.Save(memberType);
|
||||
|
||||
// saving has added (and saved) the stub properties
|
||||
Assert.AreEqual(2, memberType.PropertyGroups.Count);
|
||||
Assert.AreEqual(3 + stubs.Count, memberType.PropertyTypes.Count());
|
||||
|
||||
foreach (var stub in stubs)
|
||||
{
|
||||
var prop = memberType.PropertyTypes.First(x => x.Alias == stub.Key);
|
||||
prop.Alias = prop.Alias + "__0000";
|
||||
}
|
||||
|
||||
// saving *existing* member type does *not* ensure stub properties
|
||||
repository.Save(memberType);
|
||||
|
||||
// therefore, nothing has changed
|
||||
Assert.AreEqual(2, memberType.PropertyGroups.Count);
|
||||
Assert.AreEqual(3 + stubs.Count, memberType.PropertyTypes.Count());
|
||||
|
||||
// fetching ensures that the stub properties are there
|
||||
memberType = repository.Get("mtype");
|
||||
Assert.IsNotNull(memberType);
|
||||
|
||||
Assert.AreEqual(2, memberType.PropertyGroups.Count);
|
||||
Assert.AreEqual(3 + stubs.Count * 2, memberType.PropertyTypes.Count());
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Built_In_Member_Type_Properties_Are_Automatically_Added_When_Creating()
|
||||
{
|
||||
var stubs = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
|
||||
|
||||
var provider = TestObjects.GetScopeProvider(Logger);
|
||||
using (provider.CreateScope())
|
||||
using (var scope = provider.CreateScope())
|
||||
{
|
||||
var repository = CreateRepository(provider);
|
||||
|
||||
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
|
||||
// created without the stub properties
|
||||
Assert.AreEqual(1, memberType.PropertyGroups.Count);
|
||||
Assert.AreEqual(3, memberType.PropertyTypes.Count());
|
||||
|
||||
// saving *new* member type adds the stub properties
|
||||
repository.Save(memberType);
|
||||
|
||||
// saving has added (and saved) the stub properties
|
||||
Assert.AreEqual(2, memberType.PropertyGroups.Count);
|
||||
Assert.AreEqual(3 + stubs.Count, memberType.PropertyTypes.Count());
|
||||
|
||||
// getting with stub properties
|
||||
memberType = repository.Get(memberType.Id);
|
||||
|
||||
Assert.AreEqual(2, memberType.PropertyGroups.Count);
|
||||
Assert.AreEqual(3 + stubs.Count, memberType.PropertyTypes.Count());
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Built_In_Member_Type_Properties_Missing_Are_Automatically_Added_When_Creating()
|
||||
{
|
||||
var stubs = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
|
||||
|
||||
var provider = TestObjects.GetScopeProvider(Logger);
|
||||
using (provider.CreateScope())
|
||||
{
|
||||
var repository = CreateRepository(provider);
|
||||
|
||||
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
|
||||
// created without the stub properties
|
||||
Assert.AreEqual(1, memberType.PropertyGroups.Count);
|
||||
Assert.AreEqual(3, memberType.PropertyTypes.Count());
|
||||
|
||||
// add one stub property, others are still missing
|
||||
memberType.AddPropertyType(stubs.First().Value, Constants.Conventions.Member.StandardPropertiesGroupName);
|
||||
|
||||
// saving *new* member type adds the (missing) stub properties
|
||||
repository.Save(memberType);
|
||||
|
||||
// saving has added (and saved) the (missing) stub properties
|
||||
Assert.AreEqual(2, memberType.PropertyGroups.Count);
|
||||
Assert.AreEqual(3 + stubs.Count, memberType.PropertyTypes.Count());
|
||||
|
||||
// getting with stub properties
|
||||
memberType = repository.Get(memberType.Id);
|
||||
|
||||
Assert.AreEqual(2, memberType.PropertyGroups.Count);
|
||||
Assert.AreEqual(3 + stubs.Count, memberType.PropertyTypes.Count());
|
||||
Assert.That(memberType.PropertyTypes.Count(), Is.EqualTo(3 + Constants.Conventions.Member.GetStandardPropertyTypeStubs().Count));
|
||||
Assert.That(memberType.PropertyGroups.Count(), Is.EqualTo(2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
new WebSecurity(httpContext, Current.Services.UserService, globalSettings),
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
Enumerable.Empty<IMediaUrlProvider>(),
|
||||
globalSettings,
|
||||
new TestVariationContextAccessor());
|
||||
|
||||
|
||||
@@ -92,9 +92,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override IPublishedContent GetById(bool preview, Udi nodeId)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
{
|
||||
return _content.ContainsKey(contentId);
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Tests.PublishedContent;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Stubs;
|
||||
using Umbraco.Tests.Testing;
|
||||
using Umbraco.Web.Routing;
|
||||
|
||||
namespace Umbraco.Tests.Routing
|
||||
{
|
||||
[TestFixture]
|
||||
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerFixture)]
|
||||
public class MediaUrlProviderTests : BaseWebTest
|
||||
{
|
||||
private DefaultMediaUrlProvider _mediaUrlProvider;
|
||||
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
_mediaUrlProvider = new DefaultMediaUrlProvider();
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
_mediaUrlProvider = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Media_Url_Resolves_Url_From_Upload_Property_Editor()
|
||||
{
|
||||
const string expected = "/media/rfeiw584/test.jpg";
|
||||
|
||||
var umbracoContext = GetUmbracoContext("/", mediaUrlProviders: new[] { _mediaUrlProvider });
|
||||
var publishedContent = CreatePublishedContent(Constants.PropertyEditors.Aliases.UploadField, expected, null);
|
||||
|
||||
var resolvedUrl = umbracoContext.UrlProvider.GetMediaUrl(publishedContent, "umbracoFile", UrlProviderMode.Auto, null, null);
|
||||
|
||||
Assert.AreEqual(expected, resolvedUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Media_Url_Resolves_Url_From_Image_Cropper_Property_Editor()
|
||||
{
|
||||
const string expected = "/media/rfeiw584/test.jpg";
|
||||
|
||||
var configuration = new ImageCropperConfiguration();
|
||||
var imageCropperValue = JsonConvert.SerializeObject(new ImageCropperValue
|
||||
{
|
||||
Src = expected
|
||||
});
|
||||
|
||||
var umbracoContext = GetUmbracoContext("/", mediaUrlProviders: new[] { _mediaUrlProvider });
|
||||
var publishedContent = CreatePublishedContent(Constants.PropertyEditors.Aliases.ImageCropper, imageCropperValue, configuration);
|
||||
|
||||
var resolvedUrl = umbracoContext.UrlProvider.GetMediaUrl(publishedContent, "umbracoFile", UrlProviderMode.Auto, null, null);
|
||||
|
||||
Assert.AreEqual(expected, resolvedUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Media_Url_Can_Resolve_Absolute_Url()
|
||||
{
|
||||
const string mediaUrl = "/media/rfeiw584/test.jpg";
|
||||
var expected = $"http://localhost{mediaUrl}";
|
||||
|
||||
var umbracoContext = GetUmbracoContext("http://localhost", mediaUrlProviders: new[] { _mediaUrlProvider });
|
||||
var publishedContent = CreatePublishedContent(Constants.PropertyEditors.Aliases.UploadField, mediaUrl, null);
|
||||
|
||||
var resolvedUrl = umbracoContext.UrlProvider.GetMediaUrl(publishedContent, "umbracoFile", UrlProviderMode.Absolute, null, null);
|
||||
|
||||
Assert.AreEqual(expected, resolvedUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Media_Url_Returns_Empty_String_When_PropertyType_Is_Not_Supported()
|
||||
{
|
||||
var umbracoContext = GetUmbracoContext("/", mediaUrlProviders: new[] { _mediaUrlProvider });
|
||||
var publishedContent = CreatePublishedContent(Constants.PropertyEditors.Aliases.Boolean, "0", null);
|
||||
|
||||
var resolvedUrl = umbracoContext.UrlProvider.GetMediaUrl(publishedContent, "test", UrlProviderMode.Absolute, null, null);
|
||||
|
||||
Assert.AreEqual(string.Empty, resolvedUrl);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Media_Url_Can_Resolve_Variant_Property_Url()
|
||||
{
|
||||
var umbracoContext = GetUmbracoContext("http://localhost", mediaUrlProviders: new[] { _mediaUrlProvider });
|
||||
|
||||
var umbracoFilePropertyType = CreatePropertyType(Constants.PropertyEditors.Aliases.UploadField, null, ContentVariation.Culture);
|
||||
|
||||
const string enMediaUrl = "/media/rfeiw584/en.jpg";
|
||||
const string daMediaUrl = "/media/uf8ewud2/da.jpg";
|
||||
|
||||
var property = new SolidPublishedPropertyWithLanguageVariants
|
||||
{
|
||||
Alias = "umbracoFile",
|
||||
PropertyType = umbracoFilePropertyType,
|
||||
};
|
||||
|
||||
property.SetValue("en", enMediaUrl, true);
|
||||
property.SetValue("da", daMediaUrl);
|
||||
|
||||
var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), new [] { umbracoFilePropertyType }, ContentVariation.Culture);
|
||||
var publishedContent = new SolidPublishedContent(contentType) {Properties = new[] {property}};
|
||||
|
||||
var resolvedUrl = umbracoContext.UrlProvider.GetMediaUrl(publishedContent, "umbracoFile", UrlProviderMode.Auto, "da", null);
|
||||
Assert.AreEqual(daMediaUrl, resolvedUrl);
|
||||
}
|
||||
|
||||
private static TestPublishedContent CreatePublishedContent(string propertyEditorAlias, object propertyValue, object dataTypeConfiguration)
|
||||
{
|
||||
var umbracoFilePropertyType = CreatePropertyType(propertyEditorAlias, dataTypeConfiguration, ContentVariation.Nothing);
|
||||
|
||||
var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(),
|
||||
new[] {umbracoFilePropertyType}, ContentVariation.Nothing);
|
||||
|
||||
return new TestPublishedContent(contentType, 1234, Guid.NewGuid(),
|
||||
new Dictionary<string, object> {{"umbracoFile", propertyValue } }, false);
|
||||
}
|
||||
|
||||
private static PublishedPropertyType CreatePropertyType(string propertyEditorAlias, object dataTypeConfiguration, ContentVariation variation)
|
||||
{
|
||||
var uploadDataType = new PublishedDataType(1234, propertyEditorAlias, new Lazy<object>(() => dataTypeConfiguration));
|
||||
|
||||
var propertyValueConverters = new PropertyValueConverterCollection(new IPropertyValueConverter[]
|
||||
{
|
||||
new UploadPropertyConverter(),
|
||||
new ImageCropperValueConverter(),
|
||||
});
|
||||
|
||||
var publishedModelFactory = Mock.Of<IPublishedModelFactory>();
|
||||
var publishedContentTypeFactory = new Mock<IPublishedContentTypeFactory>();
|
||||
publishedContentTypeFactory.Setup(x => x.GetDataType(It.IsAny<int>()))
|
||||
.Returns(uploadDataType);
|
||||
|
||||
return new PublishedPropertyType("umbracoFile", 42, true, variation, propertyValueConverters, publishedModelFactory, publishedContentTypeFactory.Object);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,6 @@ namespace Umbraco.Tests.Scoping
|
||||
new WebSecurity(httpContext, Current.Services.UserService, globalSettings),
|
||||
umbracoSettings ?? SettingsForTests.GetDefaultUmbracoSettings(),
|
||||
urlProviders ?? Enumerable.Empty<IUrlProvider>(),
|
||||
Enumerable.Empty<IMediaUrlProvider>(),
|
||||
globalSettings,
|
||||
new TestVariationContextAccessor());
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Microsoft.Owin;
|
||||
using Moq;
|
||||
@@ -34,7 +33,7 @@ namespace Umbraco.Tests.Security
|
||||
Mock.Of<HttpContextBase>(),
|
||||
Mock.Of<IPublishedSnapshotService>(),
|
||||
new WebSecurity(Mock.Of<HttpContextBase>(), Current.Services.UserService, globalSettings),
|
||||
TestObjects.GetUmbracoSettings(), new List<IUrlProvider>(), Enumerable.Empty<IMediaUrlProvider>(), globalSettings,
|
||||
TestObjects.GetUmbracoSettings(), new List<IUrlProvider>(),globalSettings,
|
||||
new TestVariationContextAccessor());
|
||||
|
||||
var runtime = Mock.Of<IRuntimeState>(x => x.Level == RuntimeLevel.Install);
|
||||
@@ -54,7 +53,7 @@ namespace Umbraco.Tests.Security
|
||||
Mock.Of<HttpContextBase>(),
|
||||
Mock.Of<IPublishedSnapshotService>(),
|
||||
new WebSecurity(Mock.Of<HttpContextBase>(), Current.Services.UserService, globalSettings),
|
||||
TestObjects.GetUmbracoSettings(), new List<IUrlProvider>(), Enumerable.Empty<IMediaUrlProvider>(), globalSettings,
|
||||
TestObjects.GetUmbracoSettings(), new List<IUrlProvider>(), globalSettings,
|
||||
new TestVariationContextAccessor());
|
||||
|
||||
var runtime = Mock.Of<IRuntimeState>(x => x.Level == RuntimeLevel.Run);
|
||||
|
||||
@@ -139,7 +139,6 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
|
||||
webSecurity.Object,
|
||||
Mock.Of<IUmbracoSettingsSection>(section => section.WebRouting == Mock.Of<IWebRoutingSection>(routingSection => routingSection.UrlProviderMode == "Auto")),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
Enumerable.Empty<IMediaUrlProvider>(),
|
||||
globalSettings,
|
||||
new TestVariationContextAccessor());
|
||||
|
||||
|
||||
@@ -122,7 +122,6 @@ namespace Umbraco.Tests.TestHelpers
|
||||
var umbracoSettings = GetUmbracoSettings();
|
||||
var globalSettings = GetGlobalSettings();
|
||||
var urlProviders = new UrlProviderCollection(Enumerable.Empty<IUrlProvider>());
|
||||
var mediaUrlProviders = new MediaUrlProviderCollection(Enumerable.Empty<IMediaUrlProvider>());
|
||||
|
||||
if (accessor == null) accessor = new TestUmbracoContextAccessor();
|
||||
|
||||
@@ -134,7 +133,6 @@ namespace Umbraco.Tests.TestHelpers
|
||||
umbracoSettings,
|
||||
globalSettings,
|
||||
urlProviders,
|
||||
mediaUrlProviders,
|
||||
Mock.Of<IUserService>());
|
||||
|
||||
return umbracoContextFactory.EnsureUmbracoContext(httpContext).UmbracoContext;
|
||||
|
||||
@@ -353,7 +353,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
}
|
||||
}
|
||||
|
||||
protected UmbracoContext GetUmbracoContext(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable<IUrlProvider> urlProviders = null, IEnumerable<IMediaUrlProvider> mediaUrlProviders = null, IGlobalSettings globalSettings = null, IPublishedSnapshotService snapshotService = null)
|
||||
protected UmbracoContext GetUmbracoContext(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable<IUrlProvider> urlProviders = null, IGlobalSettings globalSettings = null, IPublishedSnapshotService snapshotService = null)
|
||||
{
|
||||
// ensure we have a PublishedCachesService
|
||||
var service = snapshotService ?? PublishedSnapshotService as PublishedSnapshotService;
|
||||
@@ -380,7 +380,6 @@ namespace Umbraco.Tests.TestHelpers
|
||||
Factory.GetInstance<IGlobalSettings>()),
|
||||
umbracoSettings ?? Factory.GetInstance<IUmbracoSettingsSection>(),
|
||||
urlProviders ?? Enumerable.Empty<IUrlProvider>(),
|
||||
mediaUrlProviders ?? Enumerable.Empty<IMediaUrlProvider>(),
|
||||
globalSettings ?? Factory.GetInstance<IGlobalSettings>(),
|
||||
new TestVariationContextAccessor());
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace Umbraco.Tests.Testing.TestingTests
|
||||
.Returns(UrlInfo.Url("/hello/world/1234"));
|
||||
var urlProvider = urlProviderMock.Object;
|
||||
|
||||
var theUrlProvider = new UrlProvider(umbracoContext, new [] { urlProvider }, Enumerable.Empty<IMediaUrlProvider>(), umbracoContext.VariationContextAccessor);
|
||||
var theUrlProvider = new UrlProvider(umbracoContext, new [] { urlProvider }, umbracoContext.VariationContextAccessor);
|
||||
|
||||
var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var publishedContent = Mock.Of<IPublishedContent>();
|
||||
|
||||
@@ -143,7 +143,6 @@
|
||||
<Compile Include="PublishedContent\PublishedContentSnapshotTestBase.cs" />
|
||||
<Compile Include="PublishedContent\SolidPublishedSnapshot.cs" />
|
||||
<Compile Include="PublishedContent\NuCacheTests.cs" />
|
||||
<Compile Include="Routing\MediaUrlProviderTests.cs" />
|
||||
<Compile Include="Runtimes\StandaloneTests.cs" />
|
||||
<Compile Include="Routing\GetContentUrlsTests.cs" />
|
||||
<Compile Include="Services\AmbiguousEventTests.cs" />
|
||||
|
||||
@@ -72,7 +72,6 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
globalSettings,
|
||||
new UrlProviderCollection(Enumerable.Empty<IUrlProvider>()),
|
||||
new MediaUrlProviderCollection(Enumerable.Empty<IMediaUrlProvider>()),
|
||||
Mock.Of<IUserService>());
|
||||
|
||||
var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(Mock.Of<HttpContextBase>());
|
||||
@@ -102,7 +101,6 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
globalSettings,
|
||||
new UrlProviderCollection(Enumerable.Empty<IUrlProvider>()),
|
||||
new MediaUrlProviderCollection(Enumerable.Empty<IMediaUrlProvider>()),
|
||||
Mock.Of<IUserService>());
|
||||
|
||||
var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(Mock.Of<HttpContextBase>());
|
||||
@@ -132,7 +130,6 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
globalSettings,
|
||||
new UrlProviderCollection(Enumerable.Empty<IUrlProvider>()),
|
||||
new MediaUrlProviderCollection(Enumerable.Empty<IMediaUrlProvider>()),
|
||||
Mock.Of<IUserService>());
|
||||
|
||||
var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(Mock.Of<HttpContextBase>());
|
||||
@@ -162,7 +159,6 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
globalSettings,
|
||||
new UrlProviderCollection(Enumerable.Empty<IUrlProvider>()),
|
||||
new MediaUrlProviderCollection(Enumerable.Empty<IMediaUrlProvider>()),
|
||||
Mock.Of<IUserService>());
|
||||
|
||||
var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(Mock.Of<HttpContextBase>());
|
||||
|
||||
@@ -47,7 +47,6 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
globalSettings,
|
||||
new UrlProviderCollection(Enumerable.Empty<IUrlProvider>()),
|
||||
new MediaUrlProviderCollection(Enumerable.Empty<IMediaUrlProvider>()),
|
||||
Mock.Of<IUserService>());
|
||||
|
||||
var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(Mock.Of<HttpContextBase>());
|
||||
@@ -75,7 +74,6 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
globalSettings,
|
||||
new UrlProviderCollection(Enumerable.Empty<IUrlProvider>()),
|
||||
new MediaUrlProviderCollection(Enumerable.Empty<IMediaUrlProvider>()),
|
||||
Mock.Of<IUserService>());
|
||||
|
||||
var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(Mock.Of<HttpContextBase>());
|
||||
@@ -106,7 +104,6 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
Mock.Of<IUmbracoSettingsSection>(section => section.WebRouting == Mock.Of<IWebRoutingSection>(routingSection => routingSection.UrlProviderMode == "Auto")),
|
||||
globalSettings,
|
||||
new UrlProviderCollection(Enumerable.Empty<IUrlProvider>()),
|
||||
new MediaUrlProviderCollection(Enumerable.Empty<IMediaUrlProvider>()),
|
||||
Mock.Of<IUserService>());
|
||||
|
||||
var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(Mock.Of<HttpContextBase>());
|
||||
@@ -144,7 +141,6 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
Mock.Of<IUmbracoSettingsSection>(section => section.WebRouting == webRoutingSettings),
|
||||
globalSettings,
|
||||
new UrlProviderCollection(Enumerable.Empty<IUrlProvider>()),
|
||||
new MediaUrlProviderCollection(Enumerable.Empty<IMediaUrlProvider>()),
|
||||
Mock.Of<IUserService>());
|
||||
|
||||
var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(Mock.Of<HttpContextBase>());
|
||||
|
||||
@@ -440,7 +440,6 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
new WebSecurity(http, Current.Services.UserService, globalSettings),
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
Enumerable.Empty<IMediaUrlProvider>(),
|
||||
globalSettings,
|
||||
new TestVariationContextAccessor());
|
||||
|
||||
|
||||
@@ -61,12 +61,10 @@ namespace Umbraco.Tests.Web
|
||||
|
||||
[TestCase("", "")]
|
||||
[TestCase("hello href=\"{localLink:1234}\" world ", "hello href=\"/my-test-url\" world ")]
|
||||
[TestCase("hello href=\"{localLink:umb://document/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"/my-test-url\" world ")]
|
||||
[TestCase("hello href=\"{localLink:umb://document/9931BDE0AAC34BABB838909A7B47570E}\" world ", "hello href=\"/my-test-url\" world ")]
|
||||
[TestCase("hello href=\"{localLink:umb://media/9931BDE0AAC34BABB838909A7B47570E}\" world ", "hello href=\"/media/1001/my-image.jpg\" world ")]
|
||||
[TestCase("hello href=\"{localLink:umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"/my-test-url\" world ")]
|
||||
[TestCase("hello href=\"{localLink:umb://document-type/9931BDE0AAC34BABB838909A7B47570E}\" world ", "hello href=\"/my-test-url\" world ")]
|
||||
//this one has an invalid char so won't match
|
||||
[TestCase("hello href=\"{localLink:umb^://document/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"{localLink:umb^://document/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ")]
|
||||
[TestCase("hello href=\"{localLink:umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"#\" world ")]
|
||||
[TestCase("hello href=\"{localLink:umb^://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"{localLink:umb^://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ")]
|
||||
public void ParseLocalLinks(string input, string result)
|
||||
{
|
||||
var serviceCtxMock = new TestObjects(null).GetServiceContextMock();
|
||||
@@ -79,7 +77,7 @@ namespace Umbraco.Tests.Web
|
||||
// return Attempt.Succeed(1234);
|
||||
// });
|
||||
|
||||
//setup a mock url provider which we'll use for testing
|
||||
//setup a mock url provider which we'll use fo rtesting
|
||||
var testUrlProvider = new Mock<IUrlProvider>();
|
||||
testUrlProvider
|
||||
.Setup(x => x.GetUrl(It.IsAny<UmbracoContext>(), It.IsAny<IPublishedContent>(), It.IsAny<UrlProviderMode>(), It.IsAny<string>(), It.IsAny<Uri>()))
|
||||
@@ -98,10 +96,6 @@ namespace Umbraco.Tests.Web
|
||||
Mock.Get(snapshot).Setup(x => x.Content).Returns(contentCache);
|
||||
var snapshotService = Mock.Of<IPublishedSnapshotService>();
|
||||
Mock.Get(snapshotService).Setup(x => x.CreatePublishedSnapshot(It.IsAny<string>())).Returns(snapshot);
|
||||
var media = Mock.Of<IPublishedContent>();
|
||||
Mock.Get(media).Setup(x => x.Url).Returns("/media/1001/my-image.jpg");
|
||||
var mediaCache = Mock.Of<IPublishedMediaCache>();
|
||||
Mock.Get(mediaCache).Setup(x => x.GetById(It.IsAny<Guid>())).Returns(media);
|
||||
|
||||
var umbracoContextFactory = new UmbracoContextFactory(
|
||||
Umbraco.Web.Composing.Current.UmbracoContextAccessor,
|
||||
@@ -111,12 +105,11 @@ namespace Umbraco.Tests.Web
|
||||
Mock.Of<IUmbracoSettingsSection>(section => section.WebRouting == Mock.Of<IWebRoutingSection>(routingSection => routingSection.UrlProviderMode == "Auto")),
|
||||
globalSettings,
|
||||
new UrlProviderCollection(new[] { testUrlProvider.Object }),
|
||||
new MediaUrlProviderCollection(Enumerable.Empty<IMediaUrlProvider>()),
|
||||
Mock.Of<IUserService>());
|
||||
|
||||
using (var reference = umbracoContextFactory.EnsureUmbracoContext(Mock.Of<HttpContextBase>()))
|
||||
{
|
||||
var output = TemplateUtilities.ParseInternalLinks(input, reference.UmbracoContext.UrlProvider, mediaCache);
|
||||
var output = TemplateUtilities.ParseInternalLinks(input, reference.UmbracoContext.UrlProvider);
|
||||
|
||||
Assert.AreEqual(result, output);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
@@ -32,7 +31,6 @@ namespace Umbraco.Tests.Web
|
||||
new WebSecurity(Mock.Of<HttpContextBase>(), Current.Services.UserService, TestObjects.GetGlobalSettings()),
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
new List<IUrlProvider>(),
|
||||
Enumerable.Empty<IMediaUrlProvider>(),
|
||||
TestObjects.GetGlobalSettings(),
|
||||
new TestVariationContextAccessor());
|
||||
var r1 = new RouteData();
|
||||
@@ -51,7 +49,6 @@ namespace Umbraco.Tests.Web
|
||||
new WebSecurity(Mock.Of<HttpContextBase>(), Current.Services.UserService, TestObjects.GetGlobalSettings()),
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
new List<IUrlProvider>(),
|
||||
Enumerable.Empty<IMediaUrlProvider>(),
|
||||
TestObjects.GetGlobalSettings(),
|
||||
new TestVariationContextAccessor());
|
||||
|
||||
@@ -80,7 +77,6 @@ namespace Umbraco.Tests.Web
|
||||
new WebSecurity(Mock.Of<HttpContextBase>(), Current.Services.UserService, TestObjects.GetGlobalSettings()),
|
||||
TestObjects.GetUmbracoSettings(),
|
||||
new List<IUrlProvider>(),
|
||||
Enumerable.Empty<IMediaUrlProvider>(),
|
||||
TestObjects.GetGlobalSettings(),
|
||||
new TestVariationContextAccessor());
|
||||
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": "last 2 version, not dead, > 0.5%, not ie 11"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
"presets": ["@babel/preset-env"]
|
||||
}
|
||||
@@ -6,6 +6,46 @@
|
||||
|
||||
This documentation relates to the angular, js, css and less APIs for developing back office components
|
||||
|
||||
##Running the site with mocked data
|
||||
|
||||
This won't require any database or setup, as everything is running through node. All you have to do is install
|
||||
node and grunt on either windows or OSX and the entire setup is ready for you.
|
||||
|
||||
|
||||
###Install node.js
|
||||
We need node to run tests and automated less compiling and other automated tasks. go to http://nodejs.org. Node.js is a powerfull javascript engine, which allows us to run all our tests and tasks written in javascript locally.
|
||||
|
||||
*note:* On windows you might need to restart explorer.exe to register node.
|
||||
|
||||
|
||||
###Install dependencies
|
||||
Next we need to install all the required packages. This is done with the package tool, included with node.js, open /Umbraco.Belle.Client in cmd.exe or osx terminal and run the command:
|
||||
|
||||
npm install
|
||||
|
||||
this will fetch all needed packages to your local machine.
|
||||
|
||||
|
||||
###Install grunt globally
|
||||
Grunt is a task runner for node.js, and we use it for all automated tasks in the build process. For convenience we need to install it globally on your machine, so it can be used directly in cmd.exe or the terminal.
|
||||
|
||||
So run the command:
|
||||
|
||||
npm install grunt-cli -g
|
||||
|
||||
*note:* On windows you might need to restart explorer.exe to register the grunt cmd.
|
||||
|
||||
*note:* On OSX you might need to run:
|
||||
|
||||
sudo npm install grunt-cli -g
|
||||
|
||||
Now that you have node and grunt installed, you can open `/Umbraco.Web.UI.Client` in either `cmd.exe` or terminal and run:
|
||||
|
||||
grunt dev
|
||||
|
||||
This will build the site, merge less files, run tests and create the /Build folder, and finally open the site in your
|
||||
browser.
|
||||
|
||||
##Getting started
|
||||
The current app is built, following conventions from angularJs and bootstrap. To get started with the applicaton you will need to atleast know the basics of these frameworks
|
||||
|
||||
|
||||
@@ -25,6 +25,10 @@ module.exports = {
|
||||
security: { files: ["./src/common/interceptors/**/*.js"], out: "umbraco.interceptors.js" }
|
||||
},
|
||||
|
||||
ts: {
|
||||
services: { files: ["./src/common/services/**/*.ts"], out: "./src/common/services/build/temp/" }
|
||||
},
|
||||
|
||||
//selectors for copying all views into the build
|
||||
//processed in the views task
|
||||
views:{
|
||||
|
||||
@@ -6,5 +6,5 @@ var runSequence = require('run-sequence');
|
||||
|
||||
// Build - build the files ready for production
|
||||
gulp.task('build', function(cb) {
|
||||
runSequence(["js", "dependencies", "less", "views"], "test:unit", cb);
|
||||
runSequence(["typescript", "js", "dependencies", "less", "views"], "test:unit", cb);
|
||||
});
|
||||
|
||||
@@ -6,5 +6,5 @@ var runSequence = require('run-sequence');
|
||||
|
||||
// Dev - build the files ready for development and start watchers
|
||||
gulp.task('dev', function(cb) {
|
||||
runSequence(["dependencies", "js", "less", "views"], "watch", cb);
|
||||
runSequence(["dependencies", "typescript", "js", "less", "views"], "watch", cb);
|
||||
});
|
||||
|
||||
@@ -9,5 +9,5 @@ gulp.task('fastdev', function(cb) {
|
||||
|
||||
global.isProd = false;
|
||||
|
||||
runSequence(["dependencies", "js", "less", "views"], "watch", cb);
|
||||
runSequence(["dependencies", "typescript", "js", "less", "views"], "watch", cb);
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
var config = require('../config');
|
||||
var gulp = require('gulp');
|
||||
|
||||
var _ = require('lodash');
|
||||
var MergeStream = require('merge-stream');
|
||||
|
||||
var processTs = require('../util/processTypescript');
|
||||
|
||||
/**************************
|
||||
* Copies all angular JS files into their seperate umbraco.*.js file
|
||||
**************************/
|
||||
gulp.task('typescript', function () {
|
||||
|
||||
//we run multiple streams, so merge them all together
|
||||
var stream = new MergeStream();
|
||||
|
||||
stream.add(
|
||||
gulp.src(config.sources.globs.js)
|
||||
.pipe(gulp.dest(config.root + config.targets.js))
|
||||
);
|
||||
|
||||
// compile TS
|
||||
_.forEach(config.sources.ts, function (group) {
|
||||
if(group.files.length > 0)
|
||||
stream.add (processTs(group.files, group.out));
|
||||
});
|
||||
|
||||
return stream;
|
||||
});
|
||||
@@ -7,7 +7,6 @@ var babel = require("gulp-babel");
|
||||
var sort = require('gulp-sort');
|
||||
var concat = require('gulp-concat');
|
||||
var wrap = require("gulp-wrap-js");
|
||||
var embedTemplates = require('gulp-angular-embed-templates');
|
||||
|
||||
module.exports = function(files, out) {
|
||||
|
||||
@@ -23,7 +22,6 @@ module.exports = function(files, out) {
|
||||
// sort files in stream by path or any custom sort comparator
|
||||
task = task.pipe(babel())
|
||||
.pipe(sort())
|
||||
.pipe(embedTemplates({ basePath: "./src/" }))
|
||||
.pipe(concat(out))
|
||||
.pipe(wrap('(function(){\n%= body %\n})();'))
|
||||
.pipe(gulp.dest(config.root + config.targets.js));
|
||||
@@ -31,4 +29,4 @@ module.exports = function(files, out) {
|
||||
|
||||
return task;
|
||||
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
var config = require('../config');
|
||||
var gulp = require('gulp');
|
||||
|
||||
var ts = require('gulp-typescript');
|
||||
|
||||
module.exports = function(files, out) {
|
||||
|
||||
var task = gulp.src(files);
|
||||
|
||||
var tsProject = ts.createProject('tsconfig.json');
|
||||
|
||||
|
||||
// sort files in stream by path or any custom sort comparator
|
||||
task = task.pipe(tsProject())
|
||||
.pipe(gulp.dest(out));
|
||||
|
||||
|
||||
return task;
|
||||
|
||||
};
|
||||
+847
-329
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,7 @@
|
||||
"diff": "3.5.0",
|
||||
"flatpickr": "4.5.2",
|
||||
"font-awesome": "4.7.0",
|
||||
"jquery": "^3.4.0",
|
||||
"jquery": "3.3.1",
|
||||
"jquery-ui-dist": "1.12.1",
|
||||
"jquery-ui-touch-punch": "0.2.3",
|
||||
"lazyload-js": "1.0.0",
|
||||
@@ -41,6 +41,7 @@
|
||||
"spectrum-colorpicker": "1.8.0",
|
||||
"tinymce": "4.9.2",
|
||||
"typeahead.js": "0.11.1",
|
||||
"typescript": "^3.2.1",
|
||||
"underscore": "1.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -50,7 +51,6 @@
|
||||
"cssnano": "4.1.7",
|
||||
"fs": "0.0.2",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-angular-embed-templates": "^2.3.0",
|
||||
"gulp-babel": "8.0.0",
|
||||
"gulp-clean-css": "4.0.0",
|
||||
"gulp-cli": "^2.0.1",
|
||||
@@ -65,6 +65,7 @@
|
||||
"gulp-postcss": "8.0.0",
|
||||
"gulp-rename": "1.4.0",
|
||||
"gulp-sort": "2.0.0",
|
||||
"gulp-typescript": "^5.0.1",
|
||||
"gulp-watch": "5.0.1",
|
||||
"gulp-wrap": "0.14.0",
|
||||
"gulp-wrap-js": "0.4.1",
|
||||
@@ -77,7 +78,6 @@
|
||||
"lodash": "4.17.11",
|
||||
"marked": "^0.5.2",
|
||||
"merge-stream": "1.0.1",
|
||||
"run-sequence": "2.2.1",
|
||||
"caniuse-lite": "^1.0.30000966"
|
||||
"run-sequence": "2.2.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
declare var angular: any;
|
||||
declare var _: any;
|
||||
declare var $q: any;
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
interface StringConstructor {
|
||||
CreateGuid(): string;
|
||||
}
|
||||
+3
-5
@@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function AppHeaderDirective(eventsService, appState, userService, focusService) {
|
||||
function AppHeaderDirective(eventsService, appState, userService) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
@@ -54,9 +54,7 @@
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
scope.rememberFocus = focusService.rememberFocus;
|
||||
|
||||
|
||||
scope.searchClick = function() {
|
||||
var showSearch = appState.getSearchState("show");
|
||||
appState.setSearchState("show", !showSearch);
|
||||
@@ -103,4 +101,4 @@
|
||||
|
||||
angular.module("umbraco.directives").directive("umbAppHeader", AppHeaderDirective);
|
||||
|
||||
})();
|
||||
})();
|
||||
+9
-18
@@ -16,6 +16,7 @@
|
||||
function UmbLoginController($scope, $location, currentUserResource, formHelper, mediaHelper, umbRequestHelper, Upload, localizationService, userService, externalLoginInfo, resetPasswordCodeInfo, $timeout, authResource, $q) {
|
||||
|
||||
const vm = this;
|
||||
let twoFactorloginDialog = null;
|
||||
|
||||
vm.invitedUser = null;
|
||||
|
||||
@@ -68,9 +69,7 @@
|
||||
).then(function (data) {
|
||||
vm.labels.usernameLabel = data[0];
|
||||
vm.labels.usernamePlaceholder = data[1];
|
||||
});
|
||||
|
||||
vm.twoFactor = {};
|
||||
})
|
||||
|
||||
function onInit() {
|
||||
|
||||
@@ -127,7 +126,6 @@
|
||||
function togglePassword() {
|
||||
var elem = $("form[name='vm.loginForm'] input[name='password']");
|
||||
elem.attr("type", (elem.attr("type") === "text" ? "password" : "text"));
|
||||
elem.focus();
|
||||
$(".password-text.show, .password-text.hide").toggle();
|
||||
}
|
||||
|
||||
@@ -188,18 +186,15 @@
|
||||
vm.view = "set-password";
|
||||
}
|
||||
|
||||
function loginSubmit() {
|
||||
|
||||
// make sure that we are returning to the login view.
|
||||
vm.view = "login";
|
||||
|
||||
function loginSubmit(login, password) {
|
||||
|
||||
// TODO: Do validation properly like in the invite password update
|
||||
|
||||
//if the login and password are not empty we need to automatically
|
||||
// validate them - this is because if there are validation errors on the server
|
||||
// then the user has to change both username & password to resubmit which isn't ideal,
|
||||
// so if they're not empty, we'll just make sure to set them to valid.
|
||||
if (vm.login && vm.password && vm.login.length > 0 && vm.password.length > 0) {
|
||||
if (login && password && login.length > 0 && password.length > 0) {
|
||||
vm.loginForm.username.$setValidity('auth', true);
|
||||
vm.loginForm.password.$setValidity('auth', true);
|
||||
}
|
||||
@@ -210,7 +205,7 @@
|
||||
|
||||
vm.loginStates.submitButton = "busy";
|
||||
|
||||
userService.authenticate(vm.login, vm.password)
|
||||
userService.authenticate(login, password)
|
||||
.then(function (data) {
|
||||
vm.loginStates.submitButton = "success";
|
||||
userService._retryRequestQueue(true);
|
||||
@@ -223,7 +218,7 @@
|
||||
//is Two Factor required?
|
||||
if (reason.status === 402) {
|
||||
vm.errorMsg = "Additional authentication required";
|
||||
show2FALoginDialog(reason.data.twoFactorView);
|
||||
show2FALoginDialog(reason.data.twoFactorView, submit);
|
||||
}
|
||||
else {
|
||||
vm.loginStates.submitButton = "error";
|
||||
@@ -407,12 +402,8 @@
|
||||
});
|
||||
}
|
||||
|
||||
function show2FALoginDialog(viewPath) {
|
||||
vm.twoFactor.submitCallback = function submitCallback() {
|
||||
vm.onLogin();
|
||||
}
|
||||
vm.twoFactor.view = viewPath;
|
||||
vm.view = "2fa-login";
|
||||
function show2FALoginDialog(view, callback) {
|
||||
// TODO: show 2FA window
|
||||
}
|
||||
|
||||
function resetInputValidation() {
|
||||
|
||||
+2
-12
@@ -13,7 +13,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
function umbSearchController($timeout, backdropService, searchService, focusService) {
|
||||
function umbSearchController($timeout, backdropService, searchService) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
@@ -25,9 +25,6 @@
|
||||
vm.handleKeyUp = handleKeyUp;
|
||||
vm.closeSearch = closeSearch;
|
||||
vm.focusSearch = focusSearch;
|
||||
|
||||
//we need to capture the focus before this element is initialized.
|
||||
vm.focusBeforeOpening = focusService.getLastKnownFocus();
|
||||
|
||||
function onInit() {
|
||||
vm.searchQuery = "";
|
||||
@@ -73,10 +70,6 @@
|
||||
* @param {object} event
|
||||
*/
|
||||
function handleKeyUp(event) {
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
// esc
|
||||
if(event.keyCode === 27) {
|
||||
closeSearch();
|
||||
@@ -87,9 +80,6 @@
|
||||
* Used to proxy a callback
|
||||
*/
|
||||
function closeSearch() {
|
||||
if(vm.focusBeforeOpening) {
|
||||
vm.focusBeforeOpening.focus();
|
||||
}
|
||||
if(vm.onClose) {
|
||||
vm.onClose();
|
||||
}
|
||||
@@ -125,4 +115,4 @@
|
||||
|
||||
angular.module('umbraco.directives').component('umbSearch', umbSearch);
|
||||
|
||||
})();
|
||||
})();
|
||||
-2
@@ -117,8 +117,6 @@ Use this directive to render an umbraco button. The directive can be used to gen
|
||||
vm.innerState = "init";
|
||||
|
||||
vm.buttonLabel = vm.label;
|
||||
// is this a primary button style (i.e. anything but an 'info' button)?
|
||||
vm.isPrimaryButtonStyle = vm.buttonStyle && vm.buttonStyle !== 'info';
|
||||
|
||||
if (vm.buttonStyle) {
|
||||
|
||||
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbToggleGroup
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to render a group of toggle buttons.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-toggle-group
|
||||
items="vm.items"
|
||||
on-click="vm.toggle(item)">
|
||||
</umb-toggle-group>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
vm.toggle = toggle;
|
||||
|
||||
function toggle(item) {
|
||||
if(item.checked) {
|
||||
// do something if item is checked
|
||||
}
|
||||
else {
|
||||
// do something else if item is unchecked
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
vm.items = [{
|
||||
name: "Item 1",
|
||||
description: "Item 1 description",
|
||||
checked: false,
|
||||
disabled: false
|
||||
}, {
|
||||
name: "Item 2",
|
||||
description: "Item 2 description",
|
||||
checked: true,
|
||||
disabled: true
|
||||
}];
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {Array} items The items to list in the toggle group
|
||||
@param {callback} onClick The function which should be called when the toggle is clicked for one of the items.
|
||||
|
||||
**/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function ToggleGroupDirective() {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
scope.change = function(item) {
|
||||
if (item.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
item.checked = !item.checked;
|
||||
if(scope.onClick) {
|
||||
scope.onClick({'item': item});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/buttons/umb-toggle-group.html',
|
||||
scope: {
|
||||
items: "=",
|
||||
onClick: "&"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbToggleGroup', ToggleGroupDirective);
|
||||
|
||||
})();
|
||||
+2
-2
@@ -55,9 +55,9 @@
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// if we still dont have a app, lets show the first one:
|
||||
if (isAppPresent === false && content.apps.length) {
|
||||
if (isAppPresent === false) {
|
||||
content.apps[0].active = true;
|
||||
$scope.appChanged(content.apps[0]);
|
||||
}
|
||||
|
||||
+3
-5
@@ -198,11 +198,9 @@
|
||||
return a.alias === "umbContent";
|
||||
});
|
||||
|
||||
if (contentApp) {
|
||||
//The view model for the content app is simply the index of the variant being edited
|
||||
var variantIndex = vm.content.variants.indexOf(variant);
|
||||
contentApp.viewModel = variantIndex;
|
||||
}
|
||||
//The view model for the content app is simply the index of the variant being edited
|
||||
var variantIndex = vm.content.variants.indexOf(variant);
|
||||
contentApp.viewModel = variantIndex;
|
||||
|
||||
// make sure the same app it set to active in the new variant
|
||||
if(activeAppAlias) {
|
||||
|
||||
-3
@@ -47,9 +47,6 @@ The sub header is sticky and will follow along down the page when scrolling.
|
||||
transclude: true,
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
scope: {
|
||||
"appearance": "@?"
|
||||
},
|
||||
templateUrl: 'views/components/editor/subheader/umb-editor-sub-header.html'
|
||||
};
|
||||
|
||||
|
||||
+2
-4
@@ -4,7 +4,7 @@
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives")
|
||||
.directive('hotkey', function($window, keyboardService, $log, focusService) {
|
||||
.directive('hotkey', function($window, keyboardService, $log) {
|
||||
|
||||
return function(scope, el, attrs) {
|
||||
|
||||
@@ -28,9 +28,7 @@ angular.module("umbraco.directives")
|
||||
}
|
||||
|
||||
keyboardService.bind(keyCombo, function() {
|
||||
|
||||
focusService.rememberFocus();
|
||||
|
||||
|
||||
var element = $(el);
|
||||
var activeElementType = document.activeElement.tagName;
|
||||
var clickableElements = ["A", "BUTTON"];
|
||||
|
||||
+29
-60
@@ -6,7 +6,7 @@
|
||||
**/
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbImageCrop',
|
||||
function ($timeout, cropperHelper) {
|
||||
function ($timeout, localizationService, cropperHelper, $log) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
@@ -21,9 +21,6 @@ angular.module("umbraco.directives")
|
||||
},
|
||||
|
||||
link: function(scope, element, attrs) {
|
||||
|
||||
let sliderRef = null;
|
||||
|
||||
scope.width = 400;
|
||||
scope.height = 320;
|
||||
|
||||
@@ -33,56 +30,12 @@ angular.module("umbraco.directives")
|
||||
viewport:{},
|
||||
margin: 20,
|
||||
scale: {
|
||||
min: 0,
|
||||
min: 0.3,
|
||||
max: 3,
|
||||
current: 1
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
scope.sliderOptions = {
|
||||
"start": scope.dimensions.scale.current,
|
||||
"step": 0.001,
|
||||
"tooltips": [false],
|
||||
"format": {
|
||||
to: function (value) {
|
||||
return parseFloat(parseFloat(value).toFixed(3)); //Math.round(value);
|
||||
},
|
||||
from: function (value) {
|
||||
return parseFloat(parseFloat(value).toFixed(3)); //Math.round(value);
|
||||
}
|
||||
},
|
||||
"range": {
|
||||
"min": scope.dimensions.scale.min,
|
||||
"max": scope.dimensions.scale.max
|
||||
}
|
||||
};
|
||||
|
||||
scope.setup = function (slider) {
|
||||
sliderRef = slider;
|
||||
|
||||
// Set slider handle position
|
||||
sliderRef.noUiSlider.set(scope.dimensions.scale.current);
|
||||
|
||||
// Update slider range min/max
|
||||
sliderRef.noUiSlider.updateOptions({
|
||||
"range": {
|
||||
"min": scope.dimensions.scale.min,
|
||||
"max": scope.dimensions.scale.max
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
scope.slide = function (values) {
|
||||
if (values) {
|
||||
scope.dimensions.scale.current = parseFloat(values);
|
||||
}
|
||||
};
|
||||
|
||||
scope.change = function (values) {
|
||||
if (values) {
|
||||
scope.dimensions.scale.current = parseFloat(values);
|
||||
}
|
||||
};
|
||||
|
||||
//live rendering of viewport and image styles
|
||||
scope.style = function () {
|
||||
@@ -110,6 +63,7 @@ angular.module("umbraco.directives")
|
||||
constraints.top.min = scope.dimensions.margin + scope.dimensions.cropper.height - scope.dimensions.image.height;
|
||||
};
|
||||
|
||||
|
||||
var setDimensions = function(originalImage){
|
||||
originalImage.width("auto");
|
||||
originalImage.height("auto");
|
||||
@@ -177,11 +131,13 @@ angular.module("umbraco.directives")
|
||||
|
||||
scope.dimensions.scale.current = scope.dimensions.image.ratio;
|
||||
|
||||
// Update min and max based on original width/height
|
||||
//min max based on original width/height
|
||||
scope.dimensions.scale.min = ratioCalculation.ratio;
|
||||
scope.dimensions.scale.max = 2;
|
||||
scope.dimensions.scale.max = 2;
|
||||
};
|
||||
|
||||
|
||||
|
||||
var validatePosition = function(left, top){
|
||||
if(left > constraints.left.max)
|
||||
{
|
||||
@@ -235,6 +191,8 @@ angular.module("umbraco.directives")
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
var init = function(image){
|
||||
scope.loaded = false;
|
||||
|
||||
@@ -261,10 +219,10 @@ angular.module("umbraco.directives")
|
||||
};
|
||||
|
||||
|
||||
// Watchers
|
||||
/// WATCHERS ////
|
||||
scope.$watchCollection('[width, height]', function(newValues, oldValues){
|
||||
// We have to reinit the whole thing if
|
||||
// one of the external params changes
|
||||
//we have to reinit the whole thing if
|
||||
//one of the external params changes
|
||||
if(newValues !== oldValues){
|
||||
setDimensions($image);
|
||||
setConstraints();
|
||||
@@ -272,18 +230,29 @@ angular.module("umbraco.directives")
|
||||
});
|
||||
|
||||
var throttledResizing = _.throttle(function(){
|
||||
resizeImageToScale(scope.dimensions.scale.current);
|
||||
resizeImageToScale(scope.dimensions.scale.current);
|
||||
calculateCropBox();
|
||||
}, 15);
|
||||
|
||||
// Happens when we change the scale
|
||||
scope.$watch("dimensions.scale.current", function (newValue, oldValue) {
|
||||
if (scope.loaded) {
|
||||
|
||||
//happens when we change the scale
|
||||
scope.$watch("dimensions.scale.current", function(){
|
||||
if(scope.loaded){
|
||||
throttledResizing();
|
||||
}
|
||||
});
|
||||
|
||||
// Init
|
||||
//ie hack
|
||||
if(window.navigator.userAgent.indexOf("MSIE ") >= 0){
|
||||
var ranger = element.find("input");
|
||||
ranger.on("change",function(){
|
||||
scope.$apply(function(){
|
||||
scope.dimensions.scale.current = ranger.val();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//// INIT /////
|
||||
$image.on("load", function(){
|
||||
$timeout(function(){
|
||||
init($image);
|
||||
|
||||
+1
-3
@@ -295,8 +295,7 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
scope.closeOverLay();
|
||||
});
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
@@ -512,7 +511,6 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
model: "=",
|
||||
view: "=",
|
||||
position: "@",
|
||||
size: "=?",
|
||||
parentScope: "=?"
|
||||
},
|
||||
link: link
|
||||
|
||||
-7
@@ -41,7 +41,6 @@
|
||||
vm.removeTag = removeTag;
|
||||
vm.showPrompt = showPrompt;
|
||||
vm.hidePrompt = hidePrompt;
|
||||
vm.onKeyUpOnTag = onKeyUpOnTag;
|
||||
|
||||
vm.htmlId = "t" + String.CreateGuid();
|
||||
vm.isLoading = true;
|
||||
@@ -273,12 +272,6 @@
|
||||
vm.promptIsVisible = "-1";
|
||||
}
|
||||
|
||||
function onKeyUpOnTag(tag, $event) {
|
||||
if ($event.keyCode === 8 || $event.keyCode === 46) {
|
||||
removeTag(tag);
|
||||
}
|
||||
}
|
||||
|
||||
// helper method to remove current tags
|
||||
function removeCurrentTagsFromSuggestions(suggestions) {
|
||||
return $.grep(suggestions, function (suggestion) {
|
||||
|
||||
-7
@@ -12,7 +12,6 @@ function treeSearchBox(localizationService, searchService, $q) {
|
||||
searchFromName: "@",
|
||||
showSearch: "@",
|
||||
section: "@",
|
||||
ignoreUserStartNodes: "@",
|
||||
hideSearchCallback: "=",
|
||||
searchCallback: "="
|
||||
},
|
||||
@@ -35,7 +34,6 @@ function treeSearchBox(localizationService, searchService, $q) {
|
||||
scope.showSearch = "false";
|
||||
}
|
||||
|
||||
|
||||
//used to cancel any request in progress if another one needs to take it's place
|
||||
var canceler = null;
|
||||
|
||||
@@ -62,11 +60,6 @@ function treeSearchBox(localizationService, searchService, $q) {
|
||||
searchArgs["searchFrom"] = scope.searchFromId;
|
||||
}
|
||||
|
||||
//append ignoreUserStartNodes value if there is one
|
||||
if (scope.ignoreUserStartNodes) {
|
||||
searchArgs["ignoreUserStartNodes"] = scope.ignoreUserStartNodes;
|
||||
}
|
||||
|
||||
searcher(searchArgs).then(function (data) {
|
||||
scope.searchCallback(data);
|
||||
//set back to null so it can be re-created
|
||||
|
||||
@@ -60,7 +60,6 @@ function confirmDirective() {
|
||||
link: function (scope, element, attr, ctrl) {
|
||||
scope.showCancel = false;
|
||||
scope.showConfirm = false;
|
||||
scope.confirmButtonState = "init";
|
||||
|
||||
if (scope.onConfirm) {
|
||||
scope.showConfirm = true;
|
||||
@@ -69,15 +68,6 @@ function confirmDirective() {
|
||||
if (scope.onCancel) {
|
||||
scope.showCancel = true;
|
||||
}
|
||||
|
||||
scope.confirm = function () {
|
||||
if (!scope.onConfirm) {
|
||||
return;
|
||||
}
|
||||
|
||||
scope.confirmButtonState = "busy";
|
||||
scope.onConfirm();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+6
-6
@@ -3,7 +3,7 @@
|
||||
function () {
|
||||
|
||||
var link = function ($scope) {
|
||||
|
||||
|
||||
// Clone the model because some property editors
|
||||
// do weird things like updating and config values
|
||||
// so we want to ensure we start from a fresh every
|
||||
@@ -12,10 +12,10 @@
|
||||
$scope.nodeContext = $scope.model;
|
||||
|
||||
// Find the selected tab
|
||||
var selectedTab = $scope.model.variants[0].tabs[0];
|
||||
var selectedTab = $scope.model.tabs[0];
|
||||
|
||||
if ($scope.tabAlias) {
|
||||
angular.forEach($scope.model.variants[0].tabs, function (tab) {
|
||||
angular.forEach($scope.model.tabs, function (tab) {
|
||||
if (tab.alias.toLowerCase() === $scope.tabAlias.toLowerCase()) {
|
||||
selectedTab = tab;
|
||||
return;
|
||||
@@ -31,9 +31,9 @@
|
||||
|
||||
// Tell inner controls we are submitting
|
||||
$scope.$broadcast("formSubmitting", { scope: $scope });
|
||||
|
||||
|
||||
// Sync the values back
|
||||
angular.forEach($scope.ngModel.variants[0].tabs, function (tab) {
|
||||
angular.forEach($scope.ngModel.tabs, function (tab) {
|
||||
if (tab.alias.toLowerCase() === selectedTab.alias.toLowerCase()) {
|
||||
|
||||
var localPropsMap = selectedTab.properties.reduce(function (map, obj) {
|
||||
@@ -94,4 +94,4 @@
|
||||
// },
|
||||
// link: link
|
||||
// }
|
||||
//});
|
||||
//});
|
||||
@@ -91,10 +91,6 @@ Use this directive to generate a pagination.
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
function activate() {
|
||||
// page number is sometimes a string - let's make sure it's an int before we do anything with it
|
||||
if (scope.pageNumber) {
|
||||
scope.pageNumber = parseInt(scope.pageNumber);
|
||||
}
|
||||
|
||||
scope.pagination = [];
|
||||
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function PermissionDirective() {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
scope.change = function() {
|
||||
scope.selected = !scope.selected;
|
||||
if(scope.onChange) {
|
||||
scope.onChange({'selected': scope.selected});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/users/umb-permission.html',
|
||||
scope: {
|
||||
name: "=",
|
||||
description: "=?",
|
||||
selected: "=",
|
||||
onChange: "&"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbPermission', PermissionDirective);
|
||||
|
||||
})();
|
||||
@@ -1,31 +0,0 @@
|
||||
/**
|
||||
* @ngdoc filter
|
||||
* @name umbraco.filters.filter:truncate
|
||||
* @namespace truncateFilter
|
||||
*
|
||||
* param {any} wordwise if true, the string will be cut after last fully displayed word.
|
||||
* param {any} max max length of the outputtet string
|
||||
* param {any} tail option tail, defaults to: ' ...'
|
||||
*
|
||||
* @description
|
||||
* Limits the length of a string, if a cut happens only the string will be appended with three dots to indicate that more is available.
|
||||
*/
|
||||
angular.module("umbraco.filters").filter('truncate',
|
||||
function () {
|
||||
return function (value, wordwise, max, tail) {
|
||||
if (!value) return '';
|
||||
max = parseInt(max, 10);
|
||||
if (!max) return value;
|
||||
if (value.length <= max) return value;
|
||||
|
||||
value = value.substr(0, max);
|
||||
if (wordwise) {
|
||||
var lastspace = value.lastIndexOf(' ');
|
||||
if (lastspace != -1) {
|
||||
value = value.substr(0, lastspace);
|
||||
}
|
||||
}
|
||||
return value + (tail || (wordwise ? ' …' : '…'));
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -59,27 +59,20 @@
|
||||
}
|
||||
|
||||
//A 401 means that the user is not logged in
|
||||
if (rejection.status === 401) {
|
||||
//avoid an infinite loop
|
||||
var umbRequestHelper = $injector.get('umbRequestHelper');
|
||||
var getCurrentUserPath = umbRequestHelper.getApiUrl("authenticationApiBaseUrl", "GetCurrentUser");
|
||||
if (!rejection.config.url.endsWith(getCurrentUserPath)) {
|
||||
if (rejection.status === 401 && !rejection.config.url.endsWith("umbraco/backoffice/UmbracoApi/Authentication/GetCurrentUser")) {
|
||||
|
||||
var userService = $injector.get('userService'); // see above
|
||||
var userService = $injector.get('userService'); // see above
|
||||
|
||||
//Associate the user name with the retry to ensure we retry for the right user
|
||||
return userService.getCurrentUser()
|
||||
.then(function(user) {
|
||||
var userName = user ? user.name : null;
|
||||
//The request bounced because it was not authorized - add a new request to the retry queue
|
||||
return requestRetryQueue.pushRetryFn('unauthorized-server',
|
||||
userName,
|
||||
function retryRequest() {
|
||||
// We must use $injector to get the $http service to prevent circular dependency
|
||||
return $injector.get('$http')(rejection.config);
|
||||
});
|
||||
//Associate the user name with the retry to ensure we retry for the right user
|
||||
return userService.getCurrentUser()
|
||||
.then(function (user) {
|
||||
var userName = user ? user.name : null;
|
||||
//The request bounced because it was not authorized - add a new request to the retry queue
|
||||
return requestRetryQueue.pushRetryFn('unauthorized-server', userName, function retryRequest() {
|
||||
// We must use $injector to get the $http service to prevent circular dependency
|
||||
return $injector.get('$http')(rejection.config);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (rejection.status === 404) {
|
||||
|
||||
|
||||
@@ -215,6 +215,14 @@ angular.module('umbraco.mocks').
|
||||
"placeholders_nameentity": "Name the %0%...",
|
||||
"placeholders_search": "Type to search...",
|
||||
"placeholders_filter": "Type to filter...",
|
||||
"editcontenttype_allowedchildnodetypes": "Allowed child nodetypes",
|
||||
"editcontenttype_create": "Create",
|
||||
"editcontenttype_deletetab": "Delete tab",
|
||||
"editcontenttype_description": "Description",
|
||||
"editcontenttype_newtab": "New tab",
|
||||
"editcontenttype_tab": "Tab",
|
||||
"editcontenttype_thumbnail": "Thumbnail",
|
||||
"editcontenttype_iscontainercontenttype": "Use as container content type",
|
||||
"editdatatype_addPrevalue": "Add prevalue",
|
||||
"editdatatype_dataBaseDatatype": "Database datatype",
|
||||
"editdatatype_guid": "Property editor GUID",
|
||||
|
||||
@@ -365,28 +365,17 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} id id of content item to return
|
||||
* @param {Bool} options.ignoreUserStartNodes set to true to allow a user to choose nodes that they normally don't have access to
|
||||
* @param {Int} culture optional culture to retrieve the item in
|
||||
* @returns {Promise} resourcePromise object containing the content item.
|
||||
*
|
||||
*/
|
||||
getById: function (id, options) {
|
||||
var defaults = {
|
||||
ignoreUserStartNodes: false
|
||||
};
|
||||
if (options === undefined) {
|
||||
options = {};
|
||||
}
|
||||
//overwrite the defaults if there are any specified
|
||||
angular.extend(defaults, options);
|
||||
//now copy back to the options we will use
|
||||
options = defaults;
|
||||
|
||||
getById: function (id) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetById",
|
||||
[{ id: id }, { ignoreUserStartNodes: options.ignoreUserStartNodes }])),
|
||||
{ id: id })),
|
||||
'Failed to retrieve data for content id ' + id)
|
||||
.then(function (result) {
|
||||
return $q.when(umbDataFormatter.formatContentGetData(result));
|
||||
|
||||
@@ -344,12 +344,6 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter, loca
|
||||
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "Import", { file: file })),
|
||||
"Failed to import document type " + file
|
||||
);
|
||||
},
|
||||
|
||||
createDefaultTemplate: function (id) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCreateDefaultTemplate", { id: id })),
|
||||
'Failed to create default template for content type with id ' + id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -284,31 +284,15 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
* @returns {Promise} resourcePromise object containing the entity.
|
||||
*
|
||||
*/
|
||||
getAncestors: function (id, type, culture, options) {
|
||||
var defaults = {
|
||||
ignoreUserStartNodes: false
|
||||
};
|
||||
if (options === undefined) {
|
||||
options = {};
|
||||
}
|
||||
//overwrite the defaults if there are any specified
|
||||
angular.extend(defaults, options);
|
||||
//now copy back to the options we will use
|
||||
options = defaults;
|
||||
getAncestors: function (id, type, culture) {
|
||||
if (culture === undefined) culture = "";
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetAncestors",
|
||||
[
|
||||
{ id: id },
|
||||
{ type: type },
|
||||
{ culture: culture },
|
||||
{ ignoreUserStartNodes: options.ignoreUserStartNodes }
|
||||
])),
|
||||
|
||||
'Failed to retrieve ancestor data for id ' + id);
|
||||
[{ id: id }, { type: type }, { culture: culture }])),
|
||||
'Failed to retrieve ancestor data for id ' + id);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -440,8 +424,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
pageNumber: 1,
|
||||
filter: '',
|
||||
orderDirection: "Ascending",
|
||||
orderBy: "SortOrder",
|
||||
ignoreUserStartNodes: false
|
||||
orderBy: "SortOrder"
|
||||
};
|
||||
if (options === undefined) {
|
||||
options = {};
|
||||
@@ -470,8 +453,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
pageSize: options.pageSize,
|
||||
orderBy: options.orderBy,
|
||||
orderDirection: options.orderDirection,
|
||||
filter: encodeURIComponent(options.filter),
|
||||
ignoreUserStartNodes: options.ignoreUserStartNodes
|
||||
filter: encodeURIComponent(options.filter)
|
||||
}
|
||||
)),
|
||||
'Failed to retrieve child data for id ' + parentId);
|
||||
@@ -499,19 +481,12 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
* @returns {Promise} resourcePromise object containing the entity array.
|
||||
*
|
||||
*/
|
||||
search: function (query, type, options, canceler) {
|
||||
search: function (query, type, searchFrom, canceler) {
|
||||
|
||||
var args = [{ query: query }, { type: type }];
|
||||
|
||||
if(options !== undefined) {
|
||||
if (options.searchFrom) {
|
||||
args.push({ searchFrom: options.searchFrom });
|
||||
}
|
||||
if (options.ignoreUserStartNodes) {
|
||||
args.push({ ignoreUserStartNodes: options.ignoreUserStartNodes });
|
||||
}
|
||||
if (searchFrom) {
|
||||
args.push({ searchFrom: searchFrom });
|
||||
}
|
||||
|
||||
|
||||
var httpConfig = {};
|
||||
if (canceler) {
|
||||
|
||||
@@ -53,7 +53,7 @@ function logResource($q, $http, umbRequestHelper) {
|
||||
*
|
||||
* @param {Object} options options object
|
||||
* @param {Int} options.id the id of the entity
|
||||
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 10
|
||||
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 10, set to 0 to disable paging
|
||||
* @param {Int} options.pageNumber if paging data, current page index, default = 1
|
||||
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Descending`
|
||||
* @param {Date} options.sinceDate if provided this will only get log entries going back to this date
|
||||
@@ -122,7 +122,7 @@ function logResource($q, $http, umbRequestHelper) {
|
||||
* </pre>
|
||||
*
|
||||
* @param {Object} options options object
|
||||
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 10
|
||||
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 10, set to 0 to disable paging
|
||||
* @param {Int} options.pageNumber if paging data, current page index, default = 1
|
||||
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Descending`
|
||||
* @param {Date} options.sinceDate if provided this will only get log entries going back to this date
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user