Compare commits
127 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 92ef071883 | |||
| b42d0bc17e | |||
| 020a416dc5 | |||
| d491c133a7 | |||
| b68dd6b35c | |||
| ba9d023cc0 | |||
| eb6fe1e4d3 | |||
| c972ae566e | |||
| 320b53ae3c | |||
| 84f94d6471 | |||
| f758eb6a62 | |||
| 7ec4d3f26d | |||
| 2a0d2bdb86 | |||
| 24d3e465ea | |||
| d987dfb5a2 | |||
| 2ede32fe70 | |||
| fce8c9d3ec | |||
| f5194efb6e | |||
| 1b360226d6 | |||
| 524d6fb76a | |||
| 7185a6dba5 | |||
| 2496a8e77e | |||
| 13e8e972eb | |||
| d631039c0d | |||
| b1e879bf68 | |||
| 95b9a46b88 | |||
| 766ca78725 | |||
| 3ca4fb76b2 | |||
| 0a76757cea | |||
| 8fb446960c | |||
| 1cf40aca07 | |||
| aadcdc9c15 | |||
| e04eed41e7 | |||
| 62887607ff | |||
| 54a639ffcd | |||
| 9f16bee040 | |||
| 976d1b1ff6 | |||
| 8a4e39a999 | |||
| f325794523 | |||
| 0b3733f992 | |||
| 2926a79c3f | |||
| ef7a6f19ba | |||
| 95a4bb9ba6 | |||
| 32b7871eaf | |||
| 3ec6d2b82f | |||
| cd03e80410 | |||
| 9ed3561b56 | |||
| 28da44f0de | |||
| f8d7aeec80 | |||
| dacec47cd9 | |||
| 57f06ba447 | |||
| 82c1c95e35 | |||
| fa6c215849 | |||
| 420746397d | |||
| 142a9963af | |||
| b656db3af3 | |||
| d697c590e7 | |||
| 1dd103caa3 | |||
| a55cd67fd6 | |||
| 43bfd6e472 | |||
| afa81be102 | |||
| b07665f4d4 | |||
| 0ebd66d926 | |||
| 8d45898274 | |||
| a99a33477a | |||
| b42d3b226d | |||
| b6925f9f07 | |||
| ddd0e8abb5 | |||
| e07f573683 | |||
| ffbb1a85ab | |||
| ac9c938e92 | |||
| 1f88960b3f | |||
| d8edf67b82 | |||
| 762656e964 | |||
| 46a4f9242c | |||
| 8cae2526d5 | |||
| 6b313aba48 | |||
| 365a8e85e9 | |||
| 7b4c58538d | |||
| e41c99d5bc | |||
| a49dd36461 | |||
| 82a1e85431 | |||
| 5f9dddafd8 | |||
| 836297df58 | |||
| 1c7d83f589 | |||
| 157428dbc8 | |||
| a2a81222e6 | |||
| 5abbca0f5d | |||
| 0bcaa0da7f | |||
| 922942197f | |||
| b8975de04d | |||
| f00950bfe4 | |||
| 80d012f3ad | |||
| 654efd1128 | |||
| aa2375b8ba | |||
| f6532d2743 | |||
| 8c334a8c95 | |||
| 42cd71ef6c | |||
| 5956394bf1 | |||
| d1e9fb6d9f | |||
| 48dcc373dc | |||
| c9961b5192 | |||
| 03d3503531 | |||
| 9acba1d6d7 | |||
| 659f47c038 | |||
| 78613823ae | |||
| cb7f26c998 | |||
| 16b5c86192 | |||
| c83ab00827 | |||
| 937e840104 | |||
| 8d49c730d5 | |||
| fadb503b97 | |||
| 289bed8fd2 | |||
| eec1048631 | |||
| 313d77eb91 | |||
| b048341da0 | |||
| 03cb54e931 | |||
| 150b67d10f | |||
| ac88da4188 | |||
| cca27e064a | |||
| 4e5019d5af | |||
| f1a312b14a | |||
| da0b935604 | |||
| b91a06ab98 | |||
| d61fb5d94d | |||
| 3b424274ee | |||
| b763c2ab2f |
+10
-1
@@ -1,5 +1,9 @@
|
||||
@ECHO OFF
|
||||
SET release=7.1.2
|
||||
IF NOT EXIST UmbracoVersion.txt (
|
||||
ECHO UmbracoVersion.txt missing!
|
||||
GOTO :showerror
|
||||
)
|
||||
SET /p release=<UmbracoVersion.txt
|
||||
SET comment=
|
||||
SET version=%release%
|
||||
|
||||
@@ -15,6 +19,11 @@ SET nuGetFolder=%CD%\..\src\packages\
|
||||
ECHO Removing the belle build folder to make sure everything is clean as a whistle
|
||||
RD ..\src\Umbraco.Web.UI.Client\build /Q /S
|
||||
|
||||
ECHO Removing existing built files to make sure everything is clean as a whistle
|
||||
DEL /F /Q UmbracoCms.*.zip
|
||||
DEL /F /Q UmbracoCms.*.nupkg
|
||||
DEL /F /Q webpihash.txt
|
||||
|
||||
ECHO Performing MSBuild and producing Umbraco binaries zip files
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment%
|
||||
|
||||
|
||||
+1
-1
@@ -325,7 +325,7 @@
|
||||
Regex="CurrentComment { get { return "([a-zA-Z]+)?""
|
||||
ReplacementText="CurrentComment { get { return "$(BUILD_COMMENT)""/>
|
||||
|
||||
<XmlPoke XmlInputPath=".\NuSpecs\build\UmbracoCms.targets"
|
||||
<XmlPoke XmlInputPath=".\NuSpecs\build\UmbracoCms.props"
|
||||
Namespaces="<Namespace Prefix='x' Uri='http://schemas.microsoft.com/developer/msbuild/2003' />"
|
||||
Query="//x:UmbracoVersion"
|
||||
Value="$(NewVersion)" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@ECHO OFF
|
||||
SET release=%1
|
||||
ECHO Installing Npm NuGet Package
|
||||
|
||||
SET nuGetFolder=%CD%\..\src\packages\
|
||||
@@ -26,7 +27,7 @@ ECHO Do npm install and the grunt build of Belle
|
||||
call npm install
|
||||
call npm install -g grunt-cli
|
||||
call npm install -g bower
|
||||
call grunt build --buildversion=7.1.2
|
||||
call grunt build --buildversion=%release%
|
||||
|
||||
ECHO Reset path to what it was before
|
||||
path=%oldPath%
|
||||
|
||||
@@ -67,5 +67,6 @@
|
||||
<file src="..\_BuildOutput\WebApp\bin\umbraco.XmlSerializers.dll" target="lib\umbraco.XmlSerializers.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\UrlRewritingNet.UrlRewriter.dll" target="lib\UrlRewritingNet.UrlRewriter.dll" />
|
||||
<file src="tools\install.core.ps1" target="tools\install.ps1" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -1,12 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
|
||||
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<UmbracoVersion>7.1.2</UmbracoVersion>
|
||||
</PropertyGroup>
|
||||
<Target Name="CopyUmbracoFilesToWebRoot" BeforeTargets="AfterBuild">
|
||||
<PropertyGroup>
|
||||
<UmbracoFilesFolder>..\packages\UmbracoCms.$(UmbracoVersion)\UmbracoFiles\</UmbracoFilesFolder>
|
||||
<UmbracoFilesFolder>$(MSBuildThisFileDirectory)..\UmbracoFiles\</UmbracoFilesFolder>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<UmbracoFiles Include="$(UmbracoFilesFolder)**\*" />
|
||||
@@ -33,6 +30,9 @@
|
||||
<CustomFilesToInclude Include=".\Config\Splashes\**\*">
|
||||
<Dir>Config\Splashes</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\data\**\*">
|
||||
<Dir>data</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\umbraco\**\*">
|
||||
<Dir>umbraco</Dir>
|
||||
</CustomFilesToInclude>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
param($rootPath, $toolsPath, $package, $project)
|
||||
|
||||
if ($project) {
|
||||
$dateTime = Get-Date -Format yyyyMMdd-HHmmss
|
||||
$backupPath = Join-Path (Split-Path $project.FullName -Parent) "\App_Data\NuGetBackup\$dateTime"
|
||||
$copyLogsPath = Join-Path $backupPath "CopyLogs"
|
||||
$projectDestinationPath = Split-Path $project.FullName -Parent
|
||||
|
||||
# Create backup folder and logs folder if it doesn't exist yet
|
||||
New-Item -ItemType Directory -Force -Path $backupPath
|
||||
New-Item -ItemType Directory -Force -Path $copyLogsPath
|
||||
|
||||
# After backing up, remove all dlls from bin folder in case dll files are included in the VS project
|
||||
# See: http://issues.umbraco.org/issue/U4-4930
|
||||
$umbracoBinFolder = Join-Path $projectDestinationPath "bin"
|
||||
if(Test-Path $umbracoBinFolder) {
|
||||
$umbracoBinBackupPath = Join-Path $backupPath "bin"
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $umbracoBinBackupPath
|
||||
|
||||
robocopy $umbracoBinFolder $umbracoBinBackupPath /e /LOG:$copyLogsPath\UmbracoBinBackup.log
|
||||
Remove-Item $umbracoBinFolder\*.dll -Force -Confirm:$false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
7.1.4
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.1.2");
|
||||
private static readonly Version Version = new Version("7.1.4");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -329,9 +329,8 @@ namespace Umbraco.Core
|
||||
UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver(
|
||||
typeof (DefaultUrlSegmentProvider));
|
||||
|
||||
// keep it internal for now
|
||||
// by default, no factory is activated
|
||||
PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver();
|
||||
// new PublishedContentModelFactoryImpl());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,13 +117,12 @@ namespace Umbraco.Core.Dynamics
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var sb = new StringBuilder("An error occurred finding an executing an extension method for type ");
|
||||
sb.Append(typeof (T));
|
||||
sb.Append("Types searched for extension methods were ");
|
||||
foreach(var t in findExtensionMethodsOnTypes)
|
||||
{
|
||||
sb.Append(t + ",");
|
||||
}
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendFormat("An error occurred finding and executing extension method \"{0}\" ", binder.Name);
|
||||
sb.AppendFormat("for type \"{0}\". ", typeof (T));
|
||||
sb.Append("Types searched for extension methods were ");
|
||||
sb.Append(string.Join(", ", findExtensionMethodsOnTypes));
|
||||
sb.Append(".");
|
||||
LogHelper.Error<DynamicInstanceHelper>(sb.ToString(), ex);
|
||||
var mresult = new TryInvokeMemberResult(null, TryInvokeMemberSuccessReason.FoundExtensionMethod);
|
||||
return Attempt<TryInvokeMemberResult>.Fail(mresult, ex);
|
||||
@@ -171,7 +170,7 @@ namespace Umbraco.Core.Dynamics
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MissingMethodException();
|
||||
throw new MissingMethodException(typeof(T).FullName, name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ using System.Linq;
|
||||
using System.Web;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
@@ -539,7 +541,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
return ApplicationContext.Current.Services.ContentService.HasPublishedVersion(content.Id);
|
||||
}
|
||||
|
||||
|
||||
#region Tag methods
|
||||
|
||||
///// <summary>
|
||||
@@ -567,6 +569,21 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="tagGroup">The group/category to assign the tags, the default value is "default"</param>
|
||||
/// <returns></returns>
|
||||
public static void SetTags(this IContentBase content, string propertyTypeAlias, IEnumerable<string> tags, bool replaceTags, string tagGroup = "default")
|
||||
{
|
||||
content.SetTags(TagCacheStorageType.Csv, propertyTypeAlias, tags, replaceTags, tagGroup);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets tags for the property - will add tags to the tags table and set the property value to be the comma delimited value of the tags.
|
||||
/// </summary>
|
||||
/// <param name="content">The content item to assign the tags to</param>
|
||||
/// <param name="storageType">The tag storage type in cache (default is csv)</param>
|
||||
/// <param name="propertyTypeAlias">The property alias to assign the tags to</param>
|
||||
/// <param name="tags">The tags to assign</param>
|
||||
/// <param name="replaceTags">True to replace the tags on the current property with the tags specified or false to merge them with the currently assigned ones</param>
|
||||
/// <param name="tagGroup">The group/category to assign the tags, the default value is "default"</param>
|
||||
/// <returns></returns>
|
||||
public static void SetTags(this IContentBase content, TagCacheStorageType storageType, string propertyTypeAlias, IEnumerable<string> tags, bool replaceTags, string tagGroup = "default")
|
||||
{
|
||||
var property = content.Properties[propertyTypeAlias];
|
||||
if (property == null)
|
||||
@@ -583,15 +600,39 @@ namespace Umbraco.Core.Models
|
||||
//ensure the property value is set to the same thing
|
||||
if (replaceTags)
|
||||
{
|
||||
property.Value = string.Join(",", trimmedTags);
|
||||
switch (storageType)
|
||||
{
|
||||
case TagCacheStorageType.Csv:
|
||||
property.Value = string.Join(",", trimmedTags);
|
||||
break;
|
||||
case TagCacheStorageType.Json:
|
||||
//json array
|
||||
property.Value = JsonConvert.SerializeObject(trimmedTags);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var currTags = property.Value.ToString().Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)
|
||||
switch (storageType)
|
||||
{
|
||||
case TagCacheStorageType.Csv:
|
||||
var currTags = property.Value.ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(x => x.Trim());
|
||||
property.Value = string.Join(",", trimmedTags.Union(currTags));
|
||||
property.Value = string.Join(",", trimmedTags.Union(currTags));
|
||||
break;
|
||||
case TagCacheStorageType.Json:
|
||||
var currJson = JsonConvert.DeserializeObject<JArray>(property.Value.ToString());
|
||||
//need to append the new ones
|
||||
foreach (var tag in trimmedTags)
|
||||
{
|
||||
currJson.Add(tag);
|
||||
}
|
||||
//json array
|
||||
property.Value = JsonConvert.SerializeObject(currJson);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -664,7 +705,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(media, true, raiseEvents: false);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates the xml representation for the <see cref="IContent"/> object
|
||||
/// </summary>
|
||||
@@ -687,10 +728,10 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
return ((PackagingService)(ApplicationContext.Current.Services.PackagingService)).Export(member);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -133,29 +133,6 @@ namespace Umbraco.Core.Models
|
||||
Key = Guid.NewGuid();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method to call when Entity is being updated
|
||||
/// </summary>
|
||||
/// <remarks>Modified Date is set and a new Version guid is set</remarks>
|
||||
internal override void UpdatingEntity()
|
||||
{
|
||||
base.UpdatingEntity();
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (ContentType)base.DeepClone();
|
||||
var propertyGroups = PropertyGroups.Select(x => (PropertyGroup)x.DeepClone()).ToList();
|
||||
clone.PropertyGroups = new PropertyGroupCollection(propertyGroups);
|
||||
//set the property types that are not part of a group
|
||||
clone.PropertyTypes = PropertyTypeCollection
|
||||
.Where(x => x.PropertyGroupId == null)
|
||||
.Select(x => (PropertyType)x.DeepClone()).ToList();
|
||||
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
|
||||
|
||||
@@ -331,11 +331,6 @@ namespace Umbraco.Core.Models
|
||||
get { return _additionalData; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
|
||||
/// </summary>
|
||||
public IDictionary<string, object> AdditionalData { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of integer Ids for allowed ContentTypes
|
||||
/// </summary>
|
||||
@@ -356,7 +351,9 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// List of PropertyGroups available on this ContentType
|
||||
/// </summary>
|
||||
/// <remarks>A PropertyGroup corresponds to a Tab in the UI</remarks>
|
||||
/// <remarks>
|
||||
/// A PropertyGroup corresponds to a Tab in the UI
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
public virtual PropertyGroupCollection PropertyGroups
|
||||
{
|
||||
@@ -372,7 +369,13 @@ namespace Umbraco.Core.Models
|
||||
/// List of PropertyTypes available on this ContentType.
|
||||
/// This list aggregates PropertyTypes across the PropertyGroups.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Marked as DoNotClone because the result of this property is not the natural result of the data, it is
|
||||
/// a union of data so when auto-cloning if the setter is used it will be setting the unnatural result of the
|
||||
/// data. We manually clone this instead.
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
[DoNotClone]
|
||||
public virtual IEnumerable<PropertyType> PropertyTypes
|
||||
{
|
||||
get
|
||||
@@ -388,6 +391,14 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the property type collection containing types that are non-groups - used for tests
|
||||
/// </summary>
|
||||
internal IEnumerable<PropertyType> NonGroupedPropertyTypes
|
||||
{
|
||||
get { return _propertyTypes; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A boolean flag indicating if a property type has been removed from this instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
@@ -584,5 +595,19 @@ namespace Umbraco.Core.Models
|
||||
propertyType.ResetDirtyProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (ContentTypeBase)base.DeepClone();
|
||||
|
||||
//need to manually wire up the event handlers for the property type collections - we've ensured
|
||||
// its ignored from the auto-clone process because its return values are unions, not raw and
|
||||
// we end up with duplicates, see: http://issues.umbraco.org/issue/U4-4842
|
||||
|
||||
clone._propertyTypes = (PropertyTypeCollection)_propertyTypes.DeepClone();
|
||||
clone._propertyTypes.CollectionChanged += clone.PropertyTypesChanged;
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,29 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to attribute properties that have a setter and are a reference type
|
||||
/// that should be ignored for cloning when using the DeepCloneHelper
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///
|
||||
/// This attribute must be used:
|
||||
/// * when the property is backed by a field but the result of the property is the un-natural data stored in the field
|
||||
///
|
||||
/// This attribute should not be used:
|
||||
/// * when the property is virtual
|
||||
/// * when the setter performs additional required logic other than just setting the underlying field
|
||||
///
|
||||
/// </remarks>
|
||||
internal class DoNotCloneAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static class DeepCloneHelper
|
||||
{
|
||||
/// <summary>
|
||||
@@ -25,8 +45,10 @@ namespace Umbraco.Core.Models
|
||||
|
||||
var refProperties = inputType.GetProperties()
|
||||
.Where(x =>
|
||||
//is not attributed with the ignore clone attribute
|
||||
x.GetCustomAttribute<DoNotCloneAttribute>() == null
|
||||
//reference type but not string
|
||||
x.PropertyType.IsValueType == false && x.PropertyType != typeof (string)
|
||||
&& x.PropertyType.IsValueType == false && x.PropertyType != typeof (string)
|
||||
//settable
|
||||
&& x.CanWrite
|
||||
//non-indexed
|
||||
|
||||
@@ -240,52 +240,6 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
DeepCloneHelper.DeepCloneRefProperties(this, clone);
|
||||
clone.ResetDirtyProperties(false);
|
||||
return clone;
|
||||
|
||||
//Using data contract serializer - has issues
|
||||
|
||||
//var s = Serialize(this);
|
||||
//var d = Deserialize(s, this.GetType());
|
||||
//return d;
|
||||
|
||||
//Using binary serializer - has issues
|
||||
|
||||
//using (var memoryStream = new MemoryStream(10))
|
||||
//{
|
||||
//IFormatter formatter = new BinaryFormatter();
|
||||
//formatter.Serialize(memoryStream, this);
|
||||
//memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
//return formatter.Deserialize(memoryStream);
|
||||
//}
|
||||
}
|
||||
|
||||
// serialize/deserialize with data contracts:
|
||||
|
||||
//public static string Serialize(object obj)
|
||||
//{
|
||||
// using (var memoryStream = new MemoryStream())
|
||||
// using (var reader = new StreamReader(memoryStream))
|
||||
// {
|
||||
// var serializer = new DataContractSerializer(obj.GetType());
|
||||
// serializer.WriteObject(memoryStream, obj);
|
||||
// memoryStream.Position = 0;
|
||||
// return reader.ReadToEnd();
|
||||
// }
|
||||
//}
|
||||
|
||||
//public static object Deserialize(string xml, Type toType)
|
||||
//{
|
||||
// using (Stream stream = new MemoryStream())
|
||||
// {
|
||||
// using (var writer = new StreamWriter(stream, Encoding.UTF8))
|
||||
// {
|
||||
// writer.Write(xml);
|
||||
// //byte[] data = Encoding.UTF8.GetBytes(xml);
|
||||
// //stream.Write(data, 0, data.Length);
|
||||
// stream.Position = 0;
|
||||
// var deserializer = new DataContractSerializer(toType);
|
||||
// return deserializer.ReadObject(stream);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Defines a Property for a Macro
|
||||
/// </summary>
|
||||
public interface IMacroProperty : IValueObject
|
||||
public interface IMacroProperty : IValueObject, IDeepCloneable, IRememberBeingDirty
|
||||
{
|
||||
[DataMember]
|
||||
int Id { get; set; }
|
||||
|
||||
@@ -138,12 +138,11 @@ namespace Umbraco.Core.Models
|
||||
|
||||
var alias = prop.Alias;
|
||||
|
||||
//remove from the removed/added props (since people could add/remove all they want in one request)
|
||||
_removedProperties.RemoveAll(s => s == alias);
|
||||
_addedProperties.RemoveAll(s => s == alias);
|
||||
|
||||
//add to the added props
|
||||
_addedProperties.Add(alias);
|
||||
if (_addedProperties.Contains(alias) == false)
|
||||
{
|
||||
//add to the added props
|
||||
_addedProperties.Add(alias);
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove)
|
||||
{
|
||||
@@ -153,12 +152,10 @@ namespace Umbraco.Core.Models
|
||||
|
||||
var alias = prop.Alias;
|
||||
|
||||
//remove from the removed/added props (since people could add/remove all they want in one request)
|
||||
_removedProperties.RemoveAll(s => s == alias);
|
||||
_addedProperties.RemoveAll(s => s == alias);
|
||||
|
||||
//add to the added props
|
||||
_removedProperties.Add(alias);
|
||||
if (_removedProperties.Contains(alias) == false)
|
||||
{
|
||||
_removedProperties.Add(alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,7 +401,8 @@ namespace Umbraco.Core.Models
|
||||
|
||||
clone._addedProperties = new List<string>();
|
||||
clone._removedProperties = new List<string>();
|
||||
clone._properties = new MacroPropertyCollection();
|
||||
clone._properties = (MacroPropertyCollection)Properties.DeepClone();
|
||||
//re-assign the event handler
|
||||
clone._properties.CollectionChanged += clone.PropertiesChanged;
|
||||
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class MacroProperty : TracksChangesEntityBase, IMacroProperty, IRememberBeingDirty
|
||||
public class MacroProperty : TracksChangesEntityBase, IMacroProperty, IRememberBeingDirty, IDeepCloneable
|
||||
{
|
||||
public MacroProperty()
|
||||
{
|
||||
@@ -176,5 +176,37 @@ namespace Umbraco.Core.Models
|
||||
}, _editorAlias, PropertyTypeSelector);
|
||||
}
|
||||
}
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
//Memberwise clone on MacroProperty will work since it doesn't have any deep elements
|
||||
// for any sub class this will work for standard properties as well that aren't complex object's themselves.
|
||||
var clone = (MacroProperty)MemberwiseClone();
|
||||
//Automatically deep clone ref properties that are IDeepCloneable
|
||||
DeepCloneHelper.DeepCloneRefProperties(this, clone);
|
||||
clone.ResetDirtyProperties(false);
|
||||
return clone;
|
||||
}
|
||||
|
||||
protected bool Equals(MacroProperty other)
|
||||
{
|
||||
return string.Equals(_alias, other._alias) && _id == other._id;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((MacroProperty) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return ((_alias != null ? _alias.GetHashCode() : 0)*397) ^ _id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,60 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// A macro's property collection
|
||||
/// </summary>
|
||||
public class MacroPropertyCollection : ObservableDictionary<string, IMacroProperty>
|
||||
public class MacroPropertyCollection : ObservableDictionary<string, IMacroProperty>, IDeepCloneable
|
||||
{
|
||||
public MacroPropertyCollection()
|
||||
: base(property => property.Alias)
|
||||
{
|
||||
}
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
var clone = new MacroPropertyCollection();
|
||||
foreach (var item in this)
|
||||
{
|
||||
clone.Add((IMacroProperty)item.DeepClone());
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to update an existing macro property
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="sortOrder"></param>
|
||||
/// <param name="editorAlias"></param>
|
||||
/// <param name="currentAlias">
|
||||
/// The existing property alias
|
||||
/// </param>
|
||||
/// <param name="newAlias"></param>
|
||||
public void UpdateProperty(string currentAlias, string name = null, int? sortOrder = null, string editorAlias = null, string newAlias = null)
|
||||
{
|
||||
var prop = this[currentAlias];
|
||||
if (prop == null)
|
||||
{
|
||||
throw new InvalidOperationException("No property exists with alias " + currentAlias);
|
||||
}
|
||||
|
||||
if (name.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
prop.Name = name;
|
||||
}
|
||||
if (sortOrder.HasValue)
|
||||
{
|
||||
prop.SortOrder = sortOrder.Value;
|
||||
}
|
||||
if (name.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
prop.EditorAlias = editorAlias;
|
||||
}
|
||||
|
||||
if (newAlias.IsNullOrWhiteSpace() == false && currentAlias != newAlias)
|
||||
{
|
||||
prop.Alias = newAlias;
|
||||
ChangeKey(currentAlias, newAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// Represents a stored pre-value field value
|
||||
/// </summary>
|
||||
public class PreValue
|
||||
public class PreValue : IDeepCloneable
|
||||
{
|
||||
public PreValue(int id, string value, int sortOrder)
|
||||
{
|
||||
@@ -37,5 +37,12 @@
|
||||
/// The sort order stored for the pre-value field value
|
||||
/// </summary>
|
||||
public int SortOrder { get; private set; }
|
||||
|
||||
public virtual object DeepClone()
|
||||
{
|
||||
//Memberwise clone on PreValue will work since it doesn't have any deep elements
|
||||
var clone = (PreValue)MemberwiseClone();
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Models
|
||||
/// Most legacy property editors won't support the dictionary format but new property editors should always use the dictionary format.
|
||||
/// In order to get overrideable pre-values working we need a dictionary since we'll have to reference a pre-value by a key.
|
||||
/// </remarks>
|
||||
public class PreValueCollection
|
||||
public class PreValueCollection : IDeepCloneable
|
||||
{
|
||||
private IDictionary<string, PreValue> _preValuesAsDictionary;
|
||||
private IEnumerable<PreValue> _preValuesAsArray;
|
||||
@@ -82,5 +82,21 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
var clone = (PreValueCollection) MemberwiseClone();
|
||||
if (_preValuesAsArray != null)
|
||||
{
|
||||
clone._preValuesAsArray = _preValuesAsArray.Select(x => (PreValue)x.DeepClone()).ToArray();
|
||||
}
|
||||
if (_preValuesAsDictionary != null)
|
||||
{
|
||||
clone._preValuesAsDictionary = _preValuesAsDictionary.ToDictionary(x => x.Key, x => (PreValue)x.Value.DeepClone());
|
||||
}
|
||||
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
internal enum PropertyTagBehavior
|
||||
{
|
||||
Replace,
|
||||
Remove,
|
||||
Merge
|
||||
}
|
||||
}
|
||||
@@ -33,11 +33,4 @@ namespace Umbraco.Core.Models
|
||||
public IEnumerable<Tuple<string, string>> Tags { get; set; }
|
||||
|
||||
}
|
||||
|
||||
internal enum PropertyTagBehavior
|
||||
{
|
||||
Replace,
|
||||
Remove,
|
||||
Merge
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// Provides the model creation service.
|
||||
/// </summary>
|
||||
internal interface IPublishedContentModelFactory
|
||||
public interface IPublishedContentModelFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a strongly-typed model representing a published content.
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
// a model, and then that model has to inherit from PublishedContentExtended,
|
||||
// => implements the internal IPublishedContentExtended.
|
||||
|
||||
var model = PublishedContentModelFactory.CreateModel(content);
|
||||
var model = content.CreateModel();
|
||||
var extended = model == content // == means the factory did not create a model
|
||||
? new PublishedContentExtended(content) // so we have to extend
|
||||
: model; // else we can use what the factory returned
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides strongly typed published content models services.
|
||||
/// </summary>
|
||||
internal static class PublishedContentExtensionsForModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a strongly typed published content model for an internal published content.
|
||||
/// </summary>
|
||||
/// <param name="content">The internal published content.</param>
|
||||
/// <returns>The strongly typed published content model.</returns>
|
||||
public static IPublishedContent CreateModel(this IPublishedContent content)
|
||||
{
|
||||
return PublishedContentModelFactoryResolver.Current.HasValue
|
||||
? PublishedContentModelFactoryResolver.Current.Factory.CreateModel(content)
|
||||
: content;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// </summary>
|
||||
/// <remarks>Every strongly-typed published content class should inherit from <c>PublishedContentModel</c>
|
||||
/// (or inherit from a class that inherits from... etc.) so they are picked by the factory.</remarks>
|
||||
internal abstract class PublishedContentModel : PublishedContentExtended
|
||||
public abstract class PublishedContentModel : PublishedContentExtended
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedContentModel"/> class with
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// <remarks>By default, the name of the class is assumed to be the content type alias. The
|
||||
/// <c>PublishedContentModelAttribute</c> can be used to indicate a different alias.</remarks>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
internal sealed class PublishedContentModelAttribute : Attribute
|
||||
public sealed class PublishedContentModelAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedContentModelAttribute"/> class with a content type alias.
|
||||
|
||||
@@ -1,20 +1,86 @@
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides strongly typed published content models services.
|
||||
/// </summary>
|
||||
internal static class PublishedContentModelFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a strongly typed published content model for an internal published content.
|
||||
/// </summary>
|
||||
/// <param name="content">The internal published content.</param>
|
||||
/// <returns>The strongly typed published content model.</returns>
|
||||
public static IPublishedContent CreateModel(IPublishedContent content)
|
||||
{
|
||||
return PublishedContentModelFactoryResolver.Current.HasValue
|
||||
? PublishedContentModelFactoryResolver.Current.Factory.CreateModel(content)
|
||||
: content;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a strongly typed content model factory
|
||||
/// </summary>
|
||||
public class PublishedContentModelFactory : IPublishedContentModelFactory
|
||||
{
|
||||
//private readonly Dictionary<string, ConstructorInfo> _constructors
|
||||
// = new Dictionary<string, ConstructorInfo>();
|
||||
|
||||
private readonly Dictionary<string, Func<IPublishedContent, IPublishedContent>> _constructors;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedContentModelFactory"/> class with types.
|
||||
/// </summary>
|
||||
/// <param name="types">The model types.</param>
|
||||
/// <remarks>
|
||||
/// <para>Types must implement <c>IPublishedContent</c> and have a unique constructor that
|
||||
/// accepts one IPublishedContent as a parameter.</para>
|
||||
/// <para>To activate,</para>
|
||||
/// <code>
|
||||
/// var types = PluginManager.Current.ResolveTypes{PublishedContentModel}();
|
||||
/// var factory = new PublishedContentModelFactoryImpl(types);
|
||||
/// PublishedContentModelFactoryResolver.Current.SetFactory(factory);
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
public PublishedContentModelFactory(IEnumerable<Type> types)
|
||||
{
|
||||
var ctorArgTypes = new[] { typeof(IPublishedContent) };
|
||||
var constructors = new Dictionary<string, Func<IPublishedContent, IPublishedContent>>();
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
var constructor = type.GetConstructor(ctorArgTypes);
|
||||
if (constructor == null)
|
||||
throw new InvalidOperationException(string.Format("Type {0} is missing a public constructor with one argument of type IPublishedContent.", type.FullName));
|
||||
var attribute = type.GetCustomAttribute<PublishedContentModelAttribute>(false);
|
||||
var typeName = attribute == null ? type.Name : attribute.ContentTypeAlias;
|
||||
typeName = typeName.ToLowerInvariant();
|
||||
|
||||
if (constructors.ContainsKey(typeName))
|
||||
throw new InvalidOperationException(string.Format("More that one type want to be a model for content type {0}.", typeName));
|
||||
|
||||
// should work everywhere, but slow
|
||||
//_constructors[typeName] = constructor;
|
||||
|
||||
// much faster with a dynamic method but potential MediumTrust issues
|
||||
// here http://stackoverflow.com/questions/16363838/how-do-you-call-a-constructor-via-an-expression-tree-on-an-existing-object
|
||||
|
||||
// fast enough and works in MediumTrust
|
||||
// read http://boxbinary.com/2011/10/how-to-run-a-unit-test-in-medium-trust-with-nunitpart-three-umbraco-framework-testing/
|
||||
var exprArg = Expression.Parameter(typeof(IPublishedContent), "content");
|
||||
var exprNew = Expression.New(constructor, exprArg);
|
||||
var expr = Expression.Lambda<Func<IPublishedContent, IPublishedContent>>(exprNew, exprArg);
|
||||
var func = expr.Compile();
|
||||
constructors[typeName] = func;
|
||||
}
|
||||
|
||||
_constructors = constructors.Count > 0 ? constructors : null;
|
||||
}
|
||||
|
||||
public IPublishedContent CreateModel(IPublishedContent content)
|
||||
{
|
||||
// fail fast
|
||||
if (_constructors == null)
|
||||
return content;
|
||||
|
||||
// be case-insensitive
|
||||
var contentTypeAlias = content.DocumentTypeAlias.ToLowerInvariant();
|
||||
|
||||
//ConstructorInfo constructor;
|
||||
//return _constructors.TryGetValue(contentTypeAlias, out constructor)
|
||||
// ? (IPublishedContent) constructor.Invoke(new object[] { content })
|
||||
// : content;
|
||||
|
||||
Func<IPublishedContent, IPublishedContent> constructor;
|
||||
return _constructors.TryGetValue(contentTypeAlias, out constructor)
|
||||
? constructor(content)
|
||||
: content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a strongly typed content model factory
|
||||
/// </summary>
|
||||
internal class PublishedContentModelFactoryImpl : IPublishedContentModelFactory
|
||||
{
|
||||
//private readonly Dictionary<string, ConstructorInfo> _constructors
|
||||
// = new Dictionary<string, ConstructorInfo>();
|
||||
|
||||
private readonly Dictionary<string, Func<IPublishedContent, IPublishedContent>> _constructors
|
||||
= new Dictionary<string, Func<IPublishedContent, IPublishedContent>>();
|
||||
|
||||
public PublishedContentModelFactoryImpl()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveTypes<PublishedContentModel>();
|
||||
var ctorArgTypes = new[] { typeof(IPublishedContent) };
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
var constructor = type.GetConstructor(ctorArgTypes);
|
||||
if (constructor == null)
|
||||
throw new InvalidOperationException(string.Format("Type {0} is missing a public constructor with one argument of type IPublishedContent.", type.FullName));
|
||||
var attribute = type.GetCustomAttribute<PublishedContentModelAttribute>(false);
|
||||
var typeName = attribute == null ? type.Name : attribute.ContentTypeAlias;
|
||||
typeName = typeName.ToLowerInvariant();
|
||||
|
||||
if (_constructors.ContainsKey(typeName))
|
||||
throw new InvalidOperationException(string.Format("More that one type want to be a model for content type {0}.", typeName));
|
||||
|
||||
// should work everywhere, but slow
|
||||
//_constructors[typeName] = constructor;
|
||||
|
||||
// much faster with a dynamic method but potential MediumTrust issues
|
||||
// here http://stackoverflow.com/questions/16363838/how-do-you-call-a-constructor-via-an-expression-tree-on-an-existing-object
|
||||
|
||||
// fast enough and works in MediumTrust
|
||||
// read http://boxbinary.com/2011/10/how-to-run-a-unit-test-in-medium-trust-with-nunitpart-three-umbraco-framework-testing/
|
||||
var exprArg = Expression.Parameter(typeof(IPublishedContent), "content");
|
||||
var exprNew = Expression.New(constructor, exprArg);
|
||||
var expr = Expression.Lambda<Func<IPublishedContent, IPublishedContent>>(exprNew, exprArg);
|
||||
var func = expr.Compile();
|
||||
_constructors[typeName] = func;
|
||||
}
|
||||
}
|
||||
|
||||
public IPublishedContent CreateModel(IPublishedContent content)
|
||||
{
|
||||
// be case-insensitive
|
||||
var contentTypeAlias = content.DocumentTypeAlias.ToLowerInvariant();
|
||||
|
||||
//ConstructorInfo constructor;
|
||||
//return _constructors.TryGetValue(contentTypeAlias, out constructor)
|
||||
// ? (IPublishedContent) constructor.Invoke(new object[] { content })
|
||||
// : content;
|
||||
|
||||
Func<IPublishedContent, IPublishedContent> constructor;
|
||||
return _constructors.TryGetValue(contentTypeAlias, out constructor)
|
||||
? constructor(content)
|
||||
: content;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// <summary>
|
||||
/// Resolves the IPublishedContentModelFactory object.
|
||||
/// </summary>
|
||||
internal class PublishedContentModelFactoryResolver : SingleObjectResolverBase<PublishedContentModelFactoryResolver, IPublishedContentModelFactory>
|
||||
public class PublishedContentModelFactoryResolver : SingleObjectResolverBase<PublishedContentModelFactoryResolver, IPublishedContentModelFactory>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedContentModelFactoryResolver"/>.
|
||||
|
||||
@@ -44,6 +44,11 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
InitializeIndexes();
|
||||
}
|
||||
|
||||
// create detached content type - ie does not match anything in the DB
|
||||
internal PublishedContentType(string alias, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
: this (0, alias, propertyTypes)
|
||||
{ }
|
||||
|
||||
private void InitializeIndexes()
|
||||
{
|
||||
for (var i = 0; i < _propertyTypes.Length; i++)
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
internal class DataTypePreValueDto
|
||||
{
|
||||
[Column("id")]
|
||||
[PrimaryKeyColumn(IdentitySeed = 5)]
|
||||
[PrimaryKeyColumn(IdentitySeed = 6)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("datatypeNodeId")]
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public enum TagCacheStorageType
|
||||
{
|
||||
Csv,
|
||||
Json
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Initializes a new instance of the <see cref="LazyManyObjectsResolverBase{TResolver, TResolved}"/> class with an initial list
|
||||
/// <remarks>If <paramref name="scope"/> is per HttpRequest then there must be a current HttpContext.</remarks>
|
||||
/// <exception cref="InvalidOperationException"><paramref name="scope"/> is per HttpRequest but the current HttpContext is null.</exception>
|
||||
/// </summary>
|
||||
protected LazyManyObjectsResolverBase(IEnumerable<Lazy<Type>> lazyTypeList, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: this(scope)
|
||||
{
|
||||
@@ -108,7 +109,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Gets a value indicating whether the resolver has resolved types to create instances from.
|
||||
/// </summary>
|
||||
/// <remarks>To be used in unit tests.</remarks>
|
||||
internal bool HasResolvedTypes
|
||||
public bool HasResolvedTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -135,6 +135,28 @@ namespace Umbraco.Core
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows us to change the key of an item
|
||||
/// </summary>
|
||||
/// <param name="currentKey"></param>
|
||||
/// <param name="newKey"></param>
|
||||
public virtual void ChangeKey(TKey currentKey, TKey newKey)
|
||||
{
|
||||
if (!Indecies.ContainsKey(currentKey))
|
||||
{
|
||||
throw new InvalidOperationException("No item with the key " + currentKey + "was found in the collection");
|
||||
}
|
||||
if (ContainsKey(newKey))
|
||||
{
|
||||
throw new DuplicateKeyException(newKey.ToString());
|
||||
}
|
||||
|
||||
var currentIndex = Indecies[currentKey];
|
||||
|
||||
Indecies.Remove(currentKey);
|
||||
Indecies.Add(newKey, currentIndex);
|
||||
}
|
||||
|
||||
internal class DuplicateKeyException : Exception
|
||||
{
|
||||
|
||||
|
||||
@@ -128,9 +128,9 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
public void Save(Type type, IEntity entity)
|
||||
{
|
||||
//IMPORTANT: we must clone to store, see: http://issues.umbraco.org/issue/U4-4259
|
||||
entity = (IEntity)entity.DeepClone();
|
||||
var clone = (IEntity)entity.DeepClone();
|
||||
|
||||
var key = GetCompositeId(type, entity.Id);
|
||||
var key = GetCompositeId(type, clone.Id);
|
||||
|
||||
_keyTracker.TryAdd(key);
|
||||
|
||||
@@ -139,11 +139,11 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
|
||||
if (_memoryCache != null)
|
||||
{
|
||||
_memoryCache.Set(key, entity, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(5) });
|
||||
_memoryCache.Set(key, clone, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(5) });
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpRuntime.Cache.Insert(key, entity, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5));
|
||||
HttpRuntime.Cache.Insert(key, clone, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
{
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 3, Alias = "", SortOrder = 0, DataTypeNodeId = -87, Value = ",code,undo,redo,cut,copy,mcepasteword,stylepicker,bold,italic,bullist,numlist,outdent,indent,mcelink,unlink,mceinsertanchor,mceimage,umbracomacro,mceinserttable,umbracoembed,mcecharmap,|1|1,2,3,|0|500,400|1049,|true|" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 4, Alias = "group", SortOrder = 0, DataTypeNodeId = 1041, Value = "default" });
|
||||
|
||||
//default's for MultipleMediaPickerAlias picker
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 5, Alias = "multiPicker", SortOrder = 0, DataTypeNodeId = 1045, Value = "1" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoRelationTypeData()
|
||||
|
||||
+14
-3
@@ -1,5 +1,7 @@
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionFourNineZero
|
||||
{
|
||||
@@ -18,9 +20,18 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionFourNineZero
|
||||
}
|
||||
else
|
||||
{
|
||||
//These are the old aliases
|
||||
Delete.ForeignKey("FK_umbracoUser2app_umbracoApp").OnTable("umbracoUser2app");
|
||||
Delete.ForeignKey("FK_umbracoUser2app_umbracoUser").OnTable("umbracoUser2app");
|
||||
//These are the old aliases, before removing them, check they exist
|
||||
var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
|
||||
|
||||
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser2app") && x.Item3.InvariantEquals("FK_umbracoUser2app_umbracoApp")))
|
||||
{
|
||||
Delete.ForeignKey("FK_umbracoUser2app_umbracoApp").OnTable("umbracoUser2app");
|
||||
}
|
||||
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser2app") && x.Item3.InvariantEquals("FK_umbracoUser2app_umbracoUser")))
|
||||
{
|
||||
Delete.ForeignKey("FK_umbracoUser2app_umbracoUser").OnTable("umbracoUser2app");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -295,8 +295,8 @@ AND umbracoNode.id <> @id",
|
||||
var cached = _cacheHelper.RuntimeCache.GetCacheItemsByKeySearch<PreValueCollection>(GetPrefixedCacheKey(dataTypeId));
|
||||
if (cached != null && cached.Any())
|
||||
{
|
||||
//return from the cache
|
||||
return cached.First();
|
||||
//return from the cache, ensure it's a cloned result
|
||||
return (PreValueCollection)cached.First().DeepClone();
|
||||
}
|
||||
|
||||
l.UpgradeToWriteLock();
|
||||
|
||||
@@ -493,14 +493,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
// Is this the same UmbracoEntity as the current one we're processing
|
||||
if (Current != null && Current.Key == a.uniqueID)
|
||||
{
|
||||
// Add this UmbracoProperty to the current additional data
|
||||
Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
if (p != null && p.PropertyAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.NTextValue.IsNullOrWhiteSpace()
|
||||
? p.NVarcharValue
|
||||
: p.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
// Add this UmbracoProperty to the current additional data
|
||||
Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.NTextValue.IsNullOrWhiteSpace()
|
||||
? p.NVarcharValue
|
||||
: p.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
}
|
||||
|
||||
// Return null to indicate we're not done with this UmbracoEntity yet
|
||||
return null;
|
||||
@@ -516,14 +519,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
Current = _factory.BuildEntityFromDynamic(a);
|
||||
|
||||
//add the property/create the prop list if null
|
||||
Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
if (p != null && p.PropertyAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.NTextValue.IsNullOrWhiteSpace()
|
||||
? p.NVarcharValue
|
||||
: p.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
//add the property/create the prop list if null
|
||||
Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.NTextValue.IsNullOrWhiteSpace()
|
||||
? p.NVarcharValue
|
||||
: p.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
}
|
||||
|
||||
// Return the now populated previous UmbracoEntity (or null if first time through)
|
||||
return prev;
|
||||
|
||||
@@ -165,10 +165,18 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
Database.Update(dto);
|
||||
|
||||
//update the sections if they've changed
|
||||
//update the properties if they've changed
|
||||
var macro = (Macro)entity;
|
||||
if (macro.IsPropertyDirty("Properties"))
|
||||
if (macro.IsPropertyDirty("Properties") || macro.Properties.Any(x => x.IsDirty()))
|
||||
{
|
||||
//now we need to delete any props that have been removed
|
||||
foreach (var propAlias in macro.RemovedProperties)
|
||||
{
|
||||
//delete the property
|
||||
Database.Delete<MacroPropertyDto>("WHERE macro=@macroId AND macroPropertyAlias=@propAlias",
|
||||
new { macroId = macro.Id, propAlias = propAlias });
|
||||
}
|
||||
|
||||
//for any that exist on the object, we need to determine if we need to update or insert
|
||||
foreach (var propDto in dto.MacroPropertyDtos)
|
||||
{
|
||||
@@ -180,17 +188,15 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
else
|
||||
{
|
||||
Database.Update(propDto);
|
||||
//only update if it's dirty
|
||||
if (macro.Properties[propDto.Alias].IsDirty())
|
||||
{
|
||||
Database.Update(propDto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//now we need to delete any props that have been removed
|
||||
foreach (var propAlias in macro.RemovedProperties)
|
||||
{
|
||||
//delete the property
|
||||
Database.Delete<MacroPropertyDto>("WHERE macro=@macroId AND macroPropertyAlias=@propAlias",
|
||||
new { macroId = macro.Id, propAlias = propAlias });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
((ICanBeDirty)entity).ResetDirtyProperties();
|
||||
|
||||
@@ -285,7 +285,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (group.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
sql = sql.Where<TagDto>(dto => dto.Group == group);
|
||||
}
|
||||
}
|
||||
|
||||
var factory = new TagFactory();
|
||||
|
||||
@@ -329,7 +329,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//NOTE: There's some very clever logic in the umbraco.cms.businesslogic.Tags.Tag to insert tags where they don't exist,
|
||||
// and assign where they don't exist which we've borrowed here. The queries are pretty zany but work, otherwise we'll end up
|
||||
// with quite a few additional queries.
|
||||
|
||||
|
||||
//do all this in one transaction
|
||||
using (var trans = Database.GetTransaction())
|
||||
{
|
||||
@@ -397,7 +397,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
public void RemoveTagsFromProperty(int contentId, int propertyTypeId, IEnumerable<ITag> tags)
|
||||
{
|
||||
var tagSetSql = GetTagSet(tags);
|
||||
|
||||
|
||||
var deleteSql = string.Concat("DELETE FROM cmsTagRelationship WHERE nodeId = ",
|
||||
contentId,
|
||||
" AND propertyTypeId = ",
|
||||
@@ -439,7 +439,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <returns></returns>
|
||||
private static string GetTagSet(IEnumerable<ITag> tagsToInsert)
|
||||
{
|
||||
var array = tagsToInsert.Select(tag => string.Format("select '{0}' as Tag, '{1}' as [Group]", tag.Text.Replace("'", "''"), tag.Group)).ToArray();
|
||||
var array = tagsToInsert
|
||||
.Select(tag =>
|
||||
string.Format("select '{0}' as Tag, '{1}' as [Group]",
|
||||
PetaPocoExtensions.EscapeAtSymbols(tag.Text.Replace("'", "''")), tag.Group))
|
||||
.ToArray();
|
||||
return "(" + string.Join(" union ", array).Replace(" ", " ") + ") as TagSet";
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id",
|
||||
"UPDATE cmsDocument SET templateId = NULL WHERE nodeId = @Id",
|
||||
"UPDATE cmsDocument SET templateId = NULL WHERE templateId = @Id",
|
||||
"DELETE FROM cmsDocumentType WHERE templateNodeId = @Id",
|
||||
"DELETE FROM cmsTemplate WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoNode WHERE id = @Id"
|
||||
|
||||
@@ -44,9 +44,9 @@ namespace Umbraco.Core
|
||||
/// file is cached temporarily until app startup completes.
|
||||
/// </summary>
|
||||
/// <param name="appContext"></param>
|
||||
/// <param name="detectBinChanges"></param>
|
||||
internal PluginManager(ApplicationContext appContext, bool detectBinChanges = true)
|
||||
: this(detectBinChanges)
|
||||
/// <param name="detectChanges"></param>
|
||||
internal PluginManager(ApplicationContext appContext, bool detectChanges = true)
|
||||
: this(detectChanges)
|
||||
{
|
||||
if (appContext == null) throw new ArgumentNullException("appContext");
|
||||
_appContext = appContext;
|
||||
@@ -55,11 +55,11 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Creates a new PluginManager
|
||||
/// </summary>
|
||||
/// <param name="detectCodeChanges">
|
||||
/// If true will detect changes in the /bin folder and therefor load plugins from the
|
||||
/// <param name="detectChanges">
|
||||
/// If true will detect changes in the /bin folder, app_code, etc... and therefor load plugins from the
|
||||
/// cached plugins file if one is found. If false will never use the cache file for plugins
|
||||
/// </param>
|
||||
internal PluginManager(bool detectCodeChanges = true)
|
||||
internal PluginManager(bool detectChanges = true)
|
||||
{
|
||||
_tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
|
||||
//create the folder if it doesn't exist
|
||||
@@ -68,29 +68,41 @@ namespace Umbraco.Core
|
||||
Directory.CreateDirectory(_tempFolder);
|
||||
}
|
||||
|
||||
var pluginListFile = GetPluginListFilePath();
|
||||
|
||||
//this is a check for legacy changes, before we didn't store the TypeResolutionKind in the file which was a mistake,
|
||||
//so we need to detect if the old file is there without this attribute, if it is then we delete it
|
||||
if (DetectLegacyPluginListFile())
|
||||
{
|
||||
var filePath = GetPluginListFilePath();
|
||||
File.Delete(filePath);
|
||||
File.Delete(pluginListFile);
|
||||
}
|
||||
|
||||
if (detectCodeChanges)
|
||||
if (detectChanges)
|
||||
{
|
||||
//first check if the cached hash is 0, if it is then we ne
|
||||
//do the check if they've changed
|
||||
HaveAssembliesChanged = (CachedAssembliesHash != CurrentAssembliesHash) || CachedAssembliesHash == 0;
|
||||
RequiresRescanning = (CachedAssembliesHash != CurrentAssembliesHash) || CachedAssembliesHash == 0;
|
||||
//if they have changed, we need to write the new file
|
||||
if (HaveAssembliesChanged)
|
||||
if (RequiresRescanning)
|
||||
{
|
||||
//if the hash has changed, clear out the persisted list no matter what, this will force
|
||||
// rescanning of all plugin types including lazy ones.
|
||||
// http://issues.umbraco.org/issue/U4-4789
|
||||
File.Delete(pluginListFile);
|
||||
|
||||
WriteCachePluginsHash();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//if the hash has changed, clear out the persisted list no matter what, this will force
|
||||
// rescanning of all plugin types including lazy ones.
|
||||
// http://issues.umbraco.org/issue/U4-4789
|
||||
File.Delete(pluginListFile);
|
||||
|
||||
//always set to true if we're not detecting (generally only for testing)
|
||||
HaveAssembliesChanged = true;
|
||||
RequiresRescanning = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -130,9 +142,9 @@ namespace Umbraco.Core
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a bool if the assemblies in the /bin have changed since they were last hashed.
|
||||
/// Returns a bool if the assemblies in the /bin, app_code, global.asax, etc... have changed since they were last hashed.
|
||||
/// </summary>
|
||||
internal bool HaveAssembliesChanged { get; private set; }
|
||||
internal bool RequiresRescanning { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the currently cached hash value of the scanned assemblies in the /bin folder. Returns 0
|
||||
@@ -328,7 +340,7 @@ namespace Umbraco.Core
|
||||
/// <remarks>
|
||||
/// Generally only used for resetting cache, for example during the install process
|
||||
/// </remarks>
|
||||
internal void ClearPluginCache()
|
||||
public void ClearPluginCache()
|
||||
{
|
||||
var path = GetPluginListFilePath();
|
||||
if (File.Exists(path))
|
||||
@@ -670,7 +682,7 @@ namespace Umbraco.Core
|
||||
|
||||
//we first need to look into our cache file (this has nothing to do with the 'cacheResult' parameter which caches in memory).
|
||||
//if assemblies have not changed and the cache file actually exists, then proceed to try to lookup by the cache file.
|
||||
if (HaveAssembliesChanged == false && File.Exists(GetPluginListFilePath()))
|
||||
if (RequiresRescanning == false && File.Exists(GetPluginListFilePath()))
|
||||
{
|
||||
var fileCacheResult = TryGetCachedPluginsFromFile<T>(resolutionType);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ using System.Security.Permissions;
|
||||
|
||||
[assembly: InternalsVisibleTo("umbraco")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Extensions")]
|
||||
[assembly: InternalsVisibleTo("businesslogic")]
|
||||
[assembly: InternalsVisibleTo("cms")]
|
||||
[assembly: InternalsVisibleTo("umbraco.editorControls")]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
@@ -30,6 +31,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
Delimiter = ",";
|
||||
ReplaceTags = true;
|
||||
TagGroup = "default";
|
||||
StorageType = TagCacheStorageType.Csv;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -37,6 +39,11 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// </summary>
|
||||
public TagValueType ValueType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines how to store the tags in cache (CSV or Json)
|
||||
/// </summary>
|
||||
public TagCacheStorageType StorageType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines a custom delimiter, the default is a comma
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Umbraco.Core.Models.Editors;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Editors;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
@@ -30,8 +31,14 @@ namespace Umbraco.Core.PropertyEditors
|
||||
Delimiter = tagsAttribute.Delimiter;
|
||||
ReplaceTags = tagsAttribute.ReplaceTags;
|
||||
TagGroup = tagsAttribute.TagGroup;
|
||||
StorageType = TagCacheStorageType.Csv;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines how to store the tags in cache (CSV or Json)
|
||||
/// </summary>
|
||||
public virtual TagCacheStorageType StorageType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines a custom delimiter, the default is a comma
|
||||
/// </summary>
|
||||
|
||||
@@ -86,6 +86,7 @@ namespace Umbraco.Core.Security
|
||||
public static UmbracoBackOfficeIdentity GetCurrentIdentity(this HttpContextBase http, bool authenticateRequestIfNotFound)
|
||||
{
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
if (http.User == null) return null; //there's no user at all so no identity
|
||||
var identity = http.User.Identity as UmbracoBackOfficeIdentity;
|
||||
if (identity != null) return identity;
|
||||
if (authenticateRequestIfNotFound == false) return null;
|
||||
|
||||
@@ -1224,8 +1224,8 @@ namespace Umbraco.Core.Services
|
||||
if (SendingToPublish.IsRaisedEventCancelled(new SendToPublishEventArgs<IContent>(content), this))
|
||||
return false;
|
||||
|
||||
//TODO: Do some stuff here.. ... what is it supposed to do ?
|
||||
// pretty sure all that legacy stuff did was raise an event? and we no longer have IActionHandlers so no worries there.
|
||||
//Save before raising event
|
||||
Save(content, userId);
|
||||
|
||||
SentToPublish.RaiseEvent(new SendToPublishEventArgs<IContent>(content, false), this);
|
||||
|
||||
|
||||
@@ -124,7 +124,9 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var collection = repository.GetPreValuesCollectionByDataTypeId(id);
|
||||
//now convert the collection to a string list
|
||||
var list = collection.FormatAsDictionary().Select(x => x.Value.Value).ToList();
|
||||
var list = collection.FormatAsDictionary()
|
||||
.Select(x => x.Value.Value)
|
||||
.ToList();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,10 +207,11 @@ namespace Umbraco.Core.Services
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
var provider = MembershipProviderExtensions.GetUsersMembershipProvider();
|
||||
if (provider.IsUmbracoMembershipProvider())
|
||||
{
|
||||
provider.ChangePassword(user.Username, "", password);
|
||||
}
|
||||
|
||||
if (provider.IsUmbracoMembershipProvider() == false)
|
||||
throw new NotSupportedException("When using a non-Umbraco membership provider you must change the user password by using the MembershipProvider.ChangePassword method");
|
||||
|
||||
provider.ChangePassword(user.Username, "", password);
|
||||
|
||||
//go re-fetch the member and update the properties that may have changed
|
||||
var result = GetByUsername(user.Username);
|
||||
@@ -221,8 +222,6 @@ namespace Umbraco.Core.Services
|
||||
user.LastPasswordChangeDate = result.LastPasswordChangeDate;
|
||||
user.UpdateDate = user.UpdateDate;
|
||||
}
|
||||
|
||||
throw new NotSupportedException("When using a non-Umbraco membership provider you must change the user password by using the MembershipProvider.ChangePassword method");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace Umbraco.Core
|
||||
//this is from SqlMetal and just makes it a bit of fun to allow pluralisation
|
||||
public static string MakePluralName(this string name)
|
||||
{
|
||||
if ((name.EndsWith("x", StringComparison.OrdinalIgnoreCase) || name.EndsWith("ch", StringComparison.OrdinalIgnoreCase)) || (name.EndsWith("ss", StringComparison.OrdinalIgnoreCase) || name.EndsWith("sh", StringComparison.OrdinalIgnoreCase)))
|
||||
if ((name.EndsWith("x", StringComparison.OrdinalIgnoreCase) || name.EndsWith("ch", StringComparison.OrdinalIgnoreCase)) || (name.EndsWith("s", StringComparison.OrdinalIgnoreCase) || name.EndsWith("sh", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
name = name + "es";
|
||||
return name;
|
||||
|
||||
@@ -349,12 +349,14 @@
|
||||
<Compile Include="Models\MemberGroup.cs" />
|
||||
<Compile Include="Models\MemberTypePropertyProfileAccess.cs" />
|
||||
<Compile Include="Models\Notification.cs" />
|
||||
<Compile Include="Models\PropertyTagBehavior.cs" />
|
||||
<Compile Include="Models\PublishedContent\IPublishedContentExtended.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedPropertyBase.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentModelFactoryImpl.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentModelFactory.cs" />
|
||||
<Compile Include="Models\PublishedContent\IPublishedContentModelFactory.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentModel.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentModelFactoryResolver.cs" />
|
||||
<Compile Include="Models\TagCacheStorageType.cs" />
|
||||
<Compile Include="Models\TaggableObjectTypes.cs" />
|
||||
<Compile Include="Models\TemplateNode.cs" />
|
||||
<Compile Include="Models\UmbracoEntityExtensions.cs" />
|
||||
@@ -439,7 +441,7 @@
|
||||
<Compile Include="Models\Macro.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentExtended.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentModelAttribute.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentModelFactory.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentExtensionsForModels.cs" />
|
||||
<Compile Include="Models\MacroProperty.cs" />
|
||||
<Compile Include="Models\MacroPropertyCollection.cs" />
|
||||
<Compile Include="Models\MacroPropertyTypeBaseTypes.cs" />
|
||||
|
||||
@@ -26,27 +26,13 @@ namespace Umbraco.Tests.AngularIntegration
|
||||
{
|
||||
var result = JsInitialization.ParseMain(new[] {"[World]", "Hello" });
|
||||
|
||||
Assert.AreEqual(@"
|
||||
yepnope({
|
||||
load: [
|
||||
'lib/jquery/jquery-2.0.3.min.js',
|
||||
'lib/angular/1.1.5/angular.min.js',
|
||||
'lib/underscore/underscore.js',
|
||||
],
|
||||
complete: function () {
|
||||
yepnope({
|
||||
load: [World],
|
||||
complete: function () {
|
||||
Assert.AreEqual(@"LazyLoad.js([World], function () {
|
||||
//we need to set the legacy UmbClientMgr path
|
||||
UmbClientMgr.setUmbracoPath('Hello');
|
||||
|
||||
//we need to set the legacy UmbClientMgr path
|
||||
UmbClientMgr.setUmbracoPath('Hello');
|
||||
|
||||
jQuery(document).ready(function () {
|
||||
angular.bootstrap(document, ['umbraco']);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
jQuery(document).ready(function () {
|
||||
angular.bootstrap(document, ['umbraco']);
|
||||
});
|
||||
});", result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace Umbraco.Tests.Models
|
||||
[TestFixture]
|
||||
public class ContentTypeTests : BaseUmbracoConfigurationTest
|
||||
{
|
||||
|
||||
|
||||
[Test]
|
||||
public void Can_Deep_Clone_Content_Type_Sort()
|
||||
{
|
||||
@@ -150,6 +152,7 @@ namespace Umbraco.Tests.Models
|
||||
}
|
||||
Assert.AreNotSame(clone.PropertyTypes, contentType.PropertyTypes);
|
||||
Assert.AreEqual(clone.PropertyTypes.Count(), contentType.PropertyTypes.Count());
|
||||
Assert.AreEqual(0, ((ContentTypeBase)clone).NonGroupedPropertyTypes.Count());
|
||||
for (var index = 0; index < contentType.PropertyTypes.Count(); index++)
|
||||
{
|
||||
Assert.AreNotSame(clone.PropertyTypes.ElementAt(index), contentType.PropertyTypes.ElementAt(index));
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
@@ -19,6 +20,7 @@ namespace Umbraco.Tests.Models
|
||||
public void Can_Deep_Clone()
|
||||
{
|
||||
var macro = new Macro(1, true, 3, "test", "Test", "blah", "blah", "xslt", false, true, true, "script");
|
||||
macro.Properties.Add(new MacroProperty(6, "rewq", "REWQ", 1, "asdfasdf"));
|
||||
|
||||
var clone = (Macro)macro.DeepClone();
|
||||
|
||||
@@ -26,6 +28,14 @@ namespace Umbraco.Tests.Models
|
||||
Assert.AreEqual(clone, macro);
|
||||
Assert.AreEqual(clone.Id, macro.Id);
|
||||
|
||||
Assert.AreEqual(clone.Properties.Count, macro.Properties.Count);
|
||||
|
||||
for (int i = 0; i < clone.Properties.Count; i++)
|
||||
{
|
||||
Assert.AreEqual(clone.Properties[i], macro.Properties[i]);
|
||||
Assert.AreNotSame(clone.Properties[i], macro.Properties[i]);
|
||||
}
|
||||
|
||||
Assert.AreNotSame(clone.Properties, macro.Properties);
|
||||
Assert.AreNotSame(clone.AddedProperties, macro.AddedProperties);
|
||||
Assert.AreNotSame(clone.RemovedProperties, macro.RemovedProperties);
|
||||
@@ -44,6 +54,9 @@ namespace Umbraco.Tests.Models
|
||||
Assert.IsFalse(asDirty.IsPropertyDirty("Properties"));
|
||||
clone.Properties.Add(new MacroProperty(3, "asdf", "SDF", 3, "asdfasdf"));
|
||||
Assert.IsTrue(asDirty.IsPropertyDirty("Properties"));
|
||||
Assert.AreEqual(1, clone.AddedProperties.Count());
|
||||
clone.Properties.Remove("rewq");
|
||||
Assert.AreEqual(1, clone.RemovedProperties.Count());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Tests.Models
|
||||
{
|
||||
[TestFixture]
|
||||
public class PreValueCollectionTests
|
||||
{
|
||||
[Test]
|
||||
public void Can_Deep_Clone()
|
||||
{
|
||||
var d = new PreValueCollection(new Dictionary<string, PreValue>
|
||||
{
|
||||
{"blah1", new PreValue(1, "test1", 1)},
|
||||
{"blah2", new PreValue(2, "test1", 3)},
|
||||
{"blah3", new PreValue(3, "test1", 2)}
|
||||
});
|
||||
|
||||
var a = new PreValueCollection(new[]
|
||||
{
|
||||
new PreValue(1, "test1", 1),
|
||||
new PreValue(2, "test1", 3),
|
||||
new PreValue(3, "test1", 2)
|
||||
});
|
||||
|
||||
var clone1 = (PreValueCollection)d.DeepClone();
|
||||
var clone2 = (PreValueCollection)a.DeepClone();
|
||||
|
||||
Action<PreValueCollection, PreValueCollection> assert = (orig, clone) =>
|
||||
{
|
||||
Assert.AreNotSame(orig, clone);
|
||||
var oDic = orig.FormatAsDictionary();
|
||||
var cDic = clone.FormatAsDictionary();
|
||||
Assert.AreEqual(oDic.Keys.Count(), cDic.Keys.Count());
|
||||
foreach (var k in oDic.Keys)
|
||||
{
|
||||
Assert.AreNotSame(oDic[k], cDic[k]);
|
||||
Assert.AreEqual(oDic[k].Id, cDic[k].Id);
|
||||
Assert.AreEqual(oDic[k].SortOrder, cDic[k].SortOrder);
|
||||
Assert.AreEqual(oDic[k].Value, cDic[k].Value);
|
||||
}
|
||||
};
|
||||
|
||||
assert(d, clone1);
|
||||
assert(a, clone2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,12 @@ using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Serialization;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.Models
|
||||
{
|
||||
[TestFixture]
|
||||
public class PropertyGroupTests
|
||||
public class PropertyGroupTests : BaseUmbracoConfigurationTest
|
||||
{
|
||||
[Test]
|
||||
public void Can_Deep_Clone()
|
||||
@@ -37,7 +38,7 @@ namespace Umbraco.Tests.Models
|
||||
Alias = "test2",
|
||||
CreateDate = DateTime.Now,
|
||||
DataTypeDefinitionId = 6,
|
||||
DataTypeId = Guid.NewGuid(),
|
||||
PropertyEditorAlias = "propTest",
|
||||
Description = "testing2",
|
||||
Key = Guid.NewGuid(),
|
||||
Mandatory = true,
|
||||
@@ -118,7 +119,7 @@ namespace Umbraco.Tests.Models
|
||||
Alias = "test2",
|
||||
CreateDate = DateTime.Now,
|
||||
DataTypeDefinitionId = 6,
|
||||
DataTypeId = Guid.NewGuid(),
|
||||
PropertyEditorAlias = "propTest",
|
||||
Description = "testing2",
|
||||
Key = Guid.NewGuid(),
|
||||
Mandatory = true,
|
||||
|
||||
@@ -364,7 +364,58 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Update_Property_For_Macro()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current))
|
||||
{
|
||||
var macro = repository.Get(1);
|
||||
macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test"));
|
||||
repository.AddOrUpdate(macro);
|
||||
unitOfWork.Commit();
|
||||
|
||||
//Act
|
||||
macro = repository.Get(1);
|
||||
macro.Properties["new1"].Name = "this is a new name";
|
||||
repository.AddOrUpdate(macro);
|
||||
unitOfWork.Commit();
|
||||
|
||||
|
||||
// Assert
|
||||
var result = repository.Get(1);
|
||||
Assert.AreEqual("new1", result.Properties.First().Alias);
|
||||
Assert.AreEqual("this is a new name", result.Properties.First().Name);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Update_Macro_Property_Alias()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current))
|
||||
{
|
||||
var macro = repository.Get(1);
|
||||
macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test"));
|
||||
repository.AddOrUpdate(macro);
|
||||
unitOfWork.Commit();
|
||||
|
||||
//Act
|
||||
macro = repository.Get(1);
|
||||
macro.Properties.UpdateProperty("new1", newAlias: "newAlias");
|
||||
repository.AddOrUpdate(macro);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Assert
|
||||
var result = repository.Get(1);
|
||||
Assert.AreEqual("newAlias", result.Properties.First().Alias);
|
||||
}
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public override void TearDown()
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
@@ -10,6 +11,7 @@ using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
namespace Umbraco.Tests.Persistence.Repositories
|
||||
{
|
||||
@@ -37,10 +39,13 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
|
||||
// Act
|
||||
var repository = RepositoryResolver.Current.ResolveByType<ITemplateRepository>(unitOfWork);
|
||||
using (var repository = RepositoryResolver.Current.ResolveByType<ITemplateRepository>(unitOfWork))
|
||||
{
|
||||
|
||||
// Assert
|
||||
Assert.That(repository, Is.Not.Null);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.That(repository, Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -51,10 +56,13 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
|
||||
// Act
|
||||
var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem);
|
||||
using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem))
|
||||
{
|
||||
|
||||
// Assert
|
||||
Assert.That(repository, Is.Not.Null);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.That(repository, Is.Not.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -63,16 +71,18 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem);
|
||||
using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem))
|
||||
{
|
||||
// Act
|
||||
var template = new Template("test-add-masterpage.master", "test", "test") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
repository.AddOrUpdate(template);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
var template = new Template("test-add-masterpage.master", "test", "test") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
repository.AddOrUpdate(template);
|
||||
unitOfWork.Commit();
|
||||
|
||||
//Assert
|
||||
Assert.That(repository.Get("test"), Is.Not.Null);
|
||||
Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True);
|
||||
//Assert
|
||||
Assert.That(repository.Get("test"), Is.Not.Null);
|
||||
Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -81,22 +91,25 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem);
|
||||
using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem))
|
||||
{
|
||||
// Act
|
||||
var template = new Template("test-updated-masterpage.master", "test", "test") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
repository.AddOrUpdate(template);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
var template = new Template("test-updated-masterpage.master", "test", "test") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
repository.AddOrUpdate(template);
|
||||
unitOfWork.Commit();
|
||||
template.Content = @"<%@ Master Language=""VB"" %>";
|
||||
repository.AddOrUpdate(template);
|
||||
unitOfWork.Commit();
|
||||
|
||||
template.Content = @"<%@ Master Language=""VB"" %>";
|
||||
repository.AddOrUpdate(template);
|
||||
unitOfWork.Commit();
|
||||
var updated = repository.Get("test");
|
||||
|
||||
var updated = repository.Get("test");
|
||||
// Assert
|
||||
Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True);
|
||||
Assert.That(updated.Content, Is.EqualTo(@"<%@ Master Language=""VB"" %>"));
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.That(_masterPageFileSystem.FileExists("test.master"), Is.True);
|
||||
Assert.That(updated.Content, Is.EqualTo(@"<%@ Master Language=""VB"" %>"));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -105,19 +118,64 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem);
|
||||
using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem))
|
||||
{
|
||||
var template = new Template("test-add-masterpage.master", "test", "test") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
repository.AddOrUpdate(template);
|
||||
unitOfWork.Commit();
|
||||
|
||||
var template = new Template("test-add-masterpage.master", "test", "test") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
repository.AddOrUpdate(template);
|
||||
unitOfWork.Commit();
|
||||
// Act
|
||||
var templates = repository.Get("test");
|
||||
repository.Delete(templates);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
var templates = repository.Get("test");
|
||||
repository.Delete(templates);
|
||||
unitOfWork.Commit();
|
||||
// Assert
|
||||
Assert.IsNull(repository.Get("test"));
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(repository.Get("test"));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_Delete_When_Assigned_To_Doc()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
|
||||
var templateRepository = new TemplateRepository(unitOfWork, NullCacheProvider.Current);
|
||||
var tagRepository = new TagsRepository(unitOfWork, NullCacheProvider.Current);
|
||||
var contentTypeRepository = new ContentTypeRepository(unitOfWork, NullCacheProvider.Current, templateRepository);
|
||||
var contentRepo = new ContentRepository(unitOfWork, NullCacheProvider.Current, contentTypeRepository, templateRepository, tagRepository, CacheHelper.CreateDisabledCacheHelper());
|
||||
|
||||
using (contentRepo)
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage");
|
||||
var textpage = MockedContent.CreateSimpleContent(contentType);
|
||||
contentTypeRepository.AddOrUpdate(contentType);
|
||||
contentRepo.AddOrUpdate(textpage);
|
||||
unitOfWork.Commit();
|
||||
|
||||
using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem))
|
||||
{
|
||||
var template = new Template("test-add-masterpage.master", "test", "test") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
repository.AddOrUpdate(template);
|
||||
unitOfWork.Commit();
|
||||
|
||||
textpage.Template = template;
|
||||
contentRepo.AddOrUpdate(textpage);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
var templates = repository.Get("test");
|
||||
repository.Delete(templates);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(repository.Get("test"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -126,27 +184,30 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem);
|
||||
using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem))
|
||||
{
|
||||
var parent = new Template("test-parent-masterpage.master", "parent", "parent") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var child = new Template("test-child-masterpage.master", "child", "child") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var baby = new Template("test-baby-masterpage.master", "baby", "baby") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
child.MasterTemplateAlias = parent.Alias;
|
||||
child.MasterTemplateId = new Lazy<int>(() => parent.Id);
|
||||
baby.MasterTemplateAlias = child.Alias;
|
||||
baby.MasterTemplateId = new Lazy<int>(() => child.Id);
|
||||
repository.AddOrUpdate(parent);
|
||||
repository.AddOrUpdate(child);
|
||||
repository.AddOrUpdate(baby);
|
||||
unitOfWork.Commit();
|
||||
|
||||
var parent = new Template("test-parent-masterpage.master", "parent", "parent") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var child = new Template("test-child-masterpage.master", "child", "child") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var baby = new Template("test-baby-masterpage.master", "baby", "baby") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
child.MasterTemplateAlias = parent.Alias;
|
||||
child.MasterTemplateId = new Lazy<int>(() => parent.Id);
|
||||
baby.MasterTemplateAlias = child.Alias;
|
||||
baby.MasterTemplateId = new Lazy<int>(() => child.Id);
|
||||
repository.AddOrUpdate(parent);
|
||||
repository.AddOrUpdate(child);
|
||||
repository.AddOrUpdate(baby);
|
||||
unitOfWork.Commit();
|
||||
// Act
|
||||
var templates = repository.Get("parent");
|
||||
repository.Delete(templates);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
var templates = repository.Get("parent");
|
||||
repository.Delete(templates);
|
||||
unitOfWork.Commit();
|
||||
// Assert
|
||||
Assert.IsNull(repository.Get("test"));
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(repository.Get("test"));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -155,66 +216,69 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem);
|
||||
using (var repository = new TemplateRepository(unitOfWork, NullCacheProvider.Current, _masterPageFileSystem, _viewsFileSystem))
|
||||
{
|
||||
var parent = new Template("test-parent-masterpage.master", "parent", "parent") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
|
||||
var child1 = new Template("test-child1-masterpage.master", "child1", "child1") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var toddler1 = new Template("test-toddler1-masterpage.master", "toddler1", "toddler1") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var toddler2 = new Template("test-toddler2-masterpage.master", "toddler2", "toddler2") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var baby1 = new Template("test-baby1-masterpage.master", "baby1", "baby1") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
|
||||
var child2 = new Template("test-child2-masterpage.master", "child2", "child2") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var toddler3 = new Template("test-toddler3-masterpage.master", "toddler3", "toddler3") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var toddler4 = new Template("test-toddler4-masterpage.master", "toddler4", "toddler4") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var baby2 = new Template("test-baby2-masterpage.master", "baby2", "baby2") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
|
||||
|
||||
child1.MasterTemplateAlias = parent.Alias;
|
||||
child1.MasterTemplateId = new Lazy<int>(() => parent.Id);
|
||||
child2.MasterTemplateAlias = parent.Alias;
|
||||
child2.MasterTemplateId = new Lazy<int>(() => parent.Id);
|
||||
|
||||
toddler1.MasterTemplateAlias = child1.Alias;
|
||||
toddler1.MasterTemplateId = new Lazy<int>(() => child1.Id);
|
||||
toddler2.MasterTemplateAlias = child1.Alias;
|
||||
toddler2.MasterTemplateId = new Lazy<int>(() => child1.Id);
|
||||
|
||||
toddler3.MasterTemplateAlias = child2.Alias;
|
||||
toddler3.MasterTemplateId = new Lazy<int>(() => child2.Id);
|
||||
toddler4.MasterTemplateAlias = child2.Alias;
|
||||
toddler4.MasterTemplateId = new Lazy<int>(() => child2.Id);
|
||||
|
||||
baby1.MasterTemplateAlias = toddler2.Alias;
|
||||
baby1.MasterTemplateId = new Lazy<int>(() => toddler2.Id);
|
||||
|
||||
baby2.MasterTemplateAlias = toddler4.Alias;
|
||||
baby2.MasterTemplateId = new Lazy<int>(() => toddler4.Id);
|
||||
|
||||
repository.AddOrUpdate(parent);
|
||||
repository.AddOrUpdate(child1);
|
||||
repository.AddOrUpdate(child2);
|
||||
repository.AddOrUpdate(toddler1);
|
||||
repository.AddOrUpdate(toddler2);
|
||||
repository.AddOrUpdate(toddler3);
|
||||
repository.AddOrUpdate(toddler4);
|
||||
repository.AddOrUpdate(baby1);
|
||||
repository.AddOrUpdate(baby2);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
var rootNode = repository.GetTemplateNode("parent");
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "parent"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "child1"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "child2"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "toddler1"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "toddler2"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "toddler3"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "toddler4"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "baby1"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "baby2"));
|
||||
}
|
||||
|
||||
var parent = new Template("test-parent-masterpage.master", "parent", "parent") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
|
||||
var child1 = new Template("test-child1-masterpage.master", "child1", "child1") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var toddler1 = new Template("test-toddler1-masterpage.master", "toddler1", "toddler1") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var toddler2 = new Template("test-toddler2-masterpage.master", "toddler2", "toddler2") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var baby1 = new Template("test-baby1-masterpage.master", "baby1", "baby1") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
|
||||
var child2 = new Template("test-child2-masterpage.master", "child2", "child2") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var toddler3 = new Template("test-toddler3-masterpage.master", "toddler3", "toddler3") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var toddler4 = new Template("test-toddler4-masterpage.master", "toddler4", "toddler4") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
var baby2 = new Template("test-baby2-masterpage.master", "baby2", "baby2") { Content = @"<%@ Master Language=""C#"" %>" };
|
||||
|
||||
|
||||
child1.MasterTemplateAlias = parent.Alias;
|
||||
child1.MasterTemplateId = new Lazy<int>(() => parent.Id);
|
||||
child2.MasterTemplateAlias = parent.Alias;
|
||||
child2.MasterTemplateId = new Lazy<int>(() => parent.Id);
|
||||
|
||||
toddler1.MasterTemplateAlias = child1.Alias;
|
||||
toddler1.MasterTemplateId = new Lazy<int>(() => child1.Id);
|
||||
toddler2.MasterTemplateAlias = child1.Alias;
|
||||
toddler2.MasterTemplateId = new Lazy<int>(() => child1.Id);
|
||||
|
||||
toddler3.MasterTemplateAlias = child2.Alias;
|
||||
toddler3.MasterTemplateId = new Lazy<int>(() => child2.Id);
|
||||
toddler4.MasterTemplateAlias = child2.Alias;
|
||||
toddler4.MasterTemplateId = new Lazy<int>(() => child2.Id);
|
||||
|
||||
baby1.MasterTemplateAlias = toddler2.Alias;
|
||||
baby1.MasterTemplateId = new Lazy<int>(() => toddler2.Id);
|
||||
|
||||
baby2.MasterTemplateAlias = toddler4.Alias;
|
||||
baby2.MasterTemplateId = new Lazy<int>(() => toddler4.Id);
|
||||
|
||||
repository.AddOrUpdate(parent);
|
||||
repository.AddOrUpdate(child1);
|
||||
repository.AddOrUpdate(child2);
|
||||
repository.AddOrUpdate(toddler1);
|
||||
repository.AddOrUpdate(toddler2);
|
||||
repository.AddOrUpdate(toddler3);
|
||||
repository.AddOrUpdate(toddler4);
|
||||
repository.AddOrUpdate(baby1);
|
||||
repository.AddOrUpdate(baby2);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
var rootNode = repository.GetTemplateNode("parent");
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "parent"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "child1"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "child2"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "toddler1"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "toddler2"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "toddler3"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "toddler4"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "baby1"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "baby2"));
|
||||
}
|
||||
|
||||
//[Test]
|
||||
|
||||
@@ -44,8 +44,9 @@ namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
PropertyValueConvertersResolver.Current =
|
||||
new PropertyValueConvertersResolver();
|
||||
var types = PluginManager.Current.ResolveTypes<PublishedContentModel>();
|
||||
PublishedContentModelFactoryResolver.Current =
|
||||
new PublishedContentModelFactoryResolver(new PublishedContentModelFactoryImpl());
|
||||
new PublishedContentModelFactoryResolver(new PublishedContentModelFactory(types));
|
||||
|
||||
base.FreezeResolution();
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
|
||||
public void Add(SolidPublishedContent content)
|
||||
{
|
||||
_content[content.Id] = PublishedContentModelFactory.CreateModel(content);
|
||||
_content[content.Id] = content.CreateModel();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
|
||||
@@ -63,8 +63,9 @@ namespace Umbraco.Tests.PublishedContent
|
||||
|
||||
protected override void FreezeResolution()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveTypes<PublishedContentModel>();
|
||||
PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver(
|
||||
new PublishedContentModelFactoryImpl());
|
||||
new PublishedContentModelFactory(types));
|
||||
base.FreezeResolution();
|
||||
}
|
||||
|
||||
@@ -221,7 +222,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
var doc = GetNode(1173);
|
||||
|
||||
var items = doc.Children
|
||||
.Select(PublishedContentModelFactory.CreateModel) // linq, returns IEnumerable<IPublishedContent>
|
||||
.Select(x => x.CreateModel()) // linq, returns IEnumerable<IPublishedContent>
|
||||
|
||||
// only way around this is to make sure every IEnumerable<T> extension
|
||||
// explicitely returns a PublishedContentSet, not an IEnumerable<T>
|
||||
|
||||
@@ -150,6 +150,40 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Add_And_Remove_Properties()
|
||||
{
|
||||
var macroService = ServiceContext.MacroService;
|
||||
var macro = new Macro("test", "Test", scriptPath: "~/Views/MacroPartials/Test.cshtml", cacheDuration: 1234);
|
||||
|
||||
//adds some properties
|
||||
macro.Properties.Add(new MacroProperty("blah1", "Blah1", 0, "blah1"));
|
||||
macro.Properties.Add(new MacroProperty("blah2", "Blah2", 0, "blah2"));
|
||||
macro.Properties.Add(new MacroProperty("blah3", "Blah3", 0, "blah3"));
|
||||
macro.Properties.Add(new MacroProperty("blah4", "Blah4", 0, "blah4"));
|
||||
macroService.Save(macro);
|
||||
|
||||
var result1 = macroService.GetById(macro.Id);
|
||||
Assert.AreEqual(4, result1.Properties.Count());
|
||||
|
||||
//simulate clearing the sections
|
||||
foreach (var s in result1.Properties.ToArray())
|
||||
{
|
||||
result1.Properties.Remove(s.Alias);
|
||||
}
|
||||
//now just re-add a couple
|
||||
result1.Properties.Add(new MacroProperty("blah3", "Blah3", 0, "blah3"));
|
||||
result1.Properties.Add(new MacroProperty("blah4", "Blah4", 0, "blah4"));
|
||||
macroService.Save(result1);
|
||||
|
||||
//assert
|
||||
|
||||
//re-get
|
||||
result1 = macroService.GetById(result1.Id);
|
||||
Assert.AreEqual(2, result1.Properties.Count());
|
||||
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void Can_Get_Many_By_Alias()
|
||||
//{
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
<Compile Include="Models\LanguageTests.cs" />
|
||||
<Compile Include="Models\MemberGroupTests.cs" />
|
||||
<Compile Include="Models\MemberTests.cs" />
|
||||
<Compile Include="Models\PreValueCollectionTests.cs" />
|
||||
<Compile Include="Models\PropertyGroupTests.cs" />
|
||||
<Compile Include="Models\PropertyTypeTests.cs" />
|
||||
<Compile Include="Models\RelationTests.cs" />
|
||||
|
||||
@@ -55,7 +55,22 @@ function authResource($q, $http, umbRequestHelper, angularHelper) {
|
||||
umbRequestHelper.getApiUrl(
|
||||
"authenticationApiBaseUrl",
|
||||
"IsAuthenticated")),
|
||||
'Server call failed for checking authentication');
|
||||
{
|
||||
success: function (data, status, headers, config) {
|
||||
//if the response is false, they are not logged in so return a rejection
|
||||
if (data === false || data === "false") {
|
||||
return $q.reject('User is not logged in');
|
||||
}
|
||||
return data;
|
||||
},
|
||||
error: function (data, status, headers, config) {
|
||||
return {
|
||||
errorMsg: 'Server call failed for checking authentication',
|
||||
data: data,
|
||||
status: status
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Gets the user's remaining seconds before their login times out */
|
||||
|
||||
@@ -81,7 +81,7 @@ function dataTypeResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
umbRequestHelper.getApiUrl(
|
||||
"dataTypeApiBaseUrl",
|
||||
"GetAll")),
|
||||
'Failed to retreive data');
|
||||
'Failed to retrieve data');
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -118,7 +118,7 @@ function dataTypeResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
umbRequestHelper.getApiUrl(
|
||||
"dataTypeApiBaseUrl",
|
||||
"GetEmpty")),
|
||||
'Failed to retreive data for empty datatype');
|
||||
'Failed to retrieve data for empty datatype');
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
|
||||
@@ -146,7 +146,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"GetByIds",
|
||||
query)),
|
||||
'Failed to retreive entity data for ids ' + ids);
|
||||
'Failed to retrieve entity data for ids ' + ids);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -192,7 +192,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"GetAll",
|
||||
query)),
|
||||
'Failed to retreive entity data for type ' + type);
|
||||
'Failed to retrieve entity data for type ' + type);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -215,7 +215,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"GetAncestors",
|
||||
[{id: id}, {type: type}])),
|
||||
'Failed to retreive ancestor data for id ' + id);
|
||||
'Failed to retrieve ancestor data for id ' + id);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -238,7 +238,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"GetChildren",
|
||||
[{ id: id }, { type: type }])),
|
||||
'Failed to retreive child data for id ' + id);
|
||||
'Failed to retrieve child data for id ' + id);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -271,7 +271,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"Search",
|
||||
[{ query: query }, {type: type}])),
|
||||
'Failed to retreive entity data for query ' + query);
|
||||
'Failed to retrieve entity data for query ' + query);
|
||||
},
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"SearchAll",
|
||||
[{ query: query }])),
|
||||
'Failed to retreive entity data for query ' + query);
|
||||
'Failed to retrieve entity data for query ' + query);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -99,7 +99,7 @@ function logResource($q, $http, umbRequestHelper) {
|
||||
"logApiBaseUrl",
|
||||
"GetLog",
|
||||
[{ logtype: type, sinceDate: since }])),
|
||||
'Failed to retreive user data for id ' + id);
|
||||
'Failed to retrieve user data for id ' + id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetEmpty")),
|
||||
'Failed to retreive data for empty member item type ' + alias);
|
||||
'Failed to retrieve data for empty member item type ' + alias);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
@@ -93,7 +93,7 @@ function stylesheetResource($q, $http, umbRequestHelper) {
|
||||
"stylesheetApiBaseUrl",
|
||||
"GetRulesByName",
|
||||
[{ name: name }])),
|
||||
'Failed to retreive stylesheets ');
|
||||
'Failed to retrieve stylesheets ');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ function treeResource($q, $http, umbRequestHelper) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(getTreeNodesUrl(options.node)),
|
||||
'Failed to retreive data for child nodes ' + options.node.nodeId);
|
||||
'Failed to retrieve data for child nodes ' + options.node.nodeId);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -178,9 +178,8 @@ angular.module('umbraco.services')
|
||||
* @methodOf umbraco.services.assetsService
|
||||
*
|
||||
* @description
|
||||
* Injects a collection of files, this can be a mixed collection of css and js files, the loader will determine how to load them
|
||||
* Injects a collection of files, this can be ONLY js files
|
||||
*
|
||||
* **Warning:** if the collection of files contains a .css file, you will in some cases not receive a resolved promise, it is therefore prefered to use the individual loadCss and loadJs methods
|
||||
*
|
||||
* @param {Array} pathArray string array of paths to the files to load
|
||||
* @param {Scope} scope optional scope to pass into the loader
|
||||
|
||||
@@ -114,11 +114,11 @@ function cropperHelper(umbRequestHelper, $http) {
|
||||
crop.x2 = x2_px / image.width;
|
||||
crop.y2 = y2_px / image.height;
|
||||
|
||||
_.forEach(crop, function(coord){
|
||||
if(coord < 0){
|
||||
coord = 0;
|
||||
for(var coord in crop){
|
||||
if(crop[coord] < 0){
|
||||
crop[coord] = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return crop;
|
||||
},
|
||||
|
||||
@@ -31,476 +31,491 @@
|
||||
angular.module('umbraco.services')
|
||||
.factory('dialogService', function ($rootScope, $compile, $http, $timeout, $q, $templateCache, appState, eventsService) {
|
||||
|
||||
var dialogs = [];
|
||||
|
||||
/** Internal method that removes all dialogs */
|
||||
function removeAllDialogs(args) {
|
||||
for (var i = 0; i < dialogs.length; i++) {
|
||||
var dialog = dialogs[i];
|
||||
dialog.close(args);
|
||||
dialogs.splice(i, 1);
|
||||
}
|
||||
}
|
||||
var dialogs = [];
|
||||
|
||||
/** Internal method that handles opening all dialogs */
|
||||
function openDialog(options) {
|
||||
var defaults = {
|
||||
container: $("body"),
|
||||
animation: "fade",
|
||||
modalClass: "umb-modal",
|
||||
width: "100%",
|
||||
inline: false,
|
||||
iframe: false,
|
||||
show: true,
|
||||
template: "views/common/notfound.html",
|
||||
callback: undefined,
|
||||
closeCallback: undefined,
|
||||
element: undefined,
|
||||
//this allows us to pass in data to the dialog if required which can be used to configure the dialog
|
||||
//and re-use it for different purposes. It will set on to the $scope.dialogData if it is defined.
|
||||
dialogData: undefined
|
||||
};
|
||||
|
||||
var dialog = angular.extend(defaults, options);
|
||||
var scope = options.scope || $rootScope.$new();
|
||||
|
||||
//Modal dom obj and unique id
|
||||
dialog.element = $('<div ng-swipe-right="swipeHide($event)" data-backdrop="false"></div>');
|
||||
var id = dialog.template.replace('.html', '').replace('.aspx', '').replace(/[\/|\.|:\&\?\=]/g, "-") + '-' + scope.$id;
|
||||
/** Internal method that removes all dialogs */
|
||||
function removeAllDialogs(args) {
|
||||
for (var i = 0; i < dialogs.length; i++) {
|
||||
var dialog = dialogs[i];
|
||||
dialog.close(args);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.inline) {
|
||||
dialog.animation = "";
|
||||
}
|
||||
else {
|
||||
dialog.element.addClass("modal");
|
||||
dialog.element.addClass("hide");
|
||||
}
|
||||
/** Internal method that closes the dialog properly and cleans up resources */
|
||||
function closeDialog(dialog) {
|
||||
|
||||
//set the id and add classes
|
||||
dialog.element
|
||||
.attr('id', id)
|
||||
.addClass(dialog.animation)
|
||||
.addClass(dialog.modalClass);
|
||||
if (dialog.element) {
|
||||
dialog.element.modal('hide');
|
||||
|
||||
//push the modal into the global modal collection
|
||||
//we halt the .push because a link click will trigger a closeAll right away
|
||||
$timeout(function () {
|
||||
dialogs.push(dialog);
|
||||
}, 500);
|
||||
|
||||
|
||||
dialog.close = function(data) {
|
||||
if (dialog.closeCallback) {
|
||||
dialog.closeCallback(data);
|
||||
}
|
||||
|
||||
if(dialog.element){
|
||||
dialog.element.modal('hide');
|
||||
|
||||
//this is not entirely enough since the damn
|
||||
//webforms scriploader still complains
|
||||
if(dialog.iframe){
|
||||
dialog.element.find("iframe").attr("src", "about:blank");
|
||||
$timeout(function(){
|
||||
dialog.element.remove();
|
||||
}, 1000);
|
||||
}else{
|
||||
//this is not entirely enough since the damn webforms scriploader still complains
|
||||
if (dialog.iframe) {
|
||||
dialog.element.find("iframe").attr("src", "about:blank");
|
||||
$timeout(function () {
|
||||
//we need to do more than just remove the element, this will not destroy the
|
||||
// scope in angular 1.1x, in angular 1.2x this is taken care of but if we dont
|
||||
// take care of this ourselves we have memory leaks.
|
||||
dialog.element.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
//SD: No idea why this is required but was there before - pretty sure it's not required
|
||||
$("#" + dialog.element.attr("id")).remove();
|
||||
dialog.scope.$destroy();
|
||||
}, 1000);
|
||||
} else {
|
||||
//we need to do more than just remove the element, this will not destroy the
|
||||
// scope in angular 1.1x, in angular 1.2x this is taken care of but if we dont
|
||||
// take care of this ourselves we have memory leaks.
|
||||
dialog.element.remove();
|
||||
//SD: No idea why this is required but was there before - pretty sure it's not required
|
||||
$("#" + dialog.element.attr("id")).remove();
|
||||
dialog.scope.$destroy();
|
||||
}
|
||||
}
|
||||
|
||||
//if iframe is enabled, inject that instead of a template
|
||||
if (dialog.iframe) {
|
||||
var html = $("<iframe src='" + dialog.template + "' class='auto-expand' style='border: none; width: 100%; height: 100%;'></iframe>");
|
||||
dialog.element.html(html);
|
||||
|
||||
//append to body or whatever element is passed in as options.containerElement
|
||||
dialog.container.append(dialog.element);
|
||||
//remove 'this' dialog from the dialogs array
|
||||
dialogs = _.reject(dialogs, function (i) { return i === dialog; });
|
||||
}
|
||||
|
||||
// Compile modal content
|
||||
$timeout(function () {
|
||||
$compile(dialog.element)(dialog.scope);
|
||||
});
|
||||
/** Internal method that handles opening all dialogs */
|
||||
function openDialog(options) {
|
||||
var defaults = {
|
||||
container: $("body"),
|
||||
animation: "fade",
|
||||
modalClass: "umb-modal",
|
||||
width: "100%",
|
||||
inline: false,
|
||||
iframe: false,
|
||||
show: true,
|
||||
template: "views/common/notfound.html",
|
||||
callback: undefined,
|
||||
closeCallback: undefined,
|
||||
element: undefined,
|
||||
// It will set this value as a property on the dialog controller's scope as dialogData,
|
||||
// used to pass in custom data to the dialog controller's $scope. Though this is near identical to
|
||||
// the dialogOptions property that is also set the the dialog controller's $scope object.
|
||||
// So there's basically 2 ways of doing the same thing which we're now stuck with and in fact
|
||||
// dialogData has another specially attached property called .selection which gets used.
|
||||
dialogData: undefined
|
||||
};
|
||||
|
||||
dialog.element.css("width", dialog.width);
|
||||
var dialog = angular.extend(defaults, options);
|
||||
|
||||
//NOTE: People should NOT pass in a scope object that is legacy functoinality and causes problems. We will ALWAYS
|
||||
// destroy the scope when the dialog is closed regardless if it is in use elsewhere which is why it shouldn't be done.
|
||||
var scope = options.scope || $rootScope.$new();
|
||||
|
||||
//Autoshow
|
||||
if (dialog.show) {
|
||||
dialog.element.modal('show');
|
||||
}
|
||||
//Modal dom obj and unique id
|
||||
dialog.element = $('<div ng-swipe-right="swipeHide($event)" data-backdrop="false"></div>');
|
||||
var id = dialog.template.replace('.html', '').replace('.aspx', '').replace(/[\/|\.|:\&\?\=]/g, "-") + '-' + scope.$id;
|
||||
|
||||
dialog.scope = scope;
|
||||
return dialog;
|
||||
}
|
||||
else {
|
||||
|
||||
//We need to load the template with an httpget and once it's loaded we'll compile and assign the result to the container
|
||||
// object. However since the result could be a promise or just data we need to use a $q.when. We still need to return the
|
||||
// $modal object so we'll actually return the modal object synchronously without waiting for the promise. Otherwise this openDialog
|
||||
// method will always need to return a promise which gets nasty because of promises in promises plus the result just needs a reference
|
||||
// to the $modal object which will not change (only it's contents will change).
|
||||
$q.when($templateCache.get(dialog.template) || $http.get(dialog.template, { cache: true }).then(function(res) { return res.data; }))
|
||||
.then(function onSuccess(template) {
|
||||
if (options.inline) {
|
||||
dialog.animation = "";
|
||||
}
|
||||
else {
|
||||
dialog.element.addClass("modal");
|
||||
dialog.element.addClass("hide");
|
||||
}
|
||||
|
||||
// Build modal object
|
||||
dialog.element.html(template);
|
||||
//set the id and add classes
|
||||
dialog.element
|
||||
.attr('id', id)
|
||||
.addClass(dialog.animation)
|
||||
.addClass(dialog.modalClass);
|
||||
|
||||
//append to body or other container element
|
||||
dialog.container.append(dialog.element);
|
||||
|
||||
// Compile modal content
|
||||
$timeout(function() {
|
||||
$compile(dialog.element)(scope);
|
||||
});
|
||||
//push the modal into the global modal collection
|
||||
//we halt the .push because a link click will trigger a closeAll right away
|
||||
$timeout(function () {
|
||||
dialogs.push(dialog);
|
||||
}, 500);
|
||||
|
||||
scope.dialogOptions = dialog;
|
||||
|
||||
//Scope to handle data from the modal form
|
||||
scope.dialogData = dialog.dialogData ? dialog.dialogData : {};
|
||||
scope.dialogData.selection = [];
|
||||
|
||||
// Provide scope display functions
|
||||
//this passes the modal to the current scope
|
||||
scope.$modal = function(name) {
|
||||
dialog.element.modal(name);
|
||||
};
|
||||
dialog.close = function (data) {
|
||||
if (dialog.closeCallback) {
|
||||
dialog.closeCallback(data);
|
||||
}
|
||||
|
||||
scope.swipeHide = function(e){
|
||||
if(appState.getGlobalState("touchDevice")){
|
||||
closeDialog(dialog);
|
||||
};
|
||||
|
||||
//if iframe is enabled, inject that instead of a template
|
||||
if (dialog.iframe) {
|
||||
var html = $("<iframe src='" + dialog.template + "' class='auto-expand' style='border: none; width: 100%; height: 100%;'></iframe>");
|
||||
dialog.element.html(html);
|
||||
|
||||
//append to body or whatever element is passed in as options.containerElement
|
||||
dialog.container.append(dialog.element);
|
||||
|
||||
// Compile modal content
|
||||
$timeout(function () {
|
||||
$compile(dialog.element)(dialog.scope);
|
||||
});
|
||||
|
||||
dialog.element.css("width", dialog.width);
|
||||
|
||||
//Autoshow
|
||||
if (dialog.show) {
|
||||
dialog.element.modal('show');
|
||||
}
|
||||
|
||||
dialog.scope = scope;
|
||||
return dialog;
|
||||
}
|
||||
else {
|
||||
|
||||
//We need to load the template with an httpget and once it's loaded we'll compile and assign the result to the container
|
||||
// object. However since the result could be a promise or just data we need to use a $q.when. We still need to return the
|
||||
// $modal object so we'll actually return the modal object synchronously without waiting for the promise. Otherwise this openDialog
|
||||
// method will always need to return a promise which gets nasty because of promises in promises plus the result just needs a reference
|
||||
// to the $modal object which will not change (only it's contents will change).
|
||||
$q.when($templateCache.get(dialog.template) || $http.get(dialog.template, { cache: true }).then(function (res) { return res.data; }))
|
||||
.then(function onSuccess(template) {
|
||||
|
||||
// Build modal object
|
||||
dialog.element.html(template);
|
||||
|
||||
//append to body or other container element
|
||||
dialog.container.append(dialog.element);
|
||||
|
||||
// Compile modal content
|
||||
$timeout(function () {
|
||||
$compile(dialog.element)(scope);
|
||||
});
|
||||
|
||||
scope.dialogOptions = dialog;
|
||||
|
||||
//Scope to handle data from the modal form
|
||||
scope.dialogData = dialog.dialogData ? dialog.dialogData : {};
|
||||
scope.dialogData.selection = [];
|
||||
|
||||
// Provide scope display functions
|
||||
//this passes the modal to the current scope
|
||||
scope.$modal = function (name) {
|
||||
dialog.element.modal(name);
|
||||
};
|
||||
|
||||
scope.swipeHide = function (e) {
|
||||
if (appState.getGlobalState("touchDevice")) {
|
||||
var selection = window.getSelection();
|
||||
if(selection.type !== "Range"){
|
||||
scope.hide();
|
||||
if (selection.type !== "Range") {
|
||||
scope.hide();
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
scope.hide = function() {
|
||||
dialog.element.modal('hide');
|
||||
//NOTE: Same as 'close' without the callbacks
|
||||
scope.hide = function () {
|
||||
closeDialog(dialog);
|
||||
};
|
||||
|
||||
dialog.element.remove();
|
||||
$("#" + dialog.element.attr("id")).remove();
|
||||
};
|
||||
//basic events for submitting and closing
|
||||
scope.submit = function (data) {
|
||||
if (dialog.callback) {
|
||||
dialog.callback(data);
|
||||
}
|
||||
|
||||
//basic events for submitting and closing
|
||||
scope.submit = function(data) {
|
||||
if (dialog.callback) {
|
||||
dialog.callback(data);
|
||||
}
|
||||
closeDialog(dialog);
|
||||
};
|
||||
|
||||
dialog.element.modal('hide');
|
||||
dialog.element.remove();
|
||||
$("#" + dialog.element.attr("id")).remove();
|
||||
};
|
||||
|
||||
scope.close = function(data) {
|
||||
scope.close = function (data) {
|
||||
dialog.close(data);
|
||||
};
|
||||
};
|
||||
|
||||
//NOTE: This can ONLY ever be used to show the dialog if dialog.show is false (autoshow).
|
||||
// You CANNOT call show() after you call hide(). hide = close, they are the same thing and once
|
||||
// a dialog is closed it's resources are disposed of.
|
||||
scope.show = function () {
|
||||
dialog.element.modal('show');
|
||||
};
|
||||
|
||||
scope.show = function() {
|
||||
dialog.element.modal('show');
|
||||
};
|
||||
|
||||
scope.select = function(item) {
|
||||
scope.select = function (item) {
|
||||
var i = scope.dialogData.selection.indexOf(item);
|
||||
if (i < 0) {
|
||||
scope.dialogData.selection.push(item);
|
||||
}else{
|
||||
if (i < 0) {
|
||||
scope.dialogData.selection.push(item);
|
||||
} else {
|
||||
scope.dialogData.selection.splice(i, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
scope.dismiss = scope.hide;
|
||||
//NOTE: Same as 'close' without the callbacks
|
||||
scope.dismiss = scope.hide;
|
||||
|
||||
// Emit modal events
|
||||
angular.forEach(['show', 'shown', 'hide', 'hidden'], function(name) {
|
||||
dialog.element.on(name, function(ev) {
|
||||
scope.$emit('modal-' + name, ev);
|
||||
});
|
||||
});
|
||||
// Emit modal events
|
||||
angular.forEach(['show', 'shown', 'hide', 'hidden'], function (name) {
|
||||
dialog.element.on(name, function (ev) {
|
||||
scope.$emit('modal-' + name, ev);
|
||||
});
|
||||
});
|
||||
|
||||
// Support autofocus attribute
|
||||
dialog.element.on('shown', function(event) {
|
||||
$('input[autofocus]', dialog.element).first().trigger('focus');
|
||||
});
|
||||
// Support autofocus attribute
|
||||
dialog.element.on('shown', function (event) {
|
||||
$('input[autofocus]', dialog.element).first().trigger('focus');
|
||||
});
|
||||
|
||||
//Autoshow
|
||||
if (dialog.show) {
|
||||
dialog.element.modal('show');
|
||||
}
|
||||
//Autoshow
|
||||
if (dialog.show) {
|
||||
dialog.element.modal('show');
|
||||
}
|
||||
|
||||
dialog.scope = scope;
|
||||
});
|
||||
|
||||
//Return the modal object outside of the promise!
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
dialog.scope = scope;
|
||||
});
|
||||
|
||||
/** Handles the closeDialogs event */
|
||||
eventsService.on("app.closeDialogs", function (evt, args) {
|
||||
removeAllDialogs(args);
|
||||
});
|
||||
//Return the modal object outside of the promise!
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#open
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a modal rendering a given template url.
|
||||
*
|
||||
* @param {Object} options rendering options
|
||||
* @param {DomElement} options.container the DOM element to inject the modal into, by default set to body
|
||||
* @param {Function} options.callback function called when the modal is submitted
|
||||
* @param {String} options.template the url of the template
|
||||
* @param {String} options.animation animation csss class, by default set to "fade"
|
||||
* @param {String} options.modalClass modal css class, by default "umb-modal"
|
||||
* @param {Bool} options.show show the modal instantly
|
||||
* @param {Object} options.scope scope to attach the modal to, by default rootScope.new()
|
||||
* @param {Bool} options.iframe load template in an iframe, only needed for serverside templates
|
||||
* @param {Int} options.width set a width on the modal, only needed for iframes
|
||||
* @param {Bool} options.inline strips the modal from any animation and wrappers, used when you want to inject a dialog into an existing container
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
open: function (options) {
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#close
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Closes a specific dialog
|
||||
* @param {Object} dialog the dialog object to close
|
||||
* @param {Object} args if specified this object will be sent to any callbacks registered on the dialogs.
|
||||
*/
|
||||
close: function (dialog, args) {
|
||||
if(dialog){
|
||||
dialog.close(args);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#closeAll
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Closes all dialogs
|
||||
* @param {Object} args if specified this object will be sent to any callbacks registered on the dialogs.
|
||||
*/
|
||||
closeAll: function(args) {
|
||||
removeAllDialogs(args);
|
||||
},
|
||||
/** Handles the closeDialogs event */
|
||||
eventsService.on("app.closeDialogs", function (evt, args) {
|
||||
removeAllDialogs(args);
|
||||
});
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#mediaPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a media picker in a modal, the callback returns an array of selected media items
|
||||
* @param {Object} options mediapicker dialog options object
|
||||
* @param {$scope} options.scope dialog scope
|
||||
* @param {Boolean} options.onlyImages Only display files that have an image file-extension
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
mediaPicker: function (options) {
|
||||
return {
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#open
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a modal rendering a given template url.
|
||||
*
|
||||
* @param {Object} options rendering options
|
||||
* @param {DomElement} options.container the DOM element to inject the modal into, by default set to body
|
||||
* @param {Function} options.callback function called when the modal is submitted
|
||||
* @param {String} options.template the url of the template
|
||||
* @param {String} options.animation animation csss class, by default set to "fade"
|
||||
* @param {String} options.modalClass modal css class, by default "umb-modal"
|
||||
* @param {Bool} options.show show the modal instantly
|
||||
* @param {Bool} options.iframe load template in an iframe, only needed for serverside templates
|
||||
* @param {Int} options.width set a width on the modal, only needed for iframes
|
||||
* @param {Bool} options.inline strips the modal from any animation and wrappers, used when you want to inject a dialog into an existing container
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
open: function (options) {
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#close
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Closes a specific dialog
|
||||
* @param {Object} dialog the dialog object to close
|
||||
* @param {Object} args if specified this object will be sent to any callbacks registered on the dialogs.
|
||||
*/
|
||||
close: function (dialog, args) {
|
||||
if (dialog) {
|
||||
dialog.close(args);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#closeAll
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Closes all dialogs
|
||||
* @param {Object} args if specified this object will be sent to any callbacks registered on the dialogs.
|
||||
*/
|
||||
closeAll: function (args) {
|
||||
removeAllDialogs(args);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#mediaPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a media picker in a modal, the callback returns an array of selected media items
|
||||
* @param {Object} options mediapicker dialog options object
|
||||
* @param {Boolean} options.onlyImages Only display files that have an image file-extension
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
mediaPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/mediaPicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#contentPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a content picker tree in a modal, the callback returns an array of selected documents
|
||||
* @param {Object} options content picker dialog options object
|
||||
* @param {$scope} options.scope dialog scope
|
||||
* @param {$scope} options.multipicker should the picker return one or multiple items
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
contentPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/contentPicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#contentPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a content picker tree in a modal, the callback returns an array of selected documents
|
||||
* @param {Object} options content picker dialog options object
|
||||
* @param {Boolean} options.multipicker should the picker return one or multiple items
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
contentPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/contentPicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#linkPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a link picker tree in a modal, the callback returns a single link
|
||||
* @param {Object} options content picker dialog options object
|
||||
* @param {$scope} options.scope dialog scope
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
linkPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/linkPicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#linkPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a link picker tree in a modal, the callback returns a single link
|
||||
* @param {Object} options content picker dialog options object
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
linkPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/linkPicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#macroPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a mcaro picker in a modal, the callback returns a object representing the macro and it's parameters
|
||||
* @param {Object} options macropicker dialog options object
|
||||
* @param {$scope} options.scope dialog scope
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
macroPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/insertmacro.html';
|
||||
options.show = true;
|
||||
options.modalClass = "span7 umb-modal";
|
||||
return openDialog(options);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#macroPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a mcaro picker in a modal, the callback returns a object representing the macro and it's parameters
|
||||
* @param {Object} options macropicker dialog options object
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
macroPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/insertmacro.html';
|
||||
options.show = true;
|
||||
options.modalClass = "span7 umb-modal";
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#memberPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a member picker in a modal, the callback returns a object representing the selected member
|
||||
* @param {Object} options member picker dialog options object
|
||||
* @param {$scope} options.scope dialog scope
|
||||
* @param {$scope} options.multiPicker should the tree pick one or multiple members before returning
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
memberPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/memberPicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#memberGroupPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a member group picker in a modal, the callback returns a object representing the selected member
|
||||
* @param {Object} options member group picker dialog options object
|
||||
* @param {$scope} options.scope dialog scope
|
||||
* @param {$scope} options.multiPicker should the tree pick one or multiple members before returning
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
memberGroupPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/memberGroupPicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#memberPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a member picker in a modal, the callback returns a object representing the selected member
|
||||
* @param {Object} options member picker dialog options object
|
||||
* @param {Boolean} options.multiPicker should the tree pick one or multiple members before returning
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
memberPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/memberPicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#iconPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a icon picker in a modal, the callback returns a object representing the selected icon
|
||||
* @param {Object} options iconpicker dialog options object
|
||||
* @param {$scope} options.scope dialog scope
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
iconPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/iconPicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#memberGroupPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a member group picker in a modal, the callback returns a object representing the selected member
|
||||
* @param {Object} options member group picker dialog options object
|
||||
* @param {Boolean} options.multiPicker should the tree pick one or multiple members before returning
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
memberGroupPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/memberGroupPicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#treePicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a tree picker in a modal, the callback returns a object representing the selected tree item
|
||||
* @param {Object} options iconpicker dialog options object
|
||||
* @param {$scope} options.scope dialog scope
|
||||
* @param {$scope} options.section tree section to display
|
||||
* @param {$scope} options.treeAlias specific tree to display
|
||||
* @param {$scope} options.multiPicker should the tree pick one or multiple items before returning
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
treePicker: function (options) {
|
||||
options.template = 'views/common/dialogs/treePicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#iconPicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a icon picker in a modal, the callback returns a object representing the selected icon
|
||||
* @param {Object} options iconpicker dialog options object
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
iconPicker: function (options) {
|
||||
options.template = 'views/common/dialogs/iconPicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#propertyDialog
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a dialog with a chosen property editor in, a value can be passed to the modal, and this value is returned in the callback
|
||||
* @param {Object} options mediapicker dialog options object
|
||||
* @param {$scope} options.scope dialog scope
|
||||
* @param {Function} options.callback callback function
|
||||
* @param {String} editor editor to use to edit a given value and return on callback
|
||||
* @param {Object} value value sent to the property editor
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
propertyDialog: function (options) {
|
||||
options.template = 'views/common/dialogs/property.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#ysodDialog
|
||||
* @methodOf umbraco.services.dialogService
|
||||
* @description
|
||||
* Opens a dialog to an embed dialog
|
||||
*/
|
||||
embedDialog: function (options) {
|
||||
options.template = 'views/common/dialogs/rteembed.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#ysodDialog
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a dialog to show a custom YSOD
|
||||
*/
|
||||
ysodDialog: function (ysodError) {
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#treePicker
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a tree picker in a modal, the callback returns a object representing the selected tree item
|
||||
* @param {Object} options iconpicker dialog options object
|
||||
* @param {String} options.section tree section to display
|
||||
* @param {String} options.treeAlias specific tree to display
|
||||
* @param {Boolean} options.multiPicker should the tree pick one or multiple items before returning
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
treePicker: function (options) {
|
||||
options.template = 'views/common/dialogs/treePicker.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
var newScope = $rootScope.$new();
|
||||
newScope.error = ysodError;
|
||||
return openDialog({
|
||||
modalClass: "umb-modal wide",
|
||||
scope: newScope,
|
||||
//callback: options.callback,
|
||||
template: 'views/common/dialogs/ysod.html',
|
||||
show: true
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#propertyDialog
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a dialog with a chosen property editor in, a value can be passed to the modal, and this value is returned in the callback
|
||||
* @param {Object} options mediapicker dialog options object
|
||||
* @param {Function} options.callback callback function
|
||||
* @param {String} editor editor to use to edit a given value and return on callback
|
||||
* @param {Object} value value sent to the property editor
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
propertyDialog: function (options) {
|
||||
options.template = 'views/common/dialogs/property.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#ysodDialog
|
||||
* @methodOf umbraco.services.dialogService
|
||||
* @description
|
||||
* Opens a dialog to an embed dialog
|
||||
*/
|
||||
embedDialog: function (options) {
|
||||
options.template = 'views/common/dialogs/rteembed.html';
|
||||
options.show = true;
|
||||
return openDialog(options);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.dialogService#ysodDialog
|
||||
* @methodOf umbraco.services.dialogService
|
||||
*
|
||||
* @description
|
||||
* Opens a dialog to show a custom YSOD
|
||||
*/
|
||||
ysodDialog: function (ysodError) {
|
||||
|
||||
var newScope = $rootScope.$new();
|
||||
newScope.error = ysodError;
|
||||
return openDialog({
|
||||
modalClass: "umb-modal wide",
|
||||
scope: newScope,
|
||||
//callback: options.callback,
|
||||
template: 'views/common/dialogs/ysod.html',
|
||||
show: true
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -28,18 +28,25 @@
|
||||
* </pre>
|
||||
*/
|
||||
angular.module('umbraco.services')
|
||||
.factory('historyService', function ($rootScope, $timeout, angularHelper) {
|
||||
.factory('historyService', function ($rootScope, $timeout, angularHelper, eventsService) {
|
||||
|
||||
var nArray = [];
|
||||
|
||||
function add(item) {
|
||||
|
||||
var any = _.where(nArray, {link: item.link});
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var listWithoutThisItem = _.reject(nArray, function(i) {
|
||||
return i.link === item.link;
|
||||
});
|
||||
|
||||
//put it at the top and reassign
|
||||
listWithoutThisItem.splice(0, 0, item);
|
||||
nArray = listWithoutThisItem;
|
||||
return nArray[0];
|
||||
|
||||
if(any.length === 0){
|
||||
nArray.splice(0,0,item);
|
||||
return nArray[0];
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -60,7 +67,9 @@ angular.module('umbraco.services')
|
||||
add: function (item) {
|
||||
var icon = item.icon || "icon-file";
|
||||
angularHelper.safeApply($rootScope, function () {
|
||||
return add({name: item.name, icon: icon, link: item.link, time: new Date() });
|
||||
var result = add({ name: item.name, icon: icon, link: item.link, time: new Date() });
|
||||
eventsService.emit("historyService.add", {added: result, all: nArray});
|
||||
return result;
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -75,7 +84,8 @@ angular.module('umbraco.services')
|
||||
*/
|
||||
remove: function (index) {
|
||||
angularHelper.safeApply($rootScope, function() {
|
||||
nArray.splice(index, 1);
|
||||
var result = nArray.splice(index, 1);
|
||||
eventsService.emit("historyService.remove", { removed: result, all: nArray });
|
||||
});
|
||||
},
|
||||
|
||||
@@ -89,21 +99,11 @@ angular.module('umbraco.services')
|
||||
*/
|
||||
removeAll: function () {
|
||||
angularHelper.safeApply($rootScope, function() {
|
||||
nArray = [];
|
||||
nArray = [];
|
||||
eventsService.emit("historyService.removeAll");
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc property
|
||||
* @name umbraco.services.historyService#current
|
||||
* @propertyOf umbraco.services.historyService
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* @returns {Array} Array of history entries for the current user, newest items first
|
||||
*/
|
||||
current: nArray,
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.historyService#getCurrent
|
||||
|
||||
@@ -400,7 +400,6 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
}
|
||||
|
||||
var dialog = self.showDialog({
|
||||
scope: args.scope,
|
||||
node: args.node,
|
||||
action: found,
|
||||
section: appState.getSectionState("currentSection")
|
||||
@@ -569,12 +568,11 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
* into #dialog div.umb-panel-body
|
||||
* the path to the dialog view is determined by:
|
||||
* "views/" + current tree + "/" + action alias + ".html"
|
||||
* The dialog controller will get passed a scope object that is created here. This scope
|
||||
* object may be injected as part of the args object, if one is not found then a new scope
|
||||
* is created. Regardless of whether a scope is created or re-used, a few properties and methods
|
||||
* will be added to it so that they can be used in any dialog controller:
|
||||
* The dialog controller will get passed a scope object that is created here with the properties:
|
||||
* scope.currentNode = the selected tree node
|
||||
* scope.currentAction = the selected menu item
|
||||
* so that the dialog controllers can use these properties
|
||||
*
|
||||
* @param {Object} args arguments passed to the function
|
||||
* @param {Scope} args.scope current scope passed to the dialog
|
||||
* @param {Object} args.action the clicked action containing `name` and `alias`
|
||||
@@ -598,8 +596,11 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
|
||||
setMode("dialog");
|
||||
|
||||
//set up the scope object and assign properties
|
||||
var dialogScope = args.scope || $rootScope.$new();
|
||||
//NOTE: Set up the scope object and assign properties, this is legacy functionality but we have to live with it now.
|
||||
// we should be passing in currentNode and currentAction using 'dialogData' for the dialog, not attaching it to a scope.
|
||||
// This scope instance will be destroyed by the dialog so it cannot be a scope that exists outside of the dialog.
|
||||
// If a scope instance has been passed in, we'll have to create a child scope of it, otherwise a new root scope.
|
||||
var dialogScope = args.scope ? args.scope.$new() : $rootScope.$new();
|
||||
dialogScope.currentNode = args.node;
|
||||
dialogScope.currentAction = args.action;
|
||||
|
||||
@@ -657,14 +658,19 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
var dialog = dialogService.open(
|
||||
{
|
||||
container: $("#dialog div.umb-modalcolumn-body"),
|
||||
//The ONLY reason we're passing in scope to the dialogService (which is legacy functionality) is
|
||||
// for backwards compatibility since many dialogs require $scope.currentNode or $scope.currentAction
|
||||
// to exist
|
||||
scope: dialogScope,
|
||||
currentNode: args.node,
|
||||
currentAction: args.action,
|
||||
inline: true,
|
||||
show: true,
|
||||
iframe: iframe,
|
||||
modalClass: "umb-dialog",
|
||||
template: templateUrl
|
||||
template: templateUrl,
|
||||
|
||||
//These will show up on the dialog controller's $scope under dialogOptions
|
||||
currentNode: args.node,
|
||||
currentAction: args.action,
|
||||
});
|
||||
|
||||
//save the currently assigned dialog so it can be removed before a new one is created
|
||||
|
||||
@@ -61,7 +61,7 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
tooltip: 'Embed',
|
||||
onclick: function () {
|
||||
dialogService.embedDialog({
|
||||
scope: $scope, callback: function (data) {
|
||||
callback: function (data) {
|
||||
editor.insertContent(data);
|
||||
}
|
||||
});
|
||||
@@ -80,7 +80,7 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
* @param {Object} editor the TinyMCE editor instance
|
||||
* @param {Object} $scope the current controller scope
|
||||
*/
|
||||
createMediaPicker: function (editor, $scope) {
|
||||
createMediaPicker: function (editor) {
|
||||
editor.addButton('umbmediapicker', {
|
||||
icon: 'custom icon-picture',
|
||||
tooltip: 'Media Picker',
|
||||
@@ -103,7 +103,7 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
currentTarget: currentTarget,
|
||||
onlyImages: true,
|
||||
showDetails: true,
|
||||
scope: $scope, callback: function (img) {
|
||||
callback: function (img) {
|
||||
|
||||
if (img) {
|
||||
|
||||
@@ -139,49 +139,6 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.tinyMceService#createLinkPicker
|
||||
* @methodOf umbraco.services.tinyMceService
|
||||
*
|
||||
* @description
|
||||
* Creates the umbrco insert link tinymce plugin
|
||||
*
|
||||
* @param {Object} editor the TinyMCE editor instance
|
||||
* @param {Object} $scope the current controller scope
|
||||
*/
|
||||
createLinkPicker: function (editor, $scope) {
|
||||
|
||||
/*
|
||||
editor.addButton('link', {
|
||||
icon: 'custom icon-link',
|
||||
tooltip: 'Link Picker',
|
||||
onclick: function () {
|
||||
dialogService.linkPicker({
|
||||
scope: $scope, callback: function (link) {
|
||||
if (link) {
|
||||
var data = {
|
||||
title: "Some description",
|
||||
href: "",
|
||||
id: '__mcenew'
|
||||
};
|
||||
|
||||
editor.execCommand("mceInsertLink", false, {
|
||||
href: "wat",
|
||||
title: "muh",
|
||||
target: null,
|
||||
"class": null
|
||||
});
|
||||
|
||||
|
||||
//editor.insertContent(editor.dom.createHTML('a', data));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});*/
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.tinyMceService#createUmbracoMacro
|
||||
@@ -496,7 +453,6 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
}
|
||||
|
||||
dialogService.macroPicker({
|
||||
scope: $scope,
|
||||
dialogData : dialogData,
|
||||
callback: function(data) {
|
||||
|
||||
|
||||
@@ -139,7 +139,8 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
|
||||
return { height: minDisplayHeight, imgCount: 1 };
|
||||
}
|
||||
else if (idealImages.length === idealImgPerRow && targetHeight < maxRowHeight) {
|
||||
//if we're already dealing with the ideal images per row and it's not quite there, we can scale up a little bit so
|
||||
|
||||
//if we're already dealing with the ideal images per row and it's not quite wide enough, we can scale up a little bit so
|
||||
// long as the targetHeight is currently less than the maxRowHeight. The scale up will be half-way between our current
|
||||
// target height and the maxRowHeight (we won't loop forever though - if there's a difference of 5 px we'll just quit)
|
||||
|
||||
@@ -152,9 +153,8 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
|
||||
}
|
||||
}
|
||||
|
||||
//Ok, we couldn't actually scale it up with the ideal row count (TBH I'm not sure that this would ever happen but we'll take it into account)
|
||||
// we'll just recurse with another image count.
|
||||
return this.getRowHeightForImages(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow + 1, margin);
|
||||
//Ok, we couldn't actually scale it up with the ideal row count we'll just recurse with a lesser image count.
|
||||
return this.getRowHeightForImages(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow - 1, margin);
|
||||
}
|
||||
else {
|
||||
//we have additional images so we'll recurse and add 1 to the idealImgPerRow until it fits
|
||||
|
||||
@@ -107,9 +107,6 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
|
||||
//this reacts to the options item in the tree
|
||||
//todo, migrate to nav service
|
||||
$scope.searchShowMenu = function (ev, args) {
|
||||
$scope.currentNode = args.node;
|
||||
args.scope = $scope;
|
||||
|
||||
//always skip default
|
||||
args.skipDefault = true;
|
||||
navigationService.showMenu(ev, args);
|
||||
|
||||
@@ -26,8 +26,10 @@ function SearchController($scope, searchService, $log, $location, navigationServ
|
||||
iterateResults(false);
|
||||
break;
|
||||
case 13:
|
||||
$location.path($scope.selectedItem.editorPath);
|
||||
navigationService.hideSearch();
|
||||
if ($scope.selectedItem) {
|
||||
$location.path($scope.selectedItem.editorPath);
|
||||
navigationService.hideSearch();
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ function ContentEditDialogController($scope) {
|
||||
$scope.model.defaultButton = null;
|
||||
$scope.model.subButtons = [];
|
||||
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
if(dialogOptions.entity){
|
||||
$scope.model.entity = dialogOptions.entity;
|
||||
$scope.loaded = true;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Dialogs.ContentPickerController",
|
||||
function ($scope, eventsService, entityResource, searchService, $log) {
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.results = [];
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
|
||||
function ($scope, eventsService, dialogService, entityResource, contentResource, mediaHelper, $log) {
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.target = {};
|
||||
|
||||
@@ -3,7 +3,7 @@ angular.module("umbraco")
|
||||
.controller("Umbraco.Dialogs.MediaPickerController",
|
||||
function ($scope, mediaResource, umbRequestHelper, entityResource, $log, mediaHelper, eventsService, treeService, $cookies) {
|
||||
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
|
||||
$scope.onlyImages = dialogOptions.onlyImages;
|
||||
$scope.showDetails = dialogOptions.showDetails;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//used for the member picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Dialogs.MemberGroupPickerController",
|
||||
function($scope, eventsService, entityResource, searchService, $log) {
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.results = [];
|
||||
$scope.dialogData = [];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//used for the member picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Dialogs.MemberPickerController",
|
||||
function($scope, eventsService, entityResource, searchService, $log) {
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.results = [];
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
|
||||
function ($scope, entityResource, eventsService, $log, searchService) {
|
||||
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.section = dialogOptions.section;
|
||||
$scope.treeAlias = dialogOptions.treeAlias;
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Dialogs.UserController", function ($scope, $location, $timeout, userService, historyService, eventsService) {
|
||||
|
||||
|
||||
$scope.user = userService.getCurrentUser();
|
||||
$scope.history = historyService.current;
|
||||
$scope.history = historyService.getCurrent();
|
||||
$scope.version = Umbraco.Sys.ServerVariables.application.version + " assembly: " + Umbraco.Sys.ServerVariables.application.assemblyVersion;
|
||||
|
||||
var evtHandlers = [];
|
||||
evtHandlers.push(eventsService.on("historyService.add", function (e, args) {
|
||||
$scope.history = args.all;
|
||||
}));
|
||||
evtHandlers.push(eventsService.on("historyService.remove", function (e, args) {
|
||||
$scope.history = args.all;
|
||||
}));
|
||||
evtHandlers.push(eventsService.on("historyService.removeAll", function (e, args) {
|
||||
$scope.history = [];
|
||||
}));
|
||||
|
||||
$scope.logout = function () {
|
||||
|
||||
@@ -12,42 +22,48 @@ angular.module("umbraco")
|
||||
var pendingChangeEvent = eventsService.on("valFormManager.pendingChanges", function (e, args) {
|
||||
//one time listener, remove the event
|
||||
pendingChangeEvent();
|
||||
$scope.hide();
|
||||
$scope.close();
|
||||
});
|
||||
|
||||
//perform the path change, if it is successful then the promise will resolve otherwise it will fail
|
||||
$location.path("/logout");
|
||||
};
|
||||
$location.path("/logout");
|
||||
};
|
||||
|
||||
$scope.gotoHistory = function (link) {
|
||||
$location.path(link);
|
||||
$scope.hide();
|
||||
};
|
||||
$scope.gotoHistory = function (link) {
|
||||
$location.path(link);
|
||||
$scope.close();
|
||||
};
|
||||
|
||||
//Manually update the remaining timeout seconds
|
||||
function updateTimeout() {
|
||||
$timeout(function () {
|
||||
if ($scope.remainingAuthSeconds > 0) {
|
||||
$scope.remainingAuthSeconds--;
|
||||
$scope.$digest();
|
||||
//recurse
|
||||
updateTimeout();
|
||||
}
|
||||
|
||||
}, 1000, false); // 1 second, do NOT execute a global digest
|
||||
}
|
||||
|
||||
//get the user
|
||||
userService.getCurrentUser().then(function (user) {
|
||||
$scope.user = user;
|
||||
if ($scope.user) {
|
||||
$scope.remainingAuthSeconds = $scope.user.remainingAuthSeconds;
|
||||
$scope.canEditProfile = _.indexOf($scope.user.allowedSections, "users") > -1;
|
||||
//set the timer
|
||||
updateTimeout();
|
||||
}
|
||||
});
|
||||
function updateTimeout() {
|
||||
$timeout(function () {
|
||||
if ($scope.remainingAuthSeconds > 0) {
|
||||
$scope.remainingAuthSeconds--;
|
||||
$scope.$digest();
|
||||
//recurse
|
||||
updateTimeout();
|
||||
}
|
||||
|
||||
}, 1000, false); // 1 second, do NOT execute a global digest
|
||||
}
|
||||
|
||||
//get the user
|
||||
userService.getCurrentUser().then(function (user) {
|
||||
$scope.user = user;
|
||||
if ($scope.user) {
|
||||
$scope.remainingAuthSeconds = $scope.user.remainingAuthSeconds;
|
||||
$scope.canEditProfile = _.indexOf($scope.user.allowedSections, "users") > -1;
|
||||
//set the timer
|
||||
updateTimeout();
|
||||
}
|
||||
});
|
||||
|
||||
//remove all event handlers
|
||||
$scope.$on('$destroy', function () {
|
||||
for (var i = 0; i < evtHandlers.length; i++) {
|
||||
evtHandlers[i]();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
@@ -34,7 +34,7 @@
|
||||
<div class="umb-pane">
|
||||
<h5><localize key="user_yourHistory" /></h5>
|
||||
<ul class="umb-tree">
|
||||
<li ng-repeat="item in history | orderBy:'time'">
|
||||
<li ng-repeat="item in history | orderBy:'time':true">
|
||||
<a ng-href="{{item.link}}" ng-click="gotoHistory(item.link)" prevent-default>
|
||||
<i class="{{item.icon}}"></i> {{item.name}}</a>
|
||||
</li>
|
||||
|
||||
@@ -2,7 +2,7 @@ angular.module("umbraco")
|
||||
.controller("Umbraco.Editors.Content.CopyController",
|
||||
function ($scope, eventsService, contentResource, navigationService, appState, treeService) {
|
||||
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
|
||||
$scope.relateToOriginal = false;
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Content.MoveController",
|
||||
function ($scope, eventsService, contentResource, navigationService, appState, treeService) {
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
var node = dialogOptions.currentNode;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<ng-form name="copyForm">
|
||||
<p class="abstract" ng-hide="success">
|
||||
Choose where to copy <strong>{{currentNode.name}}</strong> to in the tree struture below
|
||||
Choose where to copy <strong>{{currentNode.name}}</strong> to in the tree structure below
|
||||
</p>
|
||||
|
||||
<div class="alert alert-error" ng-show="error">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="umb-pane">
|
||||
|
||||
<p class="abstract" ng-hide="success">
|
||||
Choose where to move <strong>{{currentNode.name}}</strong> to in the tree struture below
|
||||
Choose where to move <strong>{{currentNode.name}}</strong> to in the tree structure below
|
||||
</p>
|
||||
|
||||
<div class="alert alert-error" ng-show="error">
|
||||
|
||||
@@ -22,7 +22,7 @@ function startupLatestEditsController($scope) {
|
||||
angular.module("umbraco").controller("Umbraco.Dashboard.StartupLatestEditsController", startupLatestEditsController);
|
||||
|
||||
function MediaFolderBrowserDashboardController($rootScope, $scope, assetsService, $routeParams, $timeout, $element, $location, umbRequestHelper,navigationService, mediaResource, $cookies) {
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
|
||||
$scope.filesUploading = [];
|
||||
$scope.options = {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Media.MoveController",
|
||||
function ($scope, eventsService, mediaResource, appState, treeService, navigationService) {
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
var node = dialogOptions.currentNode;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="umb-pane">
|
||||
|
||||
<p class="abstract" ng-hide="success">
|
||||
Choose where to move <strong>{{currentNode.name}}</strong> to in the tree struture below
|
||||
Choose where to move <strong>{{currentNode.name}}</strong> to in the tree structure below
|
||||
</p>
|
||||
|
||||
<div class="alert alert-error" ng-show="error">
|
||||
|
||||
@@ -29,7 +29,6 @@ angular.module('umbraco')
|
||||
var d = dialogService.treePicker({
|
||||
section: $scope.cfg.type,
|
||||
treeAlias: $scope.cfg.type,
|
||||
scope: $scope,
|
||||
multiPicker: $scope.cfg.multiPicker,
|
||||
callback: populate});
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user