Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7393d9c372 | |||
| 79c4d7797c | |||
| 01a895bbf7 | |||
| 4fa523db43 | |||
| 186460ac08 | |||
| 686f6752f3 | |||
| 23ccdeb2cf | |||
| 6148ce4e52 | |||
| 06850ed25c | |||
| 0320a56cb5 | |||
| cd27bb210f | |||
| 67f680a675 | |||
| 47c3e3a79f | |||
| f3bfc1ffb2 | |||
| 89cd655df2 | |||
| 14c4c4815d | |||
| bfb69a34ef | |||
| d52420183e | |||
| 2aaca865e7 | |||
| 2ec8281163 | |||
| 2ac5e61e44 | |||
| c47a08b553 | |||
| de9241bcf5 | |||
| 7c03fe3c1f | |||
| 82eb241119 | |||
| 1073e6257c | |||
| 59bf24c461 | |||
| 2748c3635d | |||
| d31e71a838 | |||
| 2252db0d55 | |||
| df896af476 | |||
| 4b605b2580 | |||
| 80d7f1b2c9 | |||
| 5ada85df29 | |||
| 5b7ae7150f | |||
| 5bf29a907a | |||
| 2a9bcf0e98 | |||
| 3c0565e516 | |||
| fa4acb255b | |||
| a018ed9e52 | |||
| fad33a97b2 | |||
| ac586c5207 | |||
| 8033931e31 | |||
| 8e29810598 | |||
| be96e2cf08 | |||
| 534ee67ad2 | |||
| 571a3bc257 | |||
| e7a30d0a5d | |||
| a55323176f | |||
| 1b83e0a87d | |||
| ca15f340b0 | |||
| 23b8e1cce8 | |||
| cf53ba363d | |||
| 2f309a2fd6 | |||
| 9f45d41a4a | |||
| 1994194656 | |||
| 36559b8761 | |||
| 8fe7c5599a | |||
| 4dd325cec9 | |||
| d558646d75 | |||
| afac4bb918 | |||
| 0869bf27c7 | |||
| 383a8617ce | |||
| 3865f4fb50 | |||
| 3e74bbfb45 | |||
| 966b07ba1c | |||
| d4311fe4ab | |||
| eab597a2a8 | |||
| 8d12170def | |||
| d2655a9f2f | |||
| c4c2082fa9 | |||
| 40d4a8fe6a | |||
| 2898203cb9 | |||
| 5ebdfc7b1c | |||
| 31d7e58191 | |||
| ad4416f663 | |||
| b55d2a8a41 | |||
| 17a4799b97 | |||
| 4df838c20c | |||
| 4e44871671 | |||
| 1dd2c1cb91 | |||
| 5c6a9480a6 | |||
| c1be8e3f00 | |||
| d8dbda8e94 | |||
| a0ab7ace07 | |||
| 7c27189e2e | |||
| 994c6eed50 | |||
| cff5046a9e | |||
| 9f6da2ca4b | |||
| 99cabe564d | |||
| 580de6befe | |||
| 0f969ecdd4 |
@@ -8,7 +8,7 @@
|
||||
</configSections>
|
||||
|
||||
<system.web.webPages.razor>
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(factoryType)" xdt:Transform="SetAttributes(factoryType)" />
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(factoryType)" xdt:Transform="SetAttributes(factoryType)" />
|
||||
<pages pageBaseType="System.Web.Mvc.WebViewPage">
|
||||
<namespaces>
|
||||
<add namespace="Umbraco.Web.PublishedContentModels" xdt:Transform="InsertIfMissing" />
|
||||
@@ -18,13 +18,13 @@
|
||||
|
||||
<system.web>
|
||||
<pages
|
||||
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(pageParserFilterType,pageBaseType,userControlBaseType)"
|
||||
xdt:Transform="SetAttributes(pageParserFilterType,pageBaseType,userControlBaseType)">
|
||||
<controls>
|
||||
<add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" xdt:Locator="Match(namespace)" xdt:Transform="SetAttributes(assembly)" />
|
||||
<add assembly="System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" xdt:Locator="Match(namespace)" xdt:Transform="SetAttributes(assembly)" />
|
||||
</controls>
|
||||
</pages>
|
||||
</system.web>
|
||||
|
||||
@@ -324,7 +324,6 @@
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='HtmlAgilityPack')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='AutoMapper')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Newtonsoft.Json')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Mvc')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.WebPages.Razor')" xdt:Transform="Remove" />
|
||||
@@ -337,6 +336,9 @@
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.CodeAnalysis.CSharp')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='log4net')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Data.SqlServerCe')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.CodeDom.Providers.DotNetCompilerPlatform')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.AspNet.SignalR.Core')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Http.WebHost')" xdt:Transform="Remove" />
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
@@ -344,7 +346,7 @@
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.4.9.5" newVersion="1.4.9.5" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.8.8.0" newVersion="1.8.8.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
|
||||
@@ -356,11 +358,11 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" />
|
||||
@@ -368,27 +370,27 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral"/>
|
||||
@@ -398,6 +400,18 @@
|
||||
<assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845DCD8080CC91" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.1.0" newVersion="2.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.AspNet.SignalR.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.4.1.0" newVersion="2.4.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Http.WebHost" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.15.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.15.0")]
|
||||
[assembly: AssemblyFileVersion("7.15.1")]
|
||||
[assembly: AssemblyInformationalVersion("7.15.1")]
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.15.0");
|
||||
private static readonly Version Version = new Version("7.15.1");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the identifiers for Umbraco data types as constants for easy centralized access/management.
|
||||
/// </summary>
|
||||
internal static class DataTypes
|
||||
{
|
||||
|
||||
public static class ReservedPreValueKeys
|
||||
{
|
||||
public const string IgnoreUserStartNodes = "ignoreUserStartNodes";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Content Picker as string
|
||||
/// </summary>
|
||||
public const string ContentPicker = "FD1E0DA5-5606-4862-B679-5D0CF3A52A59";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Content Picker
|
||||
/// </summary>
|
||||
public static readonly Guid ContentPickerGuid = new Guid(ContentPicker);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Member Picker as string
|
||||
/// </summary>
|
||||
public const string MemberPicker = "1EA2E01F-EBD8-4CE1-8D71-6B1149E63548";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Member Picker
|
||||
/// </summary>
|
||||
public static readonly Guid MemberPickerGuid = new Guid(MemberPicker);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Media Picker as string
|
||||
/// </summary>
|
||||
public const string MediaPicker = "135D60E0-64D9-49ED-AB08-893C9BA44AE5";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Media Picker
|
||||
/// </summary>
|
||||
public static readonly Guid MediaPickerGuid = new Guid(MediaPicker);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Multiple Media Picker as string
|
||||
/// </summary>
|
||||
public const string MultipleMediaPicker = "9DBBCBBB-2327-434A-B355-AF1B84E5010A";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Multiple Media Picker
|
||||
/// </summary>
|
||||
public static readonly Guid MultipleMediaPickerGuid = new Guid(MultipleMediaPicker);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Related Links as string
|
||||
/// </summary>
|
||||
public const string RelatedLinks = "B4E3535A-1753-47E2-8568-602CF8CFEE6F";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Related Links
|
||||
/// </summary>
|
||||
public static readonly Guid RelatedLinksGuid = new Guid(RelatedLinks);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Member as string
|
||||
/// </summary>
|
||||
public const string Member = "d59be02f-1df9-4228-aa1e-01917d806cda";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Member
|
||||
/// </summary>
|
||||
public static readonly Guid MemberGuid = new Guid(Member);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Image Cropper as string
|
||||
/// </summary>
|
||||
public const string ImageCropper = "1df9f033-e6d4-451f-b8d2-e0cbc50a836f";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Image Cropper
|
||||
/// </summary>
|
||||
public static readonly Guid ImageCropperGuid = new Guid(ImageCropper);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Tags as string
|
||||
/// </summary>
|
||||
public const string Tags = "b6b73142-b9c1-4bf8-a16d-e1c23320b549";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Tags
|
||||
/// </summary>
|
||||
public static readonly Guid TagsGuid = new Guid(Tags);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Content as string
|
||||
/// </summary>
|
||||
public const string ListViewContent = "C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Content
|
||||
/// </summary>
|
||||
public static readonly Guid ListViewContentGuid = new Guid(ListViewContent);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Media as string
|
||||
/// </summary>
|
||||
public const string ListViewMedia = "3A0156C4-3B8C-4803-BDC1-6871FAA83FFF";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Media
|
||||
/// </summary>
|
||||
public static readonly Guid ListViewMediaGuid = new Guid(ListViewMedia);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Members as string
|
||||
/// </summary>
|
||||
public const string ListViewMembers = "AA2C52A0-CE87-4E65-A47C-7DF09358585D";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Members
|
||||
/// </summary>
|
||||
public static readonly Guid ListViewMembersGuid = new Guid(ListViewMembers);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Date Picker with time as string
|
||||
/// </summary>
|
||||
public const string DatePickerWithTime = "e4d66c0f-b935-4200-81f0-025f7256b89a";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Date Picker with time
|
||||
/// </summary>
|
||||
public static readonly Guid DatePickerWithTimeGuid = new Guid(DatePickerWithTime);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Approved Color as string
|
||||
/// </summary>
|
||||
public const string ApprovedColor = "0225af17-b302-49cb-9176-b9f35cab9c17";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Approved Color
|
||||
/// </summary>
|
||||
public static readonly Guid ApprovedColorGuid = new Guid(ApprovedColor);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown multiple as string
|
||||
/// </summary>
|
||||
public const string DropdownMultiple = "f38f0ac7-1d27-439c-9f3f-089cd8825a53";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown multiple
|
||||
/// </summary>
|
||||
public static readonly Guid DropdownMultipleGuid = new Guid(DropdownMultiple);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Radiobox as string
|
||||
/// </summary>
|
||||
public const string Radiobox = "bb5f57c9-ce2b-4bb9-b697-4caca783a805";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Radiobox
|
||||
/// </summary>
|
||||
public static readonly Guid RadioboxGuid = new Guid(Radiobox);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Date Picker as string
|
||||
/// </summary>
|
||||
public const string DatePicker = "5046194e-4237-453c-a547-15db3a07c4e1";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Date Picker
|
||||
/// </summary>
|
||||
public static readonly Guid DatePickerGuid = new Guid(DatePicker);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown as string
|
||||
/// </summary>
|
||||
public const string Dropdown = "0b6a45e7-44ba-430d-9da5-4e46060b9e03";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown
|
||||
/// </summary>
|
||||
public static readonly Guid DropdownGuid = new Guid(Dropdown);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Checkbox list as string
|
||||
/// </summary>
|
||||
public const string CheckboxList = "fbaf13a8-4036-41f2-93a3-974f678c312a";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Checkbox list
|
||||
/// </summary>
|
||||
public static readonly Guid CheckboxListGuid = new Guid(CheckboxList);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Checkbox as string
|
||||
/// </summary>
|
||||
public const string Checkbox = "92897bc6-a5f3-4ffe-ae27-f2e7e33dda49";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Checkbox
|
||||
/// </summary>
|
||||
public static readonly Guid CheckboxGuid = new Guid(Checkbox);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Numeric as string
|
||||
/// </summary>
|
||||
public const string Numeric = "2e6d3631-066e-44b8-aec4-96f09099b2b5";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown
|
||||
/// </summary>
|
||||
public static readonly Guid NumericGuid = new Guid(Numeric);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Richtext editor as string
|
||||
/// </summary>
|
||||
public const string RichtextEditor = "ca90c950-0aff-4e72-b976-a30b1ac57dad";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Richtext editor
|
||||
/// </summary>
|
||||
public static readonly Guid RichtextEditorGuid = new Guid(RichtextEditor);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Textstring as string
|
||||
/// </summary>
|
||||
public const string Textstring = "0cc0eba1-9960-42c9-bf9b-60e150b429ae";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Textstring
|
||||
/// </summary>
|
||||
public static readonly Guid TextstringGuid = new Guid(Textstring);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Textarea as string
|
||||
/// </summary>
|
||||
public const string Textarea = "c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown
|
||||
/// </summary>
|
||||
public static readonly Guid TextareaGuid = new Guid(Textarea);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Upload as string
|
||||
/// </summary>
|
||||
public const string Upload = "84c6b441-31df-4ffe-b67e-67d5bc3ae65a";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Upload
|
||||
/// </summary>
|
||||
public static readonly Guid UploadGuid = new Guid(Upload);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label as string
|
||||
/// </summary>
|
||||
public const string Label = "f0bc4bfb-b499-40d6-ba86-058885a5178c";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label
|
||||
/// </summary>
|
||||
public static readonly Guid LabelGuid = new Guid(Label);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,219 +1,219 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Definition of a DataType/PropertyEditor
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The definition exists as a database reference between an actual DataType/PropertyEditor
|
||||
/// (identified by its control id), its prevalues (configuration) and the named DataType in the backoffice UI.
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class DataTypeDefinition : Entity, IDataTypeDefinition
|
||||
{
|
||||
private int _parentId;
|
||||
private string _name;
|
||||
private int _sortOrder;
|
||||
private int _level;
|
||||
private string _path;
|
||||
private int _creatorId;
|
||||
private bool _trashed;
|
||||
private string _propertyEditorAlias;
|
||||
private DataTypeDatabaseType _databaseType;
|
||||
|
||||
[Obsolete("Property editor's are defined by a string alias from version 7 onwards, use the alternative contructor that specifies an alias")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public DataTypeDefinition(int parentId, Guid controlId)
|
||||
{
|
||||
_parentId = parentId;
|
||||
|
||||
_propertyEditorAlias = LegacyPropertyEditorIdToAliasConverter.GetAliasFromLegacyId(controlId, false);
|
||||
if (_propertyEditorAlias == null)
|
||||
{
|
||||
//convert to Label!
|
||||
LogHelper.Warn<DataTypeDefinition>("Could not find a GUID -> Alias mapping for the legacy property editor with id " + controlId + ". The DataType has been converted to a Label.");
|
||||
_propertyEditorAlias = Constants.PropertyEditors.NoEditAlias;
|
||||
}
|
||||
|
||||
_additionalData = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public DataTypeDefinition(int parentId, string propertyEditorAlias)
|
||||
{
|
||||
_parentId = parentId;
|
||||
_propertyEditorAlias = propertyEditorAlias;
|
||||
|
||||
_additionalData = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public DataTypeDefinition(string propertyEditorAlias)
|
||||
{
|
||||
_parentId = -1;
|
||||
_propertyEditorAlias = propertyEditorAlias;
|
||||
|
||||
_additionalData = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
|
||||
|
||||
private class PropertySelectors
|
||||
{
|
||||
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.Name);
|
||||
public readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.ParentId);
|
||||
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.SortOrder);
|
||||
public readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.Level);
|
||||
public readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.Path);
|
||||
public readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.CreatorId);
|
||||
public readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, bool>(x => x.Trashed);
|
||||
public readonly PropertyInfo PropertyEditorAliasSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.PropertyEditorAlias);
|
||||
public readonly PropertyInfo DatabaseTypeSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, DataTypeDatabaseType>(x => x.DatabaseType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Id of the Parent entity
|
||||
/// </summary>
|
||||
/// <remarks>Might not be necessary if handled as a relation?</remarks>
|
||||
[DataMember]
|
||||
public int ParentId
|
||||
{
|
||||
get { return _parentId; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _parentId, Ps.Value.ParentIdSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the current entity
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sort order of the content entity
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public int SortOrder
|
||||
{
|
||||
get { return _sortOrder; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _sortOrder, Ps.Value.SortOrderSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level of the content entity
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public int Level
|
||||
{
|
||||
get { return _level; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _level, Ps.Value.LevelSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string Path //Setting this value should be handled by the class not the user
|
||||
{
|
||||
get { return _path; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _path, Ps.Value.PathSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Id of the user who created this entity
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public int CreatorId
|
||||
{
|
||||
get { return _creatorId; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _creatorId, Ps.Value.UserIdSelector); }
|
||||
}
|
||||
|
||||
//NOTE: SD: Why do we have this ??
|
||||
|
||||
/// <summary>
|
||||
/// Boolean indicating whether this entity is Trashed or not.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public bool Trashed
|
||||
{
|
||||
get { return _trashed; }
|
||||
internal set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(value, ref _trashed, Ps.Value.TrashedSelector);
|
||||
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
|
||||
_additionalData["Trashed"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public string PropertyEditorAlias
|
||||
{
|
||||
get { return _propertyEditorAlias; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(value, ref _propertyEditorAlias, Ps.Value.PropertyEditorAliasSelector);
|
||||
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
|
||||
_additionalData["DatabaseType"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Id of the DataType control
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
[Obsolete("Property editor's are defined by a string alias from version 7 onwards, use the PropertyEditorAlias property instead. This method will return a generated GUID for any property editor alias not explicitly mapped to a legacy ID")]
|
||||
public Guid ControlId
|
||||
{
|
||||
get
|
||||
{
|
||||
return LegacyPropertyEditorIdToAliasConverter.GetLegacyIdFromAlias(
|
||||
_propertyEditorAlias, LegacyPropertyEditorIdToAliasConverter.NotFoundLegacyIdResponseBehavior.GenerateId).Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
var alias = LegacyPropertyEditorIdToAliasConverter.GetAliasFromLegacyId(value, true);
|
||||
PropertyEditorAlias = alias;
|
||||
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
|
||||
_additionalData["ControlId"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the DatabaseType for which the DataType's value is saved as
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public DataTypeDatabaseType DatabaseType
|
||||
{
|
||||
get { return _databaseType; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(value, ref _databaseType, Ps.Value.DatabaseTypeSelector);
|
||||
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
|
||||
_additionalData["DatabaseType"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly IDictionary<string, object> _additionalData;
|
||||
/// <summary>
|
||||
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IDictionary<string, object> IUmbracoEntity.AdditionalData
|
||||
{
|
||||
get { return _additionalData; }
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Definition of a DataType/PropertyEditor
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The definition exists as a database reference between an actual DataType/PropertyEditor
|
||||
/// (identified by its control id), its prevalues (configuration) and the named DataType in the backoffice UI.
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class DataTypeDefinition : Entity, IDataTypeDefinition
|
||||
{
|
||||
private int _parentId;
|
||||
private string _name;
|
||||
private int _sortOrder;
|
||||
private int _level;
|
||||
private string _path;
|
||||
private int _creatorId;
|
||||
private bool _trashed;
|
||||
private string _propertyEditorAlias;
|
||||
private DataTypeDatabaseType _databaseType;
|
||||
|
||||
[Obsolete("Property editor's are defined by a string alias from version 7 onwards, use the alternative contructor that specifies an alias")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public DataTypeDefinition(int parentId, Guid controlId)
|
||||
{
|
||||
_parentId = parentId;
|
||||
|
||||
_propertyEditorAlias = LegacyPropertyEditorIdToAliasConverter.GetAliasFromLegacyId(controlId, false);
|
||||
if (_propertyEditorAlias == null)
|
||||
{
|
||||
//convert to Label!
|
||||
LogHelper.Warn<DataTypeDefinition>("Could not find a GUID -> Alias mapping for the legacy property editor with id " + controlId + ". The DataType has been converted to a Label.");
|
||||
_propertyEditorAlias = Constants.PropertyEditors.NoEditAlias;
|
||||
}
|
||||
|
||||
_additionalData = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public DataTypeDefinition(int parentId, string propertyEditorAlias)
|
||||
{
|
||||
_parentId = parentId;
|
||||
_propertyEditorAlias = propertyEditorAlias;
|
||||
|
||||
_additionalData = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public DataTypeDefinition(string propertyEditorAlias)
|
||||
{
|
||||
_parentId = -1;
|
||||
_propertyEditorAlias = propertyEditorAlias;
|
||||
|
||||
_additionalData = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
|
||||
|
||||
private class PropertySelectors
|
||||
{
|
||||
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.Name);
|
||||
public readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.ParentId);
|
||||
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.SortOrder);
|
||||
public readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.Level);
|
||||
public readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.Path);
|
||||
public readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.CreatorId);
|
||||
public readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, bool>(x => x.Trashed);
|
||||
public readonly PropertyInfo PropertyEditorAliasSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.PropertyEditorAlias);
|
||||
public readonly PropertyInfo DatabaseTypeSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, DataTypeDatabaseType>(x => x.DatabaseType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Id of the Parent entity
|
||||
/// </summary>
|
||||
/// <remarks>Might not be necessary if handled as a relation?</remarks>
|
||||
[DataMember]
|
||||
public int ParentId
|
||||
{
|
||||
get { return _parentId; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _parentId, Ps.Value.ParentIdSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the current entity
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sort order of the content entity
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public int SortOrder
|
||||
{
|
||||
get { return _sortOrder; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _sortOrder, Ps.Value.SortOrderSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level of the content entity
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public int Level
|
||||
{
|
||||
get { return _level; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _level, Ps.Value.LevelSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string Path //Setting this value should be handled by the class not the user
|
||||
{
|
||||
get { return _path; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _path, Ps.Value.PathSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Id of the user who created this entity
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public int CreatorId
|
||||
{
|
||||
get { return _creatorId; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _creatorId, Ps.Value.UserIdSelector); }
|
||||
}
|
||||
|
||||
//NOTE: SD: Why do we have this ??
|
||||
|
||||
/// <summary>
|
||||
/// Boolean indicating whether this entity is Trashed or not.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public bool Trashed
|
||||
{
|
||||
get { return _trashed; }
|
||||
internal set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(value, ref _trashed, Ps.Value.TrashedSelector);
|
||||
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
|
||||
_additionalData["Trashed"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public string PropertyEditorAlias
|
||||
{
|
||||
get { return _propertyEditorAlias; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(value, ref _propertyEditorAlias, Ps.Value.PropertyEditorAliasSelector);
|
||||
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
|
||||
_additionalData["DatabaseType"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Id of the DataType control
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
[Obsolete("Property editor's are defined by a string alias from version 7 onwards, use the PropertyEditorAlias property instead. This method will return a generated GUID for any property editor alias not explicitly mapped to a legacy ID")]
|
||||
public Guid ControlId
|
||||
{
|
||||
get
|
||||
{
|
||||
return LegacyPropertyEditorIdToAliasConverter.GetLegacyIdFromAlias(
|
||||
_propertyEditorAlias, LegacyPropertyEditorIdToAliasConverter.NotFoundLegacyIdResponseBehavior.GenerateId).Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
var alias = LegacyPropertyEditorIdToAliasConverter.GetAliasFromLegacyId(value, true);
|
||||
PropertyEditorAlias = alias;
|
||||
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
|
||||
_additionalData["ControlId"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the DatabaseType for which the DataType's value is saved as
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public DataTypeDatabaseType DatabaseType
|
||||
{
|
||||
get { return _databaseType; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(value, ref _databaseType, Ps.Value.DatabaseTypeSelector);
|
||||
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
|
||||
_additionalData["DatabaseType"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly IDictionary<string, object> _additionalData;
|
||||
/// <summary>
|
||||
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IDictionary<string, object> IUmbracoEntity.AdditionalData
|
||||
{
|
||||
get { return _additionalData; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
internal static class DataTypeExtensions
|
||||
{
|
||||
private static readonly ISet<Guid> IdsOfBuildInDataTypes = new HashSet<Guid>()
|
||||
{
|
||||
Constants.DataTypes.ContentPickerGuid,
|
||||
Constants.DataTypes.MemberPickerGuid,
|
||||
Constants.DataTypes.MediaPickerGuid,
|
||||
Constants.DataTypes.MultipleMediaPickerGuid,
|
||||
Constants.DataTypes.RelatedLinksGuid,
|
||||
Constants.DataTypes.MemberGuid,
|
||||
Constants.DataTypes.ImageCropperGuid,
|
||||
Constants.DataTypes.TagsGuid,
|
||||
Constants.DataTypes.ListViewContentGuid,
|
||||
Constants.DataTypes.ListViewMediaGuid,
|
||||
Constants.DataTypes.ListViewMembersGuid,
|
||||
Constants.DataTypes.DatePickerWithTimeGuid,
|
||||
Constants.DataTypes.ApprovedColorGuid,
|
||||
Constants.DataTypes.DropdownMultipleGuid,
|
||||
Constants.DataTypes.RadioboxGuid,
|
||||
Constants.DataTypes.DatePickerGuid,
|
||||
Constants.DataTypes.DropdownGuid,
|
||||
Constants.DataTypes.CheckboxListGuid,
|
||||
Constants.DataTypes.CheckboxGuid,
|
||||
Constants.DataTypes.NumericGuid,
|
||||
Constants.DataTypes.RichtextEditorGuid,
|
||||
Constants.DataTypes.TextstringGuid,
|
||||
Constants.DataTypes.TextareaGuid,
|
||||
Constants.DataTypes.UploadGuid,
|
||||
Constants.DataTypes.LabelGuid,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this date type is build-in/default.
|
||||
/// </summary>
|
||||
/// <param name="dataType">The data type definition.</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsBuildInDataType(this IDataTypeDefinition dataType)
|
||||
{
|
||||
return IsBuildInDataType(dataType.Key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this date type is build-in/default.
|
||||
/// </summary>
|
||||
public static bool IsBuildInDataType(Guid key)
|
||||
{
|
||||
return IdsOfBuildInDataTypes.Contains(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,24 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public interface IDataTypeDefinition : IUmbracoEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The Property editor alias assigned to the data type
|
||||
/// </summary>
|
||||
string PropertyEditorAlias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id of the DataType control
|
||||
/// </summary>
|
||||
[Obsolete("Property editor's are defined by a string alias from version 7 onwards, use the PropertyEditorAlias property instead")]
|
||||
Guid ControlId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the DatabaseType for which the DataType's value is saved as
|
||||
/// </summary>
|
||||
DataTypeDatabaseType DatabaseType { get; set; }
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public interface IDataTypeDefinition : IUmbracoEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The Property editor alias assigned to the data type
|
||||
/// </summary>
|
||||
string PropertyEditorAlias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id of the DataType control
|
||||
/// </summary>
|
||||
[Obsolete("Property editor's are defined by a string alias from version 7 onwards, use the PropertyEditorAlias property instead")]
|
||||
Guid ControlId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the DatabaseType for which the DataType's value is saved as
|
||||
/// </summary>
|
||||
DataTypeDatabaseType DatabaseType { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,42 +225,5 @@ namespace Umbraco.Core.Models
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A struction that can be contained in the additional data of an UmbracoEntity representing
|
||||
/// a user defined property
|
||||
/// </summary>
|
||||
public class EntityProperty : IDeepCloneable
|
||||
{
|
||||
public string PropertyEditorAlias { get; set; }
|
||||
public object Value { get; set; }
|
||||
public object DeepClone()
|
||||
{
|
||||
//Memberwise clone on Entity 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 = MemberwiseClone();
|
||||
return clone;
|
||||
}
|
||||
|
||||
protected bool Equals(EntityProperty other)
|
||||
{
|
||||
return PropertyEditorAlias.Equals(other.PropertyEditorAlias) && string.Equals(Value, other.Value);
|
||||
}
|
||||
|
||||
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((EntityProperty) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (PropertyEditorAlias.GetHashCode() * 397) ^ (Value != null ? Value.GetHashCode() : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,19 +193,6 @@ namespace Umbraco.Core.Models
|
||||
|
||||
// check for a start node in the path
|
||||
return startNodeIds.Any(x => formattedPath.Contains(string.Concat(",", x, ",")));
|
||||
}
|
||||
|
||||
internal static bool IsInBranchOfStartNode(this IUser user, IUmbracoEntity entity, IEntityService entityService, int recycleBinId, out bool hasPathAccess)
|
||||
{
|
||||
switch (recycleBinId)
|
||||
{
|
||||
case Constants.System.RecycleBinMedia:
|
||||
return IsInBranchOfStartNode(entity.Path, user.CalculateMediaStartNodeIds(entityService), user.GetMediaStartNodePaths(entityService), out hasPathAccess);
|
||||
case Constants.System.RecycleBinContent:
|
||||
return IsInBranchOfStartNode(entity.Path, user.CalculateContentStartNodeIds(entityService), user.GetContentStartNodePaths(entityService), out hasPathAccess);
|
||||
default:
|
||||
throw new NotSupportedException("Path access is only determined on content or media");
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsInBranchOfStartNode(string path, int[] startNodeIds, string[] startNodePaths, out bool hasPathAccess)
|
||||
|
||||
@@ -1,98 +1,98 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
internal class DataTypeDefinitionFactory
|
||||
{
|
||||
private readonly Guid _nodeObjectTypeId;
|
||||
private int _primaryKey;
|
||||
|
||||
public DataTypeDefinitionFactory(Guid nodeObjectTypeId)
|
||||
{
|
||||
_nodeObjectTypeId = nodeObjectTypeId;
|
||||
}
|
||||
|
||||
#region Implementation of IEntityFactory<DataTypeDefinition,DataTypeDto>
|
||||
|
||||
public IDataTypeDefinition BuildEntity(DataTypeDto dto)
|
||||
{
|
||||
var dataTypeDefinition = new DataTypeDefinition(dto.PropertyEditorAlias);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
dataTypeDefinition.DisableChangeTracking();
|
||||
|
||||
dataTypeDefinition.CreateDate = dto.NodeDto.CreateDate;
|
||||
dataTypeDefinition.DatabaseType = dto.DbType.EnumParse<DataTypeDatabaseType>(true);
|
||||
dataTypeDefinition.Id = dto.DataTypeId;
|
||||
dataTypeDefinition.Key = dto.NodeDto.UniqueId;
|
||||
dataTypeDefinition.Level = dto.NodeDto.Level;
|
||||
dataTypeDefinition.UpdateDate = dto.NodeDto.CreateDate;
|
||||
dataTypeDefinition.Name = dto.NodeDto.Text;
|
||||
dataTypeDefinition.ParentId = dto.NodeDto.ParentId;
|
||||
dataTypeDefinition.Path = dto.NodeDto.Path;
|
||||
dataTypeDefinition.SortOrder = dto.NodeDto.SortOrder;
|
||||
dataTypeDefinition.Trashed = dto.NodeDto.Trashed;
|
||||
dataTypeDefinition.CreatorId = dto.NodeDto.UserId.Value;
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
dataTypeDefinition.ResetDirtyProperties(false);
|
||||
return dataTypeDefinition;
|
||||
}
|
||||
finally
|
||||
{
|
||||
dataTypeDefinition.EnableChangeTracking();
|
||||
}
|
||||
}
|
||||
|
||||
public DataTypeDto BuildDto(IDataTypeDefinition entity)
|
||||
{
|
||||
var dataTypeDto = new DataTypeDto
|
||||
{
|
||||
PropertyEditorAlias = entity.PropertyEditorAlias,
|
||||
DataTypeId = entity.Id,
|
||||
DbType = entity.DatabaseType.ToString(),
|
||||
NodeDto = BuildNodeDto(entity)
|
||||
};
|
||||
|
||||
if (_primaryKey > 0)
|
||||
{
|
||||
dataTypeDto.PrimaryKey = _primaryKey;
|
||||
}
|
||||
|
||||
return dataTypeDto;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void SetPrimaryKey(int primaryKey)
|
||||
{
|
||||
_primaryKey = primaryKey;
|
||||
}
|
||||
|
||||
private NodeDto BuildNodeDto(IDataTypeDefinition entity)
|
||||
{
|
||||
var nodeDto = new NodeDto
|
||||
{
|
||||
CreateDate = entity.CreateDate,
|
||||
NodeId = entity.Id,
|
||||
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
|
||||
NodeObjectType = _nodeObjectTypeId,
|
||||
ParentId = entity.ParentId,
|
||||
Path = entity.Path,
|
||||
SortOrder = entity.SortOrder,
|
||||
Text = entity.Name,
|
||||
Trashed = entity.Trashed,
|
||||
UniqueId = entity.Key,
|
||||
UserId = entity.CreatorId
|
||||
};
|
||||
|
||||
return nodeDto;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
internal class DataTypeDefinitionFactory
|
||||
{
|
||||
private readonly Guid _nodeObjectTypeId;
|
||||
private int _primaryKey;
|
||||
|
||||
public DataTypeDefinitionFactory(Guid nodeObjectTypeId)
|
||||
{
|
||||
_nodeObjectTypeId = nodeObjectTypeId;
|
||||
}
|
||||
|
||||
#region Implementation of IEntityFactory<DataTypeDefinition,DataTypeDto>
|
||||
|
||||
public IDataTypeDefinition BuildEntity(DataTypeDto dto)
|
||||
{
|
||||
var dataTypeDefinition = new DataTypeDefinition(dto.PropertyEditorAlias);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
dataTypeDefinition.DisableChangeTracking();
|
||||
|
||||
dataTypeDefinition.CreateDate = dto.NodeDto.CreateDate;
|
||||
dataTypeDefinition.DatabaseType = dto.DbType.EnumParse<DataTypeDatabaseType>(true);
|
||||
dataTypeDefinition.Id = dto.DataTypeId;
|
||||
dataTypeDefinition.Key = dto.NodeDto.UniqueId;
|
||||
dataTypeDefinition.Level = dto.NodeDto.Level;
|
||||
dataTypeDefinition.UpdateDate = dto.NodeDto.CreateDate;
|
||||
dataTypeDefinition.Name = dto.NodeDto.Text;
|
||||
dataTypeDefinition.ParentId = dto.NodeDto.ParentId;
|
||||
dataTypeDefinition.Path = dto.NodeDto.Path;
|
||||
dataTypeDefinition.SortOrder = dto.NodeDto.SortOrder;
|
||||
dataTypeDefinition.Trashed = dto.NodeDto.Trashed;
|
||||
dataTypeDefinition.CreatorId = dto.NodeDto.UserId.Value;
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
dataTypeDefinition.ResetDirtyProperties(false);
|
||||
return dataTypeDefinition;
|
||||
}
|
||||
finally
|
||||
{
|
||||
dataTypeDefinition.EnableChangeTracking();
|
||||
}
|
||||
}
|
||||
|
||||
public DataTypeDto BuildDto(IDataTypeDefinition entity)
|
||||
{
|
||||
var dataTypeDto = new DataTypeDto
|
||||
{
|
||||
PropertyEditorAlias = entity.PropertyEditorAlias,
|
||||
DataTypeId = entity.Id,
|
||||
DbType = entity.DatabaseType.ToString(),
|
||||
NodeDto = BuildNodeDto(entity)
|
||||
};
|
||||
|
||||
if (_primaryKey > 0)
|
||||
{
|
||||
dataTypeDto.PrimaryKey = _primaryKey;
|
||||
}
|
||||
|
||||
return dataTypeDto;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void SetPrimaryKey(int primaryKey)
|
||||
{
|
||||
_primaryKey = primaryKey;
|
||||
}
|
||||
|
||||
private NodeDto BuildNodeDto(IDataTypeDefinition entity)
|
||||
{
|
||||
var nodeDto = new NodeDto
|
||||
{
|
||||
CreateDate = entity.CreateDate,
|
||||
NodeId = entity.Id,
|
||||
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
|
||||
NodeObjectType = _nodeObjectTypeId,
|
||||
ParentId = entity.ParentId,
|
||||
Path = entity.Path,
|
||||
SortOrder = entity.SortOrder,
|
||||
Text = entity.Name,
|
||||
Trashed = entity.Trashed,
|
||||
UniqueId = entity.Key,
|
||||
UserId = entity.CreatorId
|
||||
};
|
||||
|
||||
return nodeDto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,14 +12,18 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
internal class UmbracoEntityFactory
|
||||
{
|
||||
private static readonly Lazy<string[]> EntityProperties = new Lazy<string[]>(() => typeof(IUmbracoEntity).GetPublicProperties().Select(x => x.Name).ToArray());
|
||||
|
||||
/// <summary>
|
||||
/// Figure out what extra properties we have that are not on the IUmbracoEntity and add them to additional data
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="originalEntityProperties"></param>
|
||||
internal void AddAdditionalData(UmbracoEntity entity, IDictionary<string, object> originalEntityProperties)
|
||||
{
|
||||
var entityProps = typeof(IUmbracoEntity).GetPublicProperties().Select(x => x.Name).ToArray();
|
||||
|
||||
//figure out what extra properties we have that are not on the IUmbracoEntity and add them to additional data
|
||||
{
|
||||
foreach (var k in originalEntityProperties.Keys
|
||||
.Select(x => new { orig = x, title = x.ToCleanString(CleanStringType.PascalCase | CleanStringType.Ascii | CleanStringType.ConvertCase) })
|
||||
.Where(x => entityProps.InvariantContains(x.title) == false))
|
||||
.Where(x => EntityProperties.Value.InvariantContains(x.title) == false))
|
||||
{
|
||||
entity.AdditionalData[k.title] = originalEntityProperties[k.orig];
|
||||
}
|
||||
@@ -78,4 +82,4 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,342 +1,342 @@
|
||||
using System;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the initial data creation by running Insert for the base data.
|
||||
/// </summary>
|
||||
internal class BaseDataCreation
|
||||
{
|
||||
private readonly Database _database;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public BaseDataCreation(Database database, ILogger logger)
|
||||
{
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the base data creation by inserting the data foundation for umbraco
|
||||
/// specific to a table
|
||||
/// </summary>
|
||||
/// <param name="tableName">Name of the table to create base data for</param>
|
||||
public void InitializeBaseData(string tableName)
|
||||
{
|
||||
_logger.Info<BaseDataCreation>(string.Format("Creating data in table {0}", tableName));
|
||||
|
||||
if(tableName.Equals("umbracoNode"))
|
||||
{
|
||||
CreateUmbracoNodeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoLock"))
|
||||
{
|
||||
CreateUmbracoLockData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsContentType"))
|
||||
{
|
||||
CreateCmsContentTypeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoUser"))
|
||||
{
|
||||
CreateUmbracoUserData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoUserGroup"))
|
||||
{
|
||||
CreateUmbracoUserGroupData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoUser2UserGroup"))
|
||||
{
|
||||
CreateUmbracoUser2UserGroupData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoUserGroup2App"))
|
||||
{
|
||||
CreateUmbracoUserGroup2AppData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsPropertyTypeGroup"))
|
||||
{
|
||||
CreateCmsPropertyTypeGroupData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsPropertyType"))
|
||||
{
|
||||
CreateCmsPropertyTypeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoLanguage"))
|
||||
{
|
||||
CreateUmbracoLanguageData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsContentTypeAllowedContentType"))
|
||||
{
|
||||
CreateCmsContentTypeAllowedContentTypeData();
|
||||
}
|
||||
|
||||
if(tableName.Equals("cmsDataType"))
|
||||
{
|
||||
CreateCmsDataTypeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsDataTypePreValues"))
|
||||
{
|
||||
CreateCmsDataTypePreValuesData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoRelationType"))
|
||||
{
|
||||
CreateUmbracoRelationTypeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsTaskType"))
|
||||
{
|
||||
CreateCmsTaskTypeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoMigration"))
|
||||
{
|
||||
CreateUmbracoMigrationData();
|
||||
}
|
||||
|
||||
_logger.Info<BaseDataCreation>(string.Format("Done creating data in table {0}", tableName));
|
||||
}
|
||||
|
||||
private void CreateUmbracoNodeData()
|
||||
{
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -1, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1", SortOrder = 0, UniqueId = new Guid("916724a5-173d-4619-b97e-b9de133dd6f5"), Text = "SYSTEM DATA: umbraco master root", NodeObjectType = new Guid(Constants.ObjectTypes.SystemRoot), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -20, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1,-20", SortOrder = 0, UniqueId = new Guid("0F582A79-1E41-4CF0-BFA0-76340651891A"), Text = "Recycle Bin", NodeObjectType = new Guid(Constants.ObjectTypes.ContentRecycleBin), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -21, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1,-21", SortOrder = 0, UniqueId = new Guid("BF7C7CBC-952F-4518-97A2-69E9C7B33842"), Text = "Recycle Bin", NodeObjectType = new Guid(Constants.ObjectTypes.MediaRecycleBin), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -92, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-92", SortOrder = 35, UniqueId = new Guid("f0bc4bfb-b499-40d6-ba86-058885a5178c"), Text = "Label", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -90, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-90", SortOrder = 34, UniqueId = new Guid("84c6b441-31df-4ffe-b67e-67d5bc3ae65a"), Text = "Upload", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -89, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-89", SortOrder = 33, UniqueId = new Guid("c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3"), Text = "Textarea", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -88, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-88", SortOrder = 32, UniqueId = new Guid("0cc0eba1-9960-42c9-bf9b-60e150b429ae"), Text = "Textstring", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -87, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-87", SortOrder = 4, UniqueId = new Guid("ca90c950-0aff-4e72-b976-a30b1ac57dad"), Text = "Richtext editor", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -51, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-51", SortOrder = 2, UniqueId = new Guid("2e6d3631-066e-44b8-aec4-96f09099b2b5"), Text = "Numeric", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -49, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-49", SortOrder = 2, UniqueId = new Guid("92897bc6-a5f3-4ffe-ae27-f2e7e33dda49"), Text = "Checkbox", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -43, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-43", SortOrder = 2, UniqueId = new Guid("fbaf13a8-4036-41f2-93a3-974f678c312a"), Text = "Checkbox list", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -42, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-42", SortOrder = 2, UniqueId = new Guid("0b6a45e7-44ba-430d-9da5-4e46060b9e03"), Text = "Dropdown", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = new Guid("5046194e-4237-453c-a547-15db3a07c4e1"), Text = "Date Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = new Guid("bb5f57c9-ce2b-4bb9-b697-4caca783a805"), Text = "Radiobox", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -39, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-39", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = new Guid("0225af17-b302-49cb-9176-b9f35cab9c17"), Text = "Approved Color", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -36, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-36", SortOrder = 2, UniqueId = new Guid("e4d66c0f-b935-4200-81f0-025f7256b89a"), Text = "Date Picker with time", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.DefaultContentListViewDataTypeId, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-95", SortOrder = 2, UniqueId = new Guid("C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.DefaultMediaListViewDataTypeId, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-96", SortOrder = 2, UniqueId = new Guid("3A0156C4-3B8C-4803-BDC1-6871FAA83FFF"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Media", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.DefaultMembersListViewDataTypeId, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-97", SortOrder = 2, UniqueId = new Guid("AA2C52A0-CE87-4E65-A47C-7DF09358585D"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1031, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1031", SortOrder = 2, UniqueId = new Guid("f38bd2d7-65d0-48e6-95dc-87ce06ec2d3d"), Text = Constants.Conventions.MediaTypes.Folder, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1032, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1032", SortOrder = 2, UniqueId = new Guid("cc07b313-0843-4aa8-bbda-871c8da728c8"), Text = Constants.Conventions.MediaTypes.Image, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1041, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1041", SortOrder = 2, UniqueId = new Guid("b6b73142-b9c1-4bf8-a16d-e1c23320b549"), Text = "Tags", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1043, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1043", SortOrder = 2, UniqueId = new Guid("1df9f033-e6d4-451f-b8d2-e0cbc50a836f"), Text = "Image Cropper", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = new Guid("d59be02f-1df9-4228-aa1e-01917d806cda"), Text = Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = new Guid(Constants.ObjectTypes.MemberType), CreateDate = DateTime.Now });
|
||||
|
||||
//New UDI pickers with newer Ids
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1046, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1046", SortOrder = 2, UniqueId = new Guid("FD1E0DA5-5606-4862-B679-5D0CF3A52A59"), Text = "Content Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1047, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1047", SortOrder = 2, UniqueId = new Guid("1EA2E01F-EBD8-4CE1-8D71-6B1149E63548"), Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = new Guid("135D60E0-64D9-49ED-AB08-893C9BA44AE5"), Text = "Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1049, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1049", SortOrder = 2, UniqueId = new Guid("9DBBCBBB-2327-434A-B355-AF1B84E5010A"), Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1050, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1050", SortOrder = 2, UniqueId = new Guid("B4E3535A-1753-47E2-8568-602CF8CFEE6F"), Text = "Related Links", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
}
|
||||
|
||||
private void CreateUmbracoLockData()
|
||||
{
|
||||
// all lock objects
|
||||
_database.Insert("umbracoLock", "id", false, new LockDto { Id = Constants.Locks.Servers, Name = "Servers" });
|
||||
}
|
||||
|
||||
private void CreateCmsContentTypeData()
|
||||
{
|
||||
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 532, NodeId = 1031, Alias = Constants.Conventions.MediaTypes.Folder, Icon = "icon-folder", Thumbnail = "icon-folder", IsContainer = false, AllowAtRoot = true });
|
||||
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 533, NodeId = 1032, Alias = Constants.Conventions.MediaTypes.Image, Icon = "icon-picture", Thumbnail = "icon-picture", AllowAtRoot = true });
|
||||
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 534, NodeId = 1033, Alias = Constants.Conventions.MediaTypes.File, Icon = "icon-document", Thumbnail = "icon-document", AllowAtRoot = true });
|
||||
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 531, NodeId = 1044, Alias = Constants.Conventions.MemberTypes.DefaultAlias, Icon = "icon-user", Thumbnail = "icon-user" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoUserData()
|
||||
{
|
||||
_database.Insert("umbracoUser", "id", false, new UserDto { Id = 0, Disabled = false, NoConsole = false, UserName = "Administrator", Login = "admin", Password = "default", Email = "", UserLanguage = "en-US", CreateDate = DateTime.Now, UpdateDate = DateTime.Now });
|
||||
}
|
||||
|
||||
private void CreateUmbracoUserGroupData()
|
||||
{
|
||||
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 1, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.AdminGroupAlias, Name = "Administrators", DefaultPermissions = "CADMOSKTPIURZ:5F7ï", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-medal" });
|
||||
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 2, StartMediaId = -1, StartContentId = -1, Alias = "writer", Name = "Writers", DefaultPermissions = "CAH:F", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-edit" });
|
||||
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 3, StartMediaId = -1, StartContentId = -1, Alias = "editor", Name = "Editors", DefaultPermissions = "CADMOSKTPUZ:5Fï", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-tools" });
|
||||
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 4, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.TranslatorGroupAlias, Name = "Translators", DefaultPermissions = "AF", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-globe" });
|
||||
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 5, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.SensitiveDataGroupAlias, Name = "Sensitive data", DefaultPermissions = "", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-lock" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoUser2UserGroupData()
|
||||
{
|
||||
_database.Insert(new User2UserGroupDto { UserGroupId = 1, UserId = 0 }); //add admin to admins
|
||||
_database.Insert(new User2UserGroupDto { UserGroupId = 5, UserId = 0 }); //add admin to sensitive data
|
||||
}
|
||||
|
||||
private void CreateUmbracoUserGroup2AppData()
|
||||
{
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Content });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Developer });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Media });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Members });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Settings });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Users });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Forms });
|
||||
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 2, AppAlias = Constants.Applications.Content });
|
||||
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Content });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Media });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Forms });
|
||||
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 4, AppAlias = Constants.Applications.Translation });
|
||||
}
|
||||
|
||||
private void CreateCmsPropertyTypeGroupData()
|
||||
{
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 3, ContentTypeNodeId = 1032, Text = "Image", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Image) });
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 4, ContentTypeNodeId = 1033, Text = "File", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.File) });
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 5, ContentTypeNodeId = 1031, Text = "Contents", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Contents) });
|
||||
//membership property group
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 11, ContentTypeNodeId = 1044, Text = "Membership", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Membership) });
|
||||
}
|
||||
|
||||
private void CreateCmsPropertyTypeData()
|
||||
{
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 6, UniqueId = 6.ToGuid(), DataTypeId = 1043, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.File, Name = "Upload image", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 7, UniqueId = 7.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Width, Name = "Width", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 8, UniqueId = 8.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Height, Name = "Height", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 9, UniqueId = 9.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 10, UniqueId = 10.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 24, UniqueId = 24.ToGuid(), DataTypeId = -90, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.File, Name = "Upload file", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 25, UniqueId = 25.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 26, UniqueId = 26.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 27, UniqueId = 27.ToGuid(), DataTypeId = Constants.System.DefaultMediaListViewDataTypeId, ContentTypeId = 1031, PropertyTypeGroupId = 5, Alias = "contents", Name = "Contents:", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
//membership property types
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 28, UniqueId = 28.ToGuid(), DataTypeId = -89, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.Comments, Name = Constants.Conventions.Member.CommentsLabel, SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 29, UniqueId = 29.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.FailedPasswordAttempts, Name = Constants.Conventions.Member.FailedPasswordAttemptsLabel, SortOrder = 1, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 30, UniqueId = 30.ToGuid(), DataTypeId = -49, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsApproved, Name = Constants.Conventions.Member.IsApprovedLabel, SortOrder = 2, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 31, UniqueId = 31.ToGuid(), DataTypeId = -49, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsLockedOut, Name = Constants.Conventions.Member.IsLockedOutLabel, SortOrder = 3, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 32, UniqueId = 32.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLockoutDate, Name = Constants.Conventions.Member.LastLockoutDateLabel, SortOrder = 4, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 33, UniqueId = 33.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLoginDate, Name = Constants.Conventions.Member.LastLoginDateLabel, SortOrder = 5, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 34, UniqueId = 34.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastPasswordChangeDate, Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, SortOrder = 6, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
|
||||
}
|
||||
|
||||
private void CreateUmbracoLanguageData()
|
||||
{
|
||||
_database.Insert("umbracoLanguage", "id", false, new LanguageDto { Id = 1, IsoCode = "en-US", CultureName = "en-US" });
|
||||
}
|
||||
|
||||
private void CreateCmsContentTypeAllowedContentTypeData()
|
||||
{
|
||||
_database.Insert("cmsContentTypeAllowedContentType", "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1031 });
|
||||
_database.Insert("cmsContentTypeAllowedContentType", "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1032 });
|
||||
_database.Insert("cmsContentTypeAllowedContentType", "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1033 });
|
||||
}
|
||||
|
||||
private void CreateCmsDataTypeData()
|
||||
{
|
||||
//TODO Check which of the DataTypeIds below doesn't exist in umbracoNode, which results in a foreign key constraint errors.
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 1, DataTypeId = -49, PropertyEditorAlias = Constants.PropertyEditors.TrueFalseAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 2, DataTypeId = -51, PropertyEditorAlias = Constants.PropertyEditors.IntegerAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 3, DataTypeId = -87, PropertyEditorAlias = Constants.PropertyEditors.TinyMCEAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 4, DataTypeId = -88, PropertyEditorAlias = Constants.PropertyEditors.TextboxAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 5, DataTypeId = -89, PropertyEditorAlias = Constants.PropertyEditors.TextboxMultipleAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 6, DataTypeId = -90, PropertyEditorAlias = Constants.PropertyEditors.UploadFieldAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 7, DataTypeId = -92, PropertyEditorAlias = Constants.PropertyEditors.NoEditAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 8, DataTypeId = -36, PropertyEditorAlias = Constants.PropertyEditors.DateTimeAlias, DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 9, DataTypeId = -37, PropertyEditorAlias = Constants.PropertyEditors.ColorPickerAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 11, DataTypeId = -39, PropertyEditorAlias = Constants.PropertyEditors.DropDownListFlexibleAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -40, PropertyEditorAlias = Constants.PropertyEditors.RadioButtonListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, PropertyEditorAlias = Constants.PropertyEditors.DateAlias, DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, PropertyEditorAlias = Constants.PropertyEditors.DropDownListFlexibleAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = 1041, PropertyEditorAlias = Constants.PropertyEditors.TagsAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = 1043, PropertyEditorAlias = Constants.PropertyEditors.ImageCropperAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -26, DataTypeId = Constants.System.DefaultContentListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -27, DataTypeId = Constants.System.DefaultMediaListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.System.DefaultMembersListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
|
||||
//New UDI pickers with newer Ids
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 26, DataTypeId = 1046, PropertyEditorAlias = Constants.PropertyEditors.ContentPicker2Alias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = 1047, PropertyEditorAlias = Constants.PropertyEditors.MemberPicker2Alias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = 1048, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = 1049, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 30, DataTypeId = 1050, PropertyEditorAlias = Constants.PropertyEditors.RelatedLinks2Alias, DbType = "Ntext" });
|
||||
}
|
||||
|
||||
private void CreateCmsDataTypePreValuesData()
|
||||
{
|
||||
_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" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 5, Alias = "storageType", SortOrder = 0, DataTypeNodeId = 1041, Value = "Json" });
|
||||
|
||||
//defaults for the member list
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -1, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "10" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -2, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "username" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -3, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "asc" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -4, Alias = "includeProperties", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "[{\"alias\":\"username\",\"isSystem\":1},{\"alias\":\"email\",\"isSystem\":1},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1}]" });
|
||||
|
||||
//layouts for the list view
|
||||
var cardLayout = "{\"name\": \"Grid\",\"path\": \"views/propertyeditors/listview/layouts/grid/grid.html\", \"icon\": \"icon-thumbnails-small\", \"isSystem\": 1, \"selected\": true}";
|
||||
var listLayout = "{\"name\": \"List\",\"path\": \"views/propertyeditors/listview/layouts/list/list.html\",\"icon\": \"icon-list\", \"isSystem\": 1,\"selected\": true}";
|
||||
|
||||
//defaults for the media list
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -5, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "100" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -6, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "updateDate" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -7, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "desc" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -8, Alias = "layouts", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[" + cardLayout + "," + listLayout + "]" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -9, Alias = "includeProperties", SortOrder = 5, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]" });
|
||||
|
||||
//default's for MultipleMediaPickerAlias picker
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 6, Alias = "multiPicker", SortOrder = 0, DataTypeNodeId = 1049, Value = "1" });
|
||||
|
||||
// Defaults for single item dropdown
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 7, Alias = "multiple", SortOrder = 0, DataTypeNodeId = -42, Value = "0" });
|
||||
|
||||
// Defaults for multiple item dropdown
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 8, Alias = "multiple", SortOrder = 0, DataTypeNodeId = -39, Value = "1" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoRelationTypeData()
|
||||
{
|
||||
var relationType = new RelationTypeDto { Id = 1, Alias = Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, ChildObjectType = new Guid(Constants.ObjectTypes.Document), ParentObjectType = new Guid(Constants.ObjectTypes.Document), Dual = true, Name = Constants.Conventions.RelationTypes.RelateDocumentOnCopyName };
|
||||
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
|
||||
_database.Insert("umbracoRelationType", "id", false, relationType);
|
||||
relationType = new RelationTypeDto { Id = 2, Alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias, ChildObjectType = new Guid(Constants.ObjectTypes.Document), ParentObjectType = new Guid(Constants.ObjectTypes.Document), Dual = false, Name = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName };
|
||||
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
|
||||
_database.Insert("umbracoRelationType", "id", false, relationType);
|
||||
relationType = new RelationTypeDto { Id = 3, Alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias, ChildObjectType = new Guid(Constants.ObjectTypes.Media), ParentObjectType = new Guid(Constants.ObjectTypes.Media), Dual = false, Name = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName };
|
||||
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
|
||||
_database.Insert("umbracoRelationType", "id", false, relationType);
|
||||
}
|
||||
|
||||
private void CreateCmsTaskTypeData()
|
||||
{
|
||||
_database.Insert("cmsTaskType", "id", false, new TaskTypeDto { Id = 1, Alias = "toTranslate" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoMigrationData()
|
||||
{
|
||||
var dto = new MigrationDto
|
||||
{
|
||||
Id = 1,
|
||||
Name = Constants.System.UmbracoMigrationName,
|
||||
Version = UmbracoVersion.GetSemanticVersion().ToString(),
|
||||
CreateDate = DateTime.Now
|
||||
};
|
||||
|
||||
_database.Insert("umbracoMigration", "pk", false, dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the initial data creation by running Insert for the base data.
|
||||
/// </summary>
|
||||
internal class BaseDataCreation
|
||||
{
|
||||
private readonly Database _database;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public BaseDataCreation(Database database, ILogger logger)
|
||||
{
|
||||
_database = database;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the base data creation by inserting the data foundation for umbraco
|
||||
/// specific to a table
|
||||
/// </summary>
|
||||
/// <param name="tableName">Name of the table to create base data for</param>
|
||||
public void InitializeBaseData(string tableName)
|
||||
{
|
||||
_logger.Info<BaseDataCreation>(string.Format("Creating data in table {0}", tableName));
|
||||
|
||||
if(tableName.Equals("umbracoNode"))
|
||||
{
|
||||
CreateUmbracoNodeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoLock"))
|
||||
{
|
||||
CreateUmbracoLockData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsContentType"))
|
||||
{
|
||||
CreateCmsContentTypeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoUser"))
|
||||
{
|
||||
CreateUmbracoUserData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoUserGroup"))
|
||||
{
|
||||
CreateUmbracoUserGroupData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoUser2UserGroup"))
|
||||
{
|
||||
CreateUmbracoUser2UserGroupData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoUserGroup2App"))
|
||||
{
|
||||
CreateUmbracoUserGroup2AppData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsPropertyTypeGroup"))
|
||||
{
|
||||
CreateCmsPropertyTypeGroupData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsPropertyType"))
|
||||
{
|
||||
CreateCmsPropertyTypeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoLanguage"))
|
||||
{
|
||||
CreateUmbracoLanguageData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsContentTypeAllowedContentType"))
|
||||
{
|
||||
CreateCmsContentTypeAllowedContentTypeData();
|
||||
}
|
||||
|
||||
if(tableName.Equals("cmsDataType"))
|
||||
{
|
||||
CreateCmsDataTypeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsDataTypePreValues"))
|
||||
{
|
||||
CreateCmsDataTypePreValuesData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoRelationType"))
|
||||
{
|
||||
CreateUmbracoRelationTypeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("cmsTaskType"))
|
||||
{
|
||||
CreateCmsTaskTypeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoMigration"))
|
||||
{
|
||||
CreateUmbracoMigrationData();
|
||||
}
|
||||
|
||||
_logger.Info<BaseDataCreation>(string.Format("Done creating data in table {0}", tableName));
|
||||
}
|
||||
|
||||
private void CreateUmbracoNodeData()
|
||||
{
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -1, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1", SortOrder = 0, UniqueId = new Guid("916724a5-173d-4619-b97e-b9de133dd6f5"), Text = "SYSTEM DATA: umbraco master root", NodeObjectType = new Guid(Constants.ObjectTypes.SystemRoot), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -20, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1,-20", SortOrder = 0, UniqueId = new Guid("0F582A79-1E41-4CF0-BFA0-76340651891A"), Text = "Recycle Bin", NodeObjectType = new Guid(Constants.ObjectTypes.ContentRecycleBin), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -21, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1,-21", SortOrder = 0, UniqueId = new Guid("BF7C7CBC-952F-4518-97A2-69E9C7B33842"), Text = "Recycle Bin", NodeObjectType = new Guid(Constants.ObjectTypes.MediaRecycleBin), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -92, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-92", SortOrder = 35, UniqueId = Constants.DataTypes.LabelGuid, Text = "Label", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -90, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-90", SortOrder = 34, UniqueId = Constants.DataTypes.UploadGuid, Text = "Upload", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -89, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-89", SortOrder = 33, UniqueId = Constants.DataTypes.TextareaGuid, Text = "Textarea", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -88, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-88", SortOrder = 32, UniqueId = Constants.DataTypes.TextstringGuid, Text = "Textstring", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -87, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-87", SortOrder = 4, UniqueId = Constants.DataTypes.RichtextEditorGuid, Text = "Richtext editor", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -51, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-51", SortOrder = 2, UniqueId = Constants.DataTypes.NumericGuid, Text = "Numeric", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -49, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-49", SortOrder = 2, UniqueId = Constants.DataTypes.CheckboxGuid, Text = "Checkbox", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -43, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-43", SortOrder = 2, UniqueId = Constants.DataTypes.CheckboxListGuid, Text = "Checkbox list", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -42, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-42", SortOrder = 2, UniqueId = Constants.DataTypes.DropdownGuid, Text = "Dropdown", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = Constants.DataTypes.DatePickerGuid, Text = "Date Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = Constants.DataTypes.RadioboxGuid, Text = "Radiobox", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -39, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-39", SortOrder = 2, UniqueId = Constants.DataTypes.DropdownMultipleGuid, Text = "Dropdown multiple", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = Constants.DataTypes.ApprovedColorGuid, Text = "Approved Color", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -36, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-36", SortOrder = 2, UniqueId = Constants.DataTypes.DatePickerWithTimeGuid, Text = "Date Picker with time", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.DefaultContentListViewDataTypeId, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-95", SortOrder = 2, UniqueId = Constants.DataTypes.ListViewContentGuid, Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.DefaultMediaListViewDataTypeId, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-96", SortOrder = 2, UniqueId = Constants.DataTypes.ListViewMediaGuid, Text = Constants.Conventions.DataTypes.ListViewPrefix + "Media", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.DefaultMembersListViewDataTypeId, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-97", SortOrder = 2, UniqueId = Constants.DataTypes.ListViewMembersGuid, Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1031, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1031", SortOrder = 2, UniqueId = new Guid("f38bd2d7-65d0-48e6-95dc-87ce06ec2d3d"), Text = Constants.Conventions.MediaTypes.Folder, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1032, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1032", SortOrder = 2, UniqueId = new Guid("cc07b313-0843-4aa8-bbda-871c8da728c8"), Text = Constants.Conventions.MediaTypes.Image, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1041, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1041", SortOrder = 2, UniqueId = Constants.DataTypes.TagsGuid, Text = "Tags", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1043, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1043", SortOrder = 2, UniqueId = Constants.DataTypes.ImageCropperGuid, Text = "Image Cropper", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = Constants.DataTypes.MemberGuid, Text = Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = new Guid(Constants.ObjectTypes.MemberType), CreateDate = DateTime.Now });
|
||||
|
||||
//New UDI pickers with newer Ids
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1046, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1046", SortOrder = 2, UniqueId = Constants.DataTypes.ContentPickerGuid, Text = "Content Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1047, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1047", SortOrder = 2, UniqueId = Constants.DataTypes.MemberPickerGuid, Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = Constants.DataTypes.MediaPickerGuid, Text = "Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1049, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1049", SortOrder = 2, UniqueId = Constants.DataTypes.MultipleMediaPickerGuid, Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1050, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1050", SortOrder = 2, UniqueId = Constants.DataTypes.RelatedLinksGuid, Text = "Related Links", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
}
|
||||
|
||||
private void CreateUmbracoLockData()
|
||||
{
|
||||
// all lock objects
|
||||
_database.Insert("umbracoLock", "id", false, new LockDto { Id = Constants.Locks.Servers, Name = "Servers" });
|
||||
}
|
||||
|
||||
private void CreateCmsContentTypeData()
|
||||
{
|
||||
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 532, NodeId = 1031, Alias = Constants.Conventions.MediaTypes.Folder, Icon = "icon-folder", Thumbnail = "icon-folder", IsContainer = false, AllowAtRoot = true });
|
||||
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 533, NodeId = 1032, Alias = Constants.Conventions.MediaTypes.Image, Icon = "icon-picture", Thumbnail = "icon-picture", AllowAtRoot = true });
|
||||
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 534, NodeId = 1033, Alias = Constants.Conventions.MediaTypes.File, Icon = "icon-document", Thumbnail = "icon-document", AllowAtRoot = true });
|
||||
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 531, NodeId = 1044, Alias = Constants.Conventions.MemberTypes.DefaultAlias, Icon = "icon-user", Thumbnail = "icon-user" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoUserData()
|
||||
{
|
||||
_database.Insert("umbracoUser", "id", false, new UserDto { Id = 0, Disabled = false, NoConsole = false, UserName = "Administrator", Login = "admin", Password = "default", Email = "", UserLanguage = "en-US", CreateDate = DateTime.Now, UpdateDate = DateTime.Now });
|
||||
}
|
||||
|
||||
private void CreateUmbracoUserGroupData()
|
||||
{
|
||||
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 1, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.AdminGroupAlias, Name = "Administrators", DefaultPermissions = "CADMOSKTPIURZ:5F7ï", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-medal" });
|
||||
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 2, StartMediaId = -1, StartContentId = -1, Alias = "writer", Name = "Writers", DefaultPermissions = "CAH:F", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-edit" });
|
||||
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 3, StartMediaId = -1, StartContentId = -1, Alias = "editor", Name = "Editors", DefaultPermissions = "CADMOSKTPUZ:5Fï", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-tools" });
|
||||
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 4, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.TranslatorGroupAlias, Name = "Translators", DefaultPermissions = "AF", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-globe" });
|
||||
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 5, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.SensitiveDataGroupAlias, Name = "Sensitive data", DefaultPermissions = "", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-lock" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoUser2UserGroupData()
|
||||
{
|
||||
_database.Insert(new User2UserGroupDto { UserGroupId = 1, UserId = 0 }); //add admin to admins
|
||||
_database.Insert(new User2UserGroupDto { UserGroupId = 5, UserId = 0 }); //add admin to sensitive data
|
||||
}
|
||||
|
||||
private void CreateUmbracoUserGroup2AppData()
|
||||
{
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Content });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Developer });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Media });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Members });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Settings });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Users });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Forms });
|
||||
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 2, AppAlias = Constants.Applications.Content });
|
||||
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Content });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Media });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Forms });
|
||||
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 4, AppAlias = Constants.Applications.Translation });
|
||||
}
|
||||
|
||||
private void CreateCmsPropertyTypeGroupData()
|
||||
{
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 3, ContentTypeNodeId = 1032, Text = "Image", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Image) });
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 4, ContentTypeNodeId = 1033, Text = "File", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.File) });
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 5, ContentTypeNodeId = 1031, Text = "Contents", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Contents) });
|
||||
//membership property group
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 11, ContentTypeNodeId = 1044, Text = "Membership", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Membership) });
|
||||
}
|
||||
|
||||
private void CreateCmsPropertyTypeData()
|
||||
{
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 6, UniqueId = 6.ToGuid(), DataTypeId = 1043, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.File, Name = "Upload image", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 7, UniqueId = 7.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Width, Name = "Width", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 8, UniqueId = 8.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Height, Name = "Height", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 9, UniqueId = 9.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 10, UniqueId = 10.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 24, UniqueId = 24.ToGuid(), DataTypeId = -90, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.File, Name = "Upload file", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 25, UniqueId = 25.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 26, UniqueId = 26.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 27, UniqueId = 27.ToGuid(), DataTypeId = Constants.System.DefaultMediaListViewDataTypeId, ContentTypeId = 1031, PropertyTypeGroupId = 5, Alias = "contents", Name = "Contents:", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
//membership property types
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 28, UniqueId = 28.ToGuid(), DataTypeId = -89, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.Comments, Name = Constants.Conventions.Member.CommentsLabel, SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 29, UniqueId = 29.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.FailedPasswordAttempts, Name = Constants.Conventions.Member.FailedPasswordAttemptsLabel, SortOrder = 1, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 30, UniqueId = 30.ToGuid(), DataTypeId = -49, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsApproved, Name = Constants.Conventions.Member.IsApprovedLabel, SortOrder = 2, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 31, UniqueId = 31.ToGuid(), DataTypeId = -49, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsLockedOut, Name = Constants.Conventions.Member.IsLockedOutLabel, SortOrder = 3, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 32, UniqueId = 32.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLockoutDate, Name = Constants.Conventions.Member.LastLockoutDateLabel, SortOrder = 4, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 33, UniqueId = 33.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLoginDate, Name = Constants.Conventions.Member.LastLoginDateLabel, SortOrder = 5, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 34, UniqueId = 34.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastPasswordChangeDate, Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, SortOrder = 6, Mandatory = false, ValidationRegExp = null, Description = null });
|
||||
|
||||
}
|
||||
|
||||
private void CreateUmbracoLanguageData()
|
||||
{
|
||||
_database.Insert("umbracoLanguage", "id", false, new LanguageDto { Id = 1, IsoCode = "en-US", CultureName = "en-US" });
|
||||
}
|
||||
|
||||
private void CreateCmsContentTypeAllowedContentTypeData()
|
||||
{
|
||||
_database.Insert("cmsContentTypeAllowedContentType", "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1031 });
|
||||
_database.Insert("cmsContentTypeAllowedContentType", "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1032 });
|
||||
_database.Insert("cmsContentTypeAllowedContentType", "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1033 });
|
||||
}
|
||||
|
||||
private void CreateCmsDataTypeData()
|
||||
{
|
||||
//TODO Check which of the DataTypeIds below doesn't exist in umbracoNode, which results in a foreign key constraint errors.
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 1, DataTypeId = -49, PropertyEditorAlias = Constants.PropertyEditors.TrueFalseAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 2, DataTypeId = -51, PropertyEditorAlias = Constants.PropertyEditors.IntegerAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 3, DataTypeId = -87, PropertyEditorAlias = Constants.PropertyEditors.TinyMCEAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 4, DataTypeId = -88, PropertyEditorAlias = Constants.PropertyEditors.TextboxAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 5, DataTypeId = -89, PropertyEditorAlias = Constants.PropertyEditors.TextboxMultipleAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 6, DataTypeId = -90, PropertyEditorAlias = Constants.PropertyEditors.UploadFieldAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 7, DataTypeId = -92, PropertyEditorAlias = Constants.PropertyEditors.NoEditAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 8, DataTypeId = -36, PropertyEditorAlias = Constants.PropertyEditors.DateTimeAlias, DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 9, DataTypeId = -37, PropertyEditorAlias = Constants.PropertyEditors.ColorPickerAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 11, DataTypeId = -39, PropertyEditorAlias = Constants.PropertyEditors.DropDownListFlexibleAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -40, PropertyEditorAlias = Constants.PropertyEditors.RadioButtonListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, PropertyEditorAlias = Constants.PropertyEditors.DateAlias, DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, PropertyEditorAlias = Constants.PropertyEditors.DropDownListFlexibleAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = 1041, PropertyEditorAlias = Constants.PropertyEditors.TagsAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = 1043, PropertyEditorAlias = Constants.PropertyEditors.ImageCropperAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -26, DataTypeId = Constants.System.DefaultContentListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -27, DataTypeId = Constants.System.DefaultMediaListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.System.DefaultMembersListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
|
||||
//New UDI pickers with newer Ids
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 26, DataTypeId = 1046, PropertyEditorAlias = Constants.PropertyEditors.ContentPicker2Alias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = 1047, PropertyEditorAlias = Constants.PropertyEditors.MemberPicker2Alias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = 1048, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = 1049, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 30, DataTypeId = 1050, PropertyEditorAlias = Constants.PropertyEditors.RelatedLinks2Alias, DbType = "Ntext" });
|
||||
}
|
||||
|
||||
private void CreateCmsDataTypePreValuesData()
|
||||
{
|
||||
_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" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 5, Alias = "storageType", SortOrder = 0, DataTypeNodeId = 1041, Value = "Json" });
|
||||
|
||||
//defaults for the member list
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -1, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "10" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -2, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "username" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -3, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "asc" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -4, Alias = "includeProperties", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "[{\"alias\":\"username\",\"isSystem\":1},{\"alias\":\"email\",\"isSystem\":1},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1}]" });
|
||||
|
||||
//layouts for the list view
|
||||
var cardLayout = "{\"name\": \"Grid\",\"path\": \"views/propertyeditors/listview/layouts/grid/grid.html\", \"icon\": \"icon-thumbnails-small\", \"isSystem\": 1, \"selected\": true}";
|
||||
var listLayout = "{\"name\": \"List\",\"path\": \"views/propertyeditors/listview/layouts/list/list.html\",\"icon\": \"icon-list\", \"isSystem\": 1,\"selected\": true}";
|
||||
|
||||
//defaults for the media list
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -5, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "100" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -6, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "updateDate" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -7, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "desc" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -8, Alias = "layouts", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[" + cardLayout + "," + listLayout + "]" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -9, Alias = "includeProperties", SortOrder = 5, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]" });
|
||||
|
||||
//default's for MultipleMediaPickerAlias picker
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 6, Alias = "multiPicker", SortOrder = 0, DataTypeNodeId = 1049, Value = "1" });
|
||||
|
||||
// Defaults for single item dropdown
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 7, Alias = "multiple", SortOrder = 0, DataTypeNodeId = -42, Value = "0" });
|
||||
|
||||
// Defaults for multiple item dropdown
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 8, Alias = "multiple", SortOrder = 0, DataTypeNodeId = -39, Value = "1" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoRelationTypeData()
|
||||
{
|
||||
var relationType = new RelationTypeDto { Id = 1, Alias = Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, ChildObjectType = new Guid(Constants.ObjectTypes.Document), ParentObjectType = new Guid(Constants.ObjectTypes.Document), Dual = true, Name = Constants.Conventions.RelationTypes.RelateDocumentOnCopyName };
|
||||
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
|
||||
_database.Insert("umbracoRelationType", "id", false, relationType);
|
||||
relationType = new RelationTypeDto { Id = 2, Alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias, ChildObjectType = new Guid(Constants.ObjectTypes.Document), ParentObjectType = new Guid(Constants.ObjectTypes.Document), Dual = false, Name = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName };
|
||||
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
|
||||
_database.Insert("umbracoRelationType", "id", false, relationType);
|
||||
relationType = new RelationTypeDto { Id = 3, Alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias, ChildObjectType = new Guid(Constants.ObjectTypes.Media), ParentObjectType = new Guid(Constants.ObjectTypes.Media), Dual = false, Name = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName };
|
||||
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
|
||||
_database.Insert("umbracoRelationType", "id", false, relationType);
|
||||
}
|
||||
|
||||
private void CreateCmsTaskTypeData()
|
||||
{
|
||||
_database.Insert("cmsTaskType", "id", false, new TaskTypeDto { Id = 1, Alias = "toTranslate" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoMigrationData()
|
||||
{
|
||||
var dto = new MigrationDto
|
||||
{
|
||||
Id = 1,
|
||||
Name = Constants.System.UmbracoMigrationName,
|
||||
Version = UmbracoVersion.GetSemanticVersion().ToString(),
|
||||
CreateDate = DateTime.Now
|
||||
};
|
||||
|
||||
_database.Insert("umbracoMigration", "pk", false, dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+2945
-2904
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
internal static class DateTypeServiceExtensions
|
||||
{
|
||||
public static bool IsDataTypeIgnoringUserStartNodes(this IDataTypeService dataTypeService, Guid key)
|
||||
{
|
||||
if (DataTypeExtensions.IsBuildInDataType(key)) return false; //built in ones can never be ignoring start nodes
|
||||
|
||||
var dataType = dataTypeService.GetDataTypeDefinitionById(key);
|
||||
|
||||
if (dataType != null)
|
||||
{
|
||||
var preValues = dataTypeService.GetPreValuesCollectionByDataTypeId(dataType.Id);
|
||||
if (preValues.FormatAsDictionary().TryGetValue(
|
||||
Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes, out var preValue))
|
||||
return preValue.Value.InvariantEquals("1");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,167 +1,167 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the DataType Service, which is an easy access to operations involving <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
public interface IDataTypeService : IService
|
||||
{
|
||||
Attempt<OperationStatus<EntityContainer, OperationStatusType>> CreateContainer(int parentId, string name, int userId = 0);
|
||||
Attempt<OperationStatus> SaveContainer(EntityContainer container, int userId = 0);
|
||||
EntityContainer GetContainer(int containerId);
|
||||
EntityContainer GetContainer(Guid containerId);
|
||||
IEnumerable<EntityContainer> GetContainers(string folderName, int level);
|
||||
IEnumerable<EntityContainer> GetContainers(IDataTypeDefinition dataTypeDefinition);
|
||||
IEnumerable<EntityContainer> GetContainers(int[] containerIds);
|
||||
Attempt<OperationStatus> DeleteContainer(int containerId, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its Name
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the <see cref="IDataTypeDefinition"/></param>
|
||||
/// <returns><see cref="IDataTypeDefinition"/></returns>
|
||||
IDataTypeDefinition GetDataTypeDefinitionByName(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="IDataTypeDefinition"/></param>
|
||||
/// <returns><see cref="IDataTypeDefinition"/></returns>
|
||||
IDataTypeDefinition GetDataTypeDefinitionById(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its unique guid Id
|
||||
/// </summary>
|
||||
/// <param name="id">Unique guid Id of the DataType</param>
|
||||
/// <returns><see cref="IDataTypeDefinition"/></returns>
|
||||
IDataTypeDefinition GetDataTypeDefinitionById(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all <see cref="IDataTypeDefinition"/> objects or those with the ids passed in
|
||||
/// </summary>
|
||||
/// <param name="ids">Optional array of Ids</param>
|
||||
/// <returns>An enumerable list of <see cref="IDataTypeDefinition"/> objects</returns>
|
||||
IEnumerable<IDataTypeDefinition> GetAllDataTypeDefinitions(params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Saves an <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinition"><see cref="IDataTypeDefinition"/> to save</param>
|
||||
/// <param name="userId">Id of the user issueing the save</param>
|
||||
void Save(IDataTypeDefinition dataTypeDefinition, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a collection of <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinitions"><see cref="IDataTypeDefinition"/> to save</param>
|
||||
/// <param name="userId">Id of the user issueing the save</param>
|
||||
void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a collection of <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinitions"><see cref="IDataTypeDefinition"/> to save</param>
|
||||
/// <param name="userId">Id of the user issueing the save</param>
|
||||
/// <param name="raiseEvents">Boolean indicating whether or not to raise events</param>
|
||||
void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId, bool raiseEvents);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Please note that deleting a <see cref="IDataTypeDefinition"/> will remove
|
||||
/// all the <see cref="PropertyType"/> data that references this <see cref="IDataTypeDefinition"/>.
|
||||
/// </remarks>
|
||||
/// <param name="dataTypeDefinition"><see cref="IDataTypeDefinition"/> to delete</param>
|
||||
/// <param name="userId">Id of the user issueing the deletion</param>
|
||||
void Delete(IDataTypeDefinition dataTypeDefinition, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IDataType"/> specified by it's unique ID
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the DataType, which corresponds to the Guid Id of the control</param>
|
||||
/// <returns><see cref="IDataType"/> object</returns>
|
||||
[Obsolete("IDataType is obsolete and is no longer used, it will be removed from the codebase in future versions")]
|
||||
IDataType GetDataTypeById(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a complete list of all registered <see cref="IDataType"/>'s
|
||||
/// </summary>
|
||||
/// <returns>An enumerable list of <see cref="IDataType"/> objects</returns>
|
||||
[Obsolete("IDataType is obsolete and is no longer used, it will be removed from the codebase in future versions")]
|
||||
IEnumerable<IDataType> GetAllDataTypes();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its control Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the DataType control</param>
|
||||
/// <returns><see cref="IDataTypeDefinition"/></returns>
|
||||
[Obsolete("Property editor's are defined by a string alias from version 7 onwards, use the overload GetDataTypeDefinitionByPropertyEditorAlias instead")]
|
||||
IEnumerable<IDataTypeDefinition> GetDataTypeDefinitionByControlId(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its control Id
|
||||
/// </summary>
|
||||
/// <param name="propertyEditorAlias">Alias of the property editor</param>
|
||||
/// <returns>Collection of <see cref="IDataTypeDefinition"/> objects with a matching contorl id</returns>
|
||||
IEnumerable<IDataTypeDefinition> GetDataTypeDefinitionByPropertyEditorAlias(string propertyEditorAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all values for an <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="IDataTypeDefinition"/> to retrieve prevalues from</param>
|
||||
/// <returns>An enumerable list of string values</returns>
|
||||
IEnumerable<string> GetPreValuesByDataTypeId(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pre-value collection by data type id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
PreValueCollection GetPreValuesCollectionByDataTypeId(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a list of PreValues for a given DataTypeDefinition
|
||||
/// </summary>
|
||||
/// <param name="dataTypeId">Id of the DataTypeDefinition to save PreValues for</param>
|
||||
/// <param name="values">List of string values to save</param>
|
||||
[Obsolete("This should no longer be used, use the alternative SavePreValues or SaveDataTypeAndPreValues methods instead. This will only insert pre-values without keys")]
|
||||
void SavePreValues(int dataTypeId, IEnumerable<string> values);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a list of PreValues for a given DataTypeDefinition
|
||||
/// </summary>
|
||||
/// <param name="dataTypeId">Id of the DataTypeDefinition to save PreValues for</param>
|
||||
/// <param name="values">List of key/value pairs to save</param>
|
||||
void SavePreValues(int dataTypeId, IDictionary<string, PreValue> values);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a list of PreValues for a given DataTypeDefinition
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinition">The DataTypeDefinition to save PreValues for</param>
|
||||
/// <param name="values">List of key/value pairs to save</param>
|
||||
void SavePreValues(IDataTypeDefinition dataTypeDefinition, IDictionary<string, PreValue> values);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data type and it's prevalues
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinition"></param>
|
||||
/// <param name="values"></param>
|
||||
/// <param name="userId"></param>
|
||||
void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary<string, PreValue> values, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific PreValue by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the PreValue to retrieve the value from</param>
|
||||
/// <returns>PreValue as a string</returns>
|
||||
string GetPreValueAsString(int id);
|
||||
|
||||
Attempt<OperationStatus<MoveOperationStatusType>> Move(IDataTypeDefinition toMove, int parentId);
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the DataType Service, which is an easy access to operations involving <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
public interface IDataTypeService : IService
|
||||
{
|
||||
Attempt<OperationStatus<EntityContainer, OperationStatusType>> CreateContainer(int parentId, string name, int userId = 0);
|
||||
Attempt<OperationStatus> SaveContainer(EntityContainer container, int userId = 0);
|
||||
EntityContainer GetContainer(int containerId);
|
||||
EntityContainer GetContainer(Guid containerId);
|
||||
IEnumerable<EntityContainer> GetContainers(string folderName, int level);
|
||||
IEnumerable<EntityContainer> GetContainers(IDataTypeDefinition dataTypeDefinition);
|
||||
IEnumerable<EntityContainer> GetContainers(int[] containerIds);
|
||||
Attempt<OperationStatus> DeleteContainer(int containerId, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its Name
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the <see cref="IDataTypeDefinition"/></param>
|
||||
/// <returns><see cref="IDataTypeDefinition"/></returns>
|
||||
IDataTypeDefinition GetDataTypeDefinitionByName(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="IDataTypeDefinition"/></param>
|
||||
/// <returns><see cref="IDataTypeDefinition"/></returns>
|
||||
IDataTypeDefinition GetDataTypeDefinitionById(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its unique guid Id
|
||||
/// </summary>
|
||||
/// <param name="id">Unique guid Id of the DataType</param>
|
||||
/// <returns><see cref="IDataTypeDefinition"/></returns>
|
||||
IDataTypeDefinition GetDataTypeDefinitionById(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all <see cref="IDataTypeDefinition"/> objects or those with the ids passed in
|
||||
/// </summary>
|
||||
/// <param name="ids">Optional array of Ids</param>
|
||||
/// <returns>An enumerable list of <see cref="IDataTypeDefinition"/> objects</returns>
|
||||
IEnumerable<IDataTypeDefinition> GetAllDataTypeDefinitions(params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Saves an <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinition"><see cref="IDataTypeDefinition"/> to save</param>
|
||||
/// <param name="userId">Id of the user issueing the save</param>
|
||||
void Save(IDataTypeDefinition dataTypeDefinition, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a collection of <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinitions"><see cref="IDataTypeDefinition"/> to save</param>
|
||||
/// <param name="userId">Id of the user issueing the save</param>
|
||||
void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a collection of <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinitions"><see cref="IDataTypeDefinition"/> to save</param>
|
||||
/// <param name="userId">Id of the user issueing the save</param>
|
||||
/// <param name="raiseEvents">Boolean indicating whether or not to raise events</param>
|
||||
void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId, bool raiseEvents);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Please note that deleting a <see cref="IDataTypeDefinition"/> will remove
|
||||
/// all the <see cref="PropertyType"/> data that references this <see cref="IDataTypeDefinition"/>.
|
||||
/// </remarks>
|
||||
/// <param name="dataTypeDefinition"><see cref="IDataTypeDefinition"/> to delete</param>
|
||||
/// <param name="userId">Id of the user issueing the deletion</param>
|
||||
void Delete(IDataTypeDefinition dataTypeDefinition, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IDataType"/> specified by it's unique ID
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the DataType, which corresponds to the Guid Id of the control</param>
|
||||
/// <returns><see cref="IDataType"/> object</returns>
|
||||
[Obsolete("IDataType is obsolete and is no longer used, it will be removed from the codebase in future versions")]
|
||||
IDataType GetDataTypeById(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a complete list of all registered <see cref="IDataType"/>'s
|
||||
/// </summary>
|
||||
/// <returns>An enumerable list of <see cref="IDataType"/> objects</returns>
|
||||
[Obsolete("IDataType is obsolete and is no longer used, it will be removed from the codebase in future versions")]
|
||||
IEnumerable<IDataType> GetAllDataTypes();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its control Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the DataType control</param>
|
||||
/// <returns><see cref="IDataTypeDefinition"/></returns>
|
||||
[Obsolete("Property editor's are defined by a string alias from version 7 onwards, use the overload GetDataTypeDefinitionByPropertyEditorAlias instead")]
|
||||
IEnumerable<IDataTypeDefinition> GetDataTypeDefinitionByControlId(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its control Id
|
||||
/// </summary>
|
||||
/// <param name="propertyEditorAlias">Alias of the property editor</param>
|
||||
/// <returns>Collection of <see cref="IDataTypeDefinition"/> objects with a matching contorl id</returns>
|
||||
IEnumerable<IDataTypeDefinition> GetDataTypeDefinitionByPropertyEditorAlias(string propertyEditorAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all values for an <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="IDataTypeDefinition"/> to retrieve prevalues from</param>
|
||||
/// <returns>An enumerable list of string values</returns>
|
||||
IEnumerable<string> GetPreValuesByDataTypeId(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pre-value collection by data type id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
PreValueCollection GetPreValuesCollectionByDataTypeId(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a list of PreValues for a given DataTypeDefinition
|
||||
/// </summary>
|
||||
/// <param name="dataTypeId">Id of the DataTypeDefinition to save PreValues for</param>
|
||||
/// <param name="values">List of string values to save</param>
|
||||
[Obsolete("This should no longer be used, use the alternative SavePreValues or SaveDataTypeAndPreValues methods instead. This will only insert pre-values without keys")]
|
||||
void SavePreValues(int dataTypeId, IEnumerable<string> values);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a list of PreValues for a given DataTypeDefinition
|
||||
/// </summary>
|
||||
/// <param name="dataTypeId">Id of the DataTypeDefinition to save PreValues for</param>
|
||||
/// <param name="values">List of key/value pairs to save</param>
|
||||
void SavePreValues(int dataTypeId, IDictionary<string, PreValue> values);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a list of PreValues for a given DataTypeDefinition
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinition">The DataTypeDefinition to save PreValues for</param>
|
||||
/// <param name="values">List of key/value pairs to save</param>
|
||||
void SavePreValues(IDataTypeDefinition dataTypeDefinition, IDictionary<string, PreValue> values);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data type and it's prevalues
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinition"></param>
|
||||
/// <param name="values"></param>
|
||||
/// <param name="userId"></param>
|
||||
void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary<string, PreValue> values, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific PreValue by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the PreValue to retrieve the value from</param>
|
||||
/// <returns>PreValue as a string</returns>
|
||||
string GetPreValueAsString(int id);
|
||||
|
||||
Attempt<OperationStatus<MoveOperationStatusType>> Move(IDataTypeDefinition toMove, int parentId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,298 +1,306 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
public interface IEntityService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns true if the entity exists
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
bool Exists(Guid key);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the entity exists
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
bool Exists(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the integer id for a given GUID
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <returns></returns>
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
public interface IEntityService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns true if the entity exists
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
bool Exists(Guid key);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the entity exists
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
bool Exists(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the integer id for a given GUID
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <returns></returns>
|
||||
Attempt<int> GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the integer id for a given Udi
|
||||
/// </summary>
|
||||
/// <param name="udi"></param>
|
||||
/// <returns></returns>
|
||||
Attempt<int> GetIdForUdi(Udi udi);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the GUID for a given integer id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <returns></returns>
|
||||
Attempt<Guid> GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an UmbracoEntity by its Id, and optionally loads the complete object graph.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
|
||||
/// </returns>
|
||||
/// <param name="key">Unique Id of the object to retrieve</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c>.</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an UmbracoEntity by its Id, and optionally loads the complete object graph.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
|
||||
/// </returns>
|
||||
/// <param name="id">Id of the object to retrieve</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c>.</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity Get(int id, bool loadBaseType = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an UmbracoEntity by its Id and UmbracoObjectType, and optionally loads the complete object graph.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
|
||||
/// </returns>
|
||||
/// <param name="key">Unique Id of the object to retrieve</param>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the entity to retrieve</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c>.</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetByKey(Guid key, UmbracoObjectTypes umbracoObjectType, bool loadBaseType = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an UmbracoEntity by its Id and UmbracoObjectType, and optionally loads the complete object graph.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
|
||||
/// </returns>
|
||||
/// <param name="id">Id of the object to retrieve</param>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the entity to retrieve</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c>.</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity Get(int id, UmbracoObjectTypes umbracoObjectType, bool loadBaseType = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an UmbracoEntity by its Id and specified Type. Optionally loads the complete object graph.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
|
||||
/// </returns>
|
||||
/// <typeparam name="T">Type of the model to retrieve. Must be based on an <see cref="IUmbracoEntity"/></typeparam>
|
||||
/// <param name="key">Unique Id of the object to retrieve</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c>.</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetByKey<T>(Guid key, bool loadBaseType = true) where T : IUmbracoEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets an UmbracoEntity by its Id and specified Type. Optionally loads the complete object graph.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
|
||||
/// </returns>
|
||||
/// <typeparam name="T">Type of the model to retrieve. Must be based on an <see cref="IUmbracoEntity"/></typeparam>
|
||||
/// <param name="id">Id of the object to retrieve</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c>.</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity Get<T>(int id, bool loadBaseType = true) where T : IUmbracoEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent of entity by its id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the entity to retrieve the Parent for</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetParent(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent of entity by its id and UmbracoObjectType
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the entity to retrieve the Parent for</param>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the parent to retrieve</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetParent(int id, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of children by the parents Id
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the parent to retrieve children for</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetChildren(int parentId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of children by the parents Id and UmbracoObjectType
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the parent to retrieve children for</param>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the children to retrieve</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of children
|
||||
/// </summary>
|
||||
/// <param name="parentId">The parent id to return children for</param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedChildren(int parentId, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "");
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of descendants
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedDescendants(int id, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "");
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of descendants
|
||||
/// </summary>
|
||||
IEnumerable<IUmbracoEntity> GetPagedDescendants(IEnumerable<int> ids, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "");
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of descendants from the root
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <param name="includeTrashed">true/false to include trashed objects</param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedDescendantsFromRoot(UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "", bool includeTrashed = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of descendents by the parents Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of entity to retrieve descendents for</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetDescendents(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of descendents by the parents Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of entity to retrieve descendents for</param>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the descendents to retrieve</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetDescendents(int id, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of the entities at the root, which corresponds to the entities with a Parent Id of -1.
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the root entities to retrieve</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetRootEntities(UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of all <see cref="IUmbracoEntity"/> of a given type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the entities to retrieve</typeparam>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetAll<T>(params int[] ids) where T : IUmbracoEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of all <see cref="IUmbracoEntity"/> of a given type.
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the entities to return</param>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetAll(UmbracoObjectTypes umbracoObjectType, params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of all <see cref="IUmbracoEntity"/> of a given type.
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the entities to return</param>
|
||||
/// <param name="keys"></param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetAll(UmbracoObjectTypes umbracoObjectType, Guid[] keys);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IUmbracoEntity"/>
|
||||
/// </summary>
|
||||
/// <param name="objectTypeId">Guid id of the UmbracoObjectType</param>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetAll(Guid objectTypeId, params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets paths for entities.
|
||||
/// </summary>
|
||||
IEnumerable<EntityPath> GetAllPaths(UmbracoObjectTypes umbracoObjectType, params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets paths for entities.
|
||||
/// </summary>
|
||||
IEnumerable<EntityPath> GetAllPaths(UmbracoObjectTypes umbracoObjectType, params Guid[] keys);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UmbracoObjectType from the integer id of an IUmbracoEntity.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the entity</param>
|
||||
/// <returns><see cref="UmbracoObjectTypes"/></returns>
|
||||
UmbracoObjectTypes GetObjectType(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UmbracoObjectType from an IUmbracoEntity.
|
||||
/// </summary>
|
||||
/// <param name="entity"><see cref="IUmbracoEntity"/></param>
|
||||
/// <returns><see cref="UmbracoObjectTypes"/></returns>
|
||||
UmbracoObjectTypes GetObjectType(IUmbracoEntity entity);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Type of an entity by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the entity</param>
|
||||
/// <returns>Type of the entity</returns>
|
||||
Type GetEntityType(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Type of an entity by its <see cref="UmbracoObjectTypes"/>
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType"><see cref="UmbracoObjectTypes"/></param>
|
||||
/// <returns>Type of the entity</returns>
|
||||
Type GetEntityType(UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Reserves an identifier for a key.
|
||||
/// </summary>
|
||||
/// <param name="key">They key.</param>
|
||||
/// <returns>The identifier.</returns>
|
||||
/// <remarks>When a new content or a media is saved with the key, it will have the reserved identifier.</remarks>
|
||||
int ReserveId(Guid key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the integer id for a given Udi
|
||||
/// </summary>
|
||||
/// <param name="udi"></param>
|
||||
/// <returns></returns>
|
||||
Attempt<int> GetIdForUdi(Udi udi);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the GUID for a given integer id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <returns></returns>
|
||||
Attempt<Guid> GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an UmbracoEntity by its Id, and optionally loads the complete object graph.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
|
||||
/// </returns>
|
||||
/// <param name="key">Unique Id of the object to retrieve</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetByKey(Guid key);
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an UmbracoEntity by its Id, and optionally loads the complete object graph.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
|
||||
/// </returns>
|
||||
/// <param name="id">Id of the object to retrieve</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity Get(int id);
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IUmbracoEntity Get(int id, bool loadBaseType = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an UmbracoEntity by its Id and UmbracoObjectType, and optionally loads the complete object graph.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
|
||||
/// </returns>
|
||||
/// <param name="key">Unique Id of the object to retrieve</param>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the entity to retrieve</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetByKey(Guid key, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IUmbracoEntity GetByKey(Guid key, UmbracoObjectTypes umbracoObjectType, bool loadBaseType = true);
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IUmbracoEntity GetByKey<T>(Guid key, bool loadBaseType = true) where T : IUmbracoEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets an UmbracoEntity by its Id and UmbracoObjectType, and optionally loads the complete object graph.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
|
||||
/// </returns>
|
||||
/// <param name="id">Id of the object to retrieve</param>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the entity to retrieve</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity Get(int id, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IUmbracoEntity Get(int id, UmbracoObjectTypes umbracoObjectType, bool loadBaseType = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an UmbracoEntity by its Id and specified Type. Optionally loads the complete object graph.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
|
||||
/// </returns>
|
||||
/// <typeparam name="T">Type of the model to retrieve. Must be based on an <see cref="IUmbracoEntity"/></typeparam>
|
||||
/// <param name="id">Id of the object to retrieve</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity Get<T>(int id) where T : IUmbracoEntity;
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IUmbracoEntity Get<T>(int id, bool loadBaseType = true) where T : IUmbracoEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent of entity by its id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the entity to retrieve the Parent for</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetParent(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent of entity by its id and UmbracoObjectType
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the entity to retrieve the Parent for</param>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the parent to retrieve</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetParent(int id, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of children by the parents Id
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the parent to retrieve children for</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetChildren(int parentId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of children by the parents Id and UmbracoObjectType
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the parent to retrieve children for</param>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the children to retrieve</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of children
|
||||
/// </summary>
|
||||
/// <param name="parentId">The parent id to return children for</param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedChildren(int parentId, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "");
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of descendants
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedDescendants(int id, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "");
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of descendants
|
||||
/// </summary>
|
||||
IEnumerable<IUmbracoEntity> GetPagedDescendants(IEnumerable<int> ids, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "");
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of descendants from the root
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <param name="includeTrashed">true/false to include trashed objects</param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedDescendantsFromRoot(UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "", bool includeTrashed = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of descendents by the parents Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of entity to retrieve descendents for</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetDescendents(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of descendents by the parents Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of entity to retrieve descendents for</param>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the descendents to retrieve</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetDescendents(int id, UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of the entities at the root, which corresponds to the entities with a Parent Id of -1.
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the root entities to retrieve</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetRootEntities(UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of all <see cref="IUmbracoEntity"/> of a given type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the entities to retrieve</typeparam>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetAll<T>(params int[] ids) where T : IUmbracoEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of all <see cref="IUmbracoEntity"/> of a given type.
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the entities to return</param>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetAll(UmbracoObjectTypes umbracoObjectType, params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of all <see cref="IUmbracoEntity"/> of a given type.
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType">UmbracoObjectType of the entities to return</param>
|
||||
/// <param name="keys"></param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetAll(UmbracoObjectTypes umbracoObjectType, Guid[] keys);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IUmbracoEntity"/>
|
||||
/// </summary>
|
||||
/// <param name="objectTypeId">Guid id of the UmbracoObjectType</param>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
IEnumerable<IUmbracoEntity> GetAll(Guid objectTypeId, params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets paths for entities.
|
||||
/// </summary>
|
||||
IEnumerable<EntityPath> GetAllPaths(UmbracoObjectTypes umbracoObjectType, params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets paths for entities.
|
||||
/// </summary>
|
||||
IEnumerable<EntityPath> GetAllPaths(UmbracoObjectTypes umbracoObjectType, params Guid[] keys);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UmbracoObjectType from the integer id of an IUmbracoEntity.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the entity</param>
|
||||
/// <returns><see cref="UmbracoObjectTypes"/></returns>
|
||||
UmbracoObjectTypes GetObjectType(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UmbracoObjectType from an IUmbracoEntity.
|
||||
/// </summary>
|
||||
/// <param name="entity"><see cref="IUmbracoEntity"/></param>
|
||||
/// <returns><see cref="UmbracoObjectTypes"/></returns>
|
||||
UmbracoObjectTypes GetObjectType(IUmbracoEntity entity);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Type of an entity by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the entity</param>
|
||||
/// <returns>Type of the entity</returns>
|
||||
Type GetEntityType(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Type of an entity by its <see cref="UmbracoObjectTypes"/>
|
||||
/// </summary>
|
||||
/// <param name="umbracoObjectType"><see cref="UmbracoObjectTypes"/></param>
|
||||
/// <returns>Type of the entity</returns>
|
||||
Type GetEntityType(UmbracoObjectTypes umbracoObjectType);
|
||||
|
||||
/// <summary>
|
||||
/// Reserves an identifier for a key.
|
||||
/// </summary>
|
||||
/// <param name="key">They key.</param>
|
||||
/// <returns>The identifier.</returns>
|
||||
/// <remarks>When a new content or a media is saved with the key, it will have the reserved identifier.</remarks>
|
||||
int ReserveId(Guid key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,306 +1,325 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
public interface IRelationService : IService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a <see cref="Relation"/> by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="Relation"/></param>
|
||||
/// <returns>A <see cref="Relation"/> object</returns>
|
||||
IRelation GetById(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="RelationType"/> by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="RelationType"/></param>
|
||||
/// <returns>A <see cref="RelationType"/> object</returns>
|
||||
IRelationType GetRelationTypeById(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="RelationType"/> by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="RelationType"/></param>
|
||||
/// <returns>A <see cref="RelationType"/> object</returns>
|
||||
IRelationType GetRelationTypeById(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="RelationType"/> by its Alias
|
||||
/// </summary>
|
||||
/// <param name="alias">Alias of the <see cref="RelationType"/></param>
|
||||
/// <returns>A <see cref="RelationType"/> object</returns>
|
||||
IRelationType GetRelationTypeByAlias(string alias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all <see cref="Relation"/> objects
|
||||
/// </summary>
|
||||
/// <param name="ids">Optional array of integer ids to return relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetAllRelations(params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all <see cref="Relation"/> objects by their <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationType"><see cref="RelationType"/> to retrieve Relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetAllRelationsByRelationType(RelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all <see cref="Relation"/> objects by their <see cref="RelationType"/>'s Id
|
||||
/// </summary>
|
||||
/// <param name="relationTypeId">Id of the <see cref="RelationType"/> to retrieve Relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetAllRelationsByRelationType(int relationTypeId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all <see cref="Relation"/> objects
|
||||
/// </summary>
|
||||
/// <param name="ids">Optional array of integer ids to return relationtypes for</param>
|
||||
/// <returns>An enumerable list of <see cref="RelationType"/> objects</returns>
|
||||
IEnumerable<IRelationType> GetAllRelationTypes(params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their parent Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the parent to retrieve relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByParentId(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their parent entity
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent Entity to retrieve relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByParent(IUmbracoEntity parent);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their parent entity
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent Entity to retrieve relations for</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to retrieve</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByParent(IUmbracoEntity parent, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their child Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the child to retrieve relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByChildId(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their child Entity
|
||||
/// </summary>
|
||||
/// <param name="child">Child Entity to retrieve relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByChild(IUmbracoEntity child);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their child Entity
|
||||
/// </summary>
|
||||
/// <param name="child">Child Entity to retrieve relations for</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to retrieve</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByChild(IUmbracoEntity child, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their child or parent Id.
|
||||
/// Using this method will get you all relations regards of it being a child or parent relation.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the child or parent to retrieve relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByParentOrChildId(int id);
|
||||
|
||||
IEnumerable<IRelation> GetByParentOrChildId(int id, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by the Name of the <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationTypeName">Name of the <see cref="RelationType"/> to retrieve Relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByRelationTypeName(string relationTypeName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by the Alias of the <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationTypeAlias">Alias of the <see cref="RelationType"/> to retrieve Relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByRelationTypeAlias(string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by the Id of the <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationTypeId">Id of the <see cref="RelationType"/> to retrieve Relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByRelationTypeId(int relationTypeId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Child object from a Relation as an <see cref="IUmbracoEntity"/>
|
||||
/// </summary>
|
||||
/// <param name="relation">Relation to retrieve child object from</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c></param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetChildEntityFromRelation(IRelation relation, bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Parent object from a Relation as an <see cref="IUmbracoEntity"/>
|
||||
/// </summary>
|
||||
/// <param name="relation">Relation to retrieve parent object from</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c></param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetParentEntityFromRelation(IRelation relation, bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Parent and Child objects from a Relation as a <see cref="Tuple"/>"/> with <see cref="IUmbracoEntity"/>.
|
||||
/// </summary>
|
||||
/// <param name="relation">Relation to retrieve parent and child object from</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c></param>
|
||||
/// <returns>Returns a Tuple with Parent (item1) and Child (item2)</returns>
|
||||
Tuple<IUmbracoEntity, IUmbracoEntity> GetEntitiesFromRelation(IRelation relation, bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Child objects from a list of Relations as a list of <see cref="IUmbracoEntity"/> objects.
|
||||
/// </summary>
|
||||
/// <param name="relations">List of relations to retrieve child objects from</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c></param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/></returns>
|
||||
IEnumerable<IUmbracoEntity> GetChildEntitiesFromRelations(IEnumerable<IRelation> relations, bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Parent objects from a list of Relations as a list of <see cref="IUmbracoEntity"/> objects.
|
||||
/// </summary>
|
||||
/// <param name="relations">List of relations to retrieve parent objects from</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c></param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/></returns>
|
||||
IEnumerable<IUmbracoEntity> GetParentEntitiesFromRelations(IEnumerable<IRelation> relations,
|
||||
bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Parent and Child objects from a list of Relations as a list of <see cref="IUmbracoEntity"/> objects.
|
||||
/// </summary>
|
||||
/// <param name="relations">List of relations to retrieve parent and child objects from</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c></param>
|
||||
/// <returns>An enumerable list of <see cref="Tuple"/> with <see cref="IUmbracoEntity"/></returns>
|
||||
IEnumerable<Tuple<IUmbracoEntity, IUmbracoEntity>> GetEntitiesFromRelations(
|
||||
IEnumerable<IRelation> relations,
|
||||
bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Relates two objects by their entity Ids.
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the parent</param>
|
||||
/// <param name="childId">Id of the child</param>
|
||||
/// <param name="relationType">The type of relation to create</param>
|
||||
/// <returns>The created <see cref="Relation"/></returns>
|
||||
IRelation Relate(int parentId, int childId, IRelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Relates two objects that are based on the <see cref="IUmbracoEntity"/> interface.
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent entity</param>
|
||||
/// <param name="child">Child entity</param>
|
||||
/// <param name="relationType">The type of relation to create</param>
|
||||
/// <returns>The created <see cref="Relation"/></returns>
|
||||
IRelation Relate(IUmbracoEntity parent, IUmbracoEntity child, IRelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Relates two objects by their entity Ids.
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the parent</param>
|
||||
/// <param name="childId">Id of the child</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to create</param>
|
||||
/// <returns>The created <see cref="Relation"/></returns>
|
||||
IRelation Relate(int parentId, int childId, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Relates two objects that are based on the <see cref="IUmbracoEntity"/> interface.
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent entity</param>
|
||||
/// <param name="child">Child entity</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to create</param>
|
||||
/// <returns>The created <see cref="Relation"/></returns>
|
||||
IRelation Relate(IUmbracoEntity parent, IUmbracoEntity child, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether any relations exists for the passed in <see cref="RelationType"/>.
|
||||
/// </summary>
|
||||
/// <param name="relationType"><see cref="RelationType"/> to check for relations</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exists for the given <see cref="RelationType"/>, otherwise <c>False</c></returns>
|
||||
bool HasRelations(IRelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether any relations exists for the passed in Id.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of an object to check relations for</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exists with the given Id, otherwise <c>False</c></returns>
|
||||
bool IsRelated(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether two items are related
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the Parent relation</param>
|
||||
/// <param name="childId">Id of the Child relation</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exists with the given Ids, otherwise <c>False</c></returns>
|
||||
bool AreRelated(int parentId, int childId);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether two items are related
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent entity</param>
|
||||
/// <param name="child">Child entity</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exist between the entities, otherwise <c>False</c></returns>
|
||||
bool AreRelated(IUmbracoEntity parent, IUmbracoEntity child);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether two items are related
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent entity</param>
|
||||
/// <param name="child">Child entity</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to create</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exist between the entities, otherwise <c>False</c></returns>
|
||||
bool AreRelated(IUmbracoEntity parent, IUmbracoEntity child, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether two items are related
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the Parent relation</param>
|
||||
/// <param name="childId">Id of the Child relation</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to create</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exist between the entities, otherwise <c>False</c></returns>
|
||||
bool AreRelated(int parentId, int childId, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a <see cref="Relation"/>
|
||||
/// </summary>
|
||||
/// <param name="relation">Relation to save</param>
|
||||
void Save(IRelation relation);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationType">RelationType to Save</param>
|
||||
void Save(IRelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a <see cref="Relation"/>
|
||||
/// </summary>
|
||||
/// <param name="relation">Relation to Delete</param>
|
||||
void Delete(IRelation relation);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationType">RelationType to Delete</param>
|
||||
void Delete(IRelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all <see cref="Relation"/> objects based on the passed in <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationType"><see cref="RelationType"/> to Delete Relations for</param>
|
||||
void DeleteRelationsOfType(IRelationType relationType);
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
public interface IRelationService : IService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a <see cref="Relation"/> by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="Relation"/></param>
|
||||
/// <returns>A <see cref="Relation"/> object</returns>
|
||||
IRelation GetById(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="RelationType"/> by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="RelationType"/></param>
|
||||
/// <returns>A <see cref="RelationType"/> object</returns>
|
||||
IRelationType GetRelationTypeById(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="RelationType"/> by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="RelationType"/></param>
|
||||
/// <returns>A <see cref="RelationType"/> object</returns>
|
||||
IRelationType GetRelationTypeById(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="RelationType"/> by its Alias
|
||||
/// </summary>
|
||||
/// <param name="alias">Alias of the <see cref="RelationType"/></param>
|
||||
/// <returns>A <see cref="RelationType"/> object</returns>
|
||||
IRelationType GetRelationTypeByAlias(string alias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all <see cref="Relation"/> objects
|
||||
/// </summary>
|
||||
/// <param name="ids">Optional array of integer ids to return relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetAllRelations(params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all <see cref="Relation"/> objects by their <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationType"><see cref="RelationType"/> to retrieve Relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetAllRelationsByRelationType(RelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all <see cref="Relation"/> objects by their <see cref="RelationType"/>'s Id
|
||||
/// </summary>
|
||||
/// <param name="relationTypeId">Id of the <see cref="RelationType"/> to retrieve Relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetAllRelationsByRelationType(int relationTypeId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all <see cref="Relation"/> objects
|
||||
/// </summary>
|
||||
/// <param name="ids">Optional array of integer ids to return relationtypes for</param>
|
||||
/// <returns>An enumerable list of <see cref="RelationType"/> objects</returns>
|
||||
IEnumerable<IRelationType> GetAllRelationTypes(params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their parent Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the parent to retrieve relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByParentId(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their parent entity
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent Entity to retrieve relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByParent(IUmbracoEntity parent);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their parent entity
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent Entity to retrieve relations for</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to retrieve</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByParent(IUmbracoEntity parent, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their child Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the child to retrieve relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByChildId(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their child Entity
|
||||
/// </summary>
|
||||
/// <param name="child">Child Entity to retrieve relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByChild(IUmbracoEntity child);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their child Entity
|
||||
/// </summary>
|
||||
/// <param name="child">Child Entity to retrieve relations for</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to retrieve</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByChild(IUmbracoEntity child, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by their child or parent Id.
|
||||
/// Using this method will get you all relations regards of it being a child or parent relation.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the child or parent to retrieve relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByParentOrChildId(int id);
|
||||
|
||||
IEnumerable<IRelation> GetByParentOrChildId(int id, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by the Name of the <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationTypeName">Name of the <see cref="RelationType"/> to retrieve Relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByRelationTypeName(string relationTypeName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by the Alias of the <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationTypeAlias">Alias of the <see cref="RelationType"/> to retrieve Relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByRelationTypeAlias(string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="Relation"/> objects by the Id of the <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationTypeId">Id of the <see cref="RelationType"/> to retrieve Relations for</param>
|
||||
/// <returns>An enumerable list of <see cref="Relation"/> objects</returns>
|
||||
IEnumerable<IRelation> GetByRelationTypeId(int relationTypeId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Child object from a Relation as an <see cref="IUmbracoEntity"/>
|
||||
/// </summary>
|
||||
/// <param name="relation">Relation to retrieve child object from</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetChildEntityFromRelation(IRelation relation);
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IUmbracoEntity GetChildEntityFromRelation(IRelation relation, bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Parent object from a Relation as an <see cref="IUmbracoEntity"/>
|
||||
/// </summary>
|
||||
/// <param name="relation">Relation to retrieve parent object from</param>
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
IUmbracoEntity GetParentEntityFromRelation(IRelation relation);
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IUmbracoEntity GetParentEntityFromRelation(IRelation relation, bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Parent and Child objects from a Relation as a <see cref="Tuple"/>"/> with <see cref="IUmbracoEntity"/>.
|
||||
/// </summary>
|
||||
/// <param name="relation">Relation to retrieve parent and child object from</param>
|
||||
/// <returns>Returns a Tuple with Parent (item1) and Child (item2)</returns>
|
||||
Tuple<IUmbracoEntity, IUmbracoEntity> GetEntitiesFromRelation(IRelation relation);
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
Tuple<IUmbracoEntity, IUmbracoEntity> GetEntitiesFromRelation(IRelation relation, bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Child objects from a list of Relations as a list of <see cref="IUmbracoEntity"/> objects.
|
||||
/// </summary>
|
||||
/// <param name="relations">List of relations to retrieve child objects from</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/></returns>
|
||||
IEnumerable<IUmbracoEntity> GetChildEntitiesFromRelations(IEnumerable<IRelation> relations);
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IEnumerable<IUmbracoEntity> GetChildEntitiesFromRelations(IEnumerable<IRelation> relations, bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Parent objects from a list of Relations as a list of <see cref="IUmbracoEntity"/> objects.
|
||||
/// </summary>
|
||||
/// <param name="relations">List of relations to retrieve parent objects from</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/></returns>
|
||||
IEnumerable<IUmbracoEntity> GetParentEntitiesFromRelations(IEnumerable<IRelation> relations);
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IEnumerable<IUmbracoEntity> GetParentEntitiesFromRelations(IEnumerable<IRelation> relations, bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Parent and Child objects from a list of Relations as a list of <see cref="IUmbracoEntity"/> objects.
|
||||
/// </summary>
|
||||
/// <param name="relations">List of relations to retrieve parent and child objects from</param>
|
||||
/// <param name="loadBaseType">Optional bool to load the complete object graph when set to <c>False</c></param>
|
||||
IEnumerable<Tuple<IUmbracoEntity, IUmbracoEntity>> GetEntitiesFromRelations(
|
||||
IEnumerable<IRelation> relations);
|
||||
|
||||
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IEnumerable<Tuple<IUmbracoEntity, IUmbracoEntity>> GetEntitiesFromRelations(
|
||||
IEnumerable<IRelation> relations,
|
||||
bool loadBaseType = false);
|
||||
|
||||
/// <summary>
|
||||
/// Relates two objects by their entity Ids.
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the parent</param>
|
||||
/// <param name="childId">Id of the child</param>
|
||||
/// <param name="relationType">The type of relation to create</param>
|
||||
/// <returns>The created <see cref="Relation"/></returns>
|
||||
IRelation Relate(int parentId, int childId, IRelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Relates two objects that are based on the <see cref="IUmbracoEntity"/> interface.
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent entity</param>
|
||||
/// <param name="child">Child entity</param>
|
||||
/// <param name="relationType">The type of relation to create</param>
|
||||
/// <returns>The created <see cref="Relation"/></returns>
|
||||
IRelation Relate(IUmbracoEntity parent, IUmbracoEntity child, IRelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Relates two objects by their entity Ids.
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the parent</param>
|
||||
/// <param name="childId">Id of the child</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to create</param>
|
||||
/// <returns>The created <see cref="Relation"/></returns>
|
||||
IRelation Relate(int parentId, int childId, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Relates two objects that are based on the <see cref="IUmbracoEntity"/> interface.
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent entity</param>
|
||||
/// <param name="child">Child entity</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to create</param>
|
||||
/// <returns>The created <see cref="Relation"/></returns>
|
||||
IRelation Relate(IUmbracoEntity parent, IUmbracoEntity child, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether any relations exists for the passed in <see cref="RelationType"/>.
|
||||
/// </summary>
|
||||
/// <param name="relationType"><see cref="RelationType"/> to check for relations</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exists for the given <see cref="RelationType"/>, otherwise <c>False</c></returns>
|
||||
bool HasRelations(IRelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether any relations exists for the passed in Id.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of an object to check relations for</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exists with the given Id, otherwise <c>False</c></returns>
|
||||
bool IsRelated(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether two items are related
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the Parent relation</param>
|
||||
/// <param name="childId">Id of the Child relation</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exists with the given Ids, otherwise <c>False</c></returns>
|
||||
bool AreRelated(int parentId, int childId);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether two items are related
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent entity</param>
|
||||
/// <param name="child">Child entity</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exist between the entities, otherwise <c>False</c></returns>
|
||||
bool AreRelated(IUmbracoEntity parent, IUmbracoEntity child);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether two items are related
|
||||
/// </summary>
|
||||
/// <param name="parent">Parent entity</param>
|
||||
/// <param name="child">Child entity</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to create</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exist between the entities, otherwise <c>False</c></returns>
|
||||
bool AreRelated(IUmbracoEntity parent, IUmbracoEntity child, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether two items are related
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the Parent relation</param>
|
||||
/// <param name="childId">Id of the Child relation</param>
|
||||
/// <param name="relationTypeAlias">Alias of the type of relation to create</param>
|
||||
/// <returns>Returns <c>True</c> if any relations exist between the entities, otherwise <c>False</c></returns>
|
||||
bool AreRelated(int parentId, int childId, string relationTypeAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a <see cref="Relation"/>
|
||||
/// </summary>
|
||||
/// <param name="relation">Relation to save</param>
|
||||
void Save(IRelation relation);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationType">RelationType to Save</param>
|
||||
void Save(IRelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a <see cref="Relation"/>
|
||||
/// </summary>
|
||||
/// <param name="relation">Relation to Delete</param>
|
||||
void Delete(IRelation relation);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationType">RelationType to Delete</param>
|
||||
void Delete(IRelationType relationType);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all <see cref="Relation"/> objects based on the passed in <see cref="RelationType"/>
|
||||
/// </summary>
|
||||
/// <param name="relationType"><see cref="RelationType"/> to Delete Relations for</param>
|
||||
void DeleteRelationsOfType(IRelationType relationType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,40 +124,52 @@ namespace Umbraco.Core.Services
|
||||
var notifications = GetUsersNotifications(users.Select(x => x.Id), action, Enumerable.Empty<int>(), Constants.ObjectTypes.DocumentGuid).ToList();
|
||||
if (notifications.Count == 0) break;
|
||||
|
||||
var i = 0;
|
||||
foreach (var user in users)
|
||||
{
|
||||
// continue if there's no notification for this user
|
||||
if (notifications[i].UserId != user.Id) continue; // next user
|
||||
|
||||
for (var j = 0; j < entitiesL.Count; j++)
|
||||
{
|
||||
var content = entitiesL[j];
|
||||
var path = paths[j];
|
||||
|
||||
// test if the notification applies to the path ie to this entity
|
||||
if (path.Contains(notifications[i].EntityId) == false) continue; // next entity
|
||||
|
||||
if (prevVersionDictionary.ContainsKey(content.Id) == false)
|
||||
{
|
||||
prevVersionDictionary[content.Id] = GetPreviousVersion(content.Id);
|
||||
}
|
||||
|
||||
// queue notification
|
||||
var req = CreateNotificationRequest(operatingUser, user, content, prevVersionDictionary[content.Id], actionName, http, createSubject, createBody);
|
||||
Enqueue(req);
|
||||
}
|
||||
|
||||
// skip other notifications for this user, essentially this means moving i to the next index of notifications
|
||||
// for the next user.
|
||||
do
|
||||
{
|
||||
i++;
|
||||
} while (i < notifications.Count && notifications[i].UserId == user.Id);
|
||||
|
||||
if (i >= notifications.Count) break; // break if no more notifications
|
||||
}
|
||||
while (notifications.Count > 0)
|
||||
{
|
||||
var notification = notifications[0];
|
||||
var isMatched = false;
|
||||
|
||||
// grab user whose associated to the notification
|
||||
var user = users.Where(x => x.Id == notification.UserId).FirstOrDefault();
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
notifications.RemoveAll(x => x.UserId == notification.UserId);
|
||||
}
|
||||
|
||||
for (var j = 0; j < entitiesL.Count; j++)
|
||||
{
|
||||
var content = entitiesL[j];
|
||||
var path = paths[j];
|
||||
|
||||
// test if the notification applies to the path ie to this entity
|
||||
if (path.Contains(notification.EntityId) == false) continue; // next entity
|
||||
|
||||
isMatched = true;
|
||||
|
||||
if (prevVersionDictionary.ContainsKey(content.Id) == false)
|
||||
{
|
||||
prevVersionDictionary[content.Id] = GetPreviousVersion(content.Id);
|
||||
}
|
||||
|
||||
// queue notification
|
||||
var req = CreateNotificationRequest(operatingUser, user, content, prevVersionDictionary[content.Id], actionName, http, createSubject, createBody);
|
||||
Enqueue(req);
|
||||
|
||||
// don't process any further entities as a notification has been sent
|
||||
break;
|
||||
}
|
||||
|
||||
// when a match has been found, skip other notifications for user.
|
||||
if (isMatched)
|
||||
{
|
||||
notifications.RemoveAll(x => x.UserId == notification.UserId);
|
||||
continue;
|
||||
}
|
||||
|
||||
notifications.Remove(notification);
|
||||
}
|
||||
|
||||
// load more users if any
|
||||
id = users.Count == pagesz ? users.Last().Id + 1 : -1;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -324,6 +324,9 @@
|
||||
<Compile Include="Configuration\UmbracoSettings\WebRoutingElement.cs" />
|
||||
<Compile Include="Configuration\UmbracoVersion.cs" />
|
||||
<Compile Include="Attempt.cs" />
|
||||
<Compile Include="Constants-DataTypes.cs">
|
||||
<DependentUpon>Constants.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Constants-DeploySelector.cs" />
|
||||
<Compile Include="Constants-Examine.cs" />
|
||||
<Compile Include="Constants-Icons.cs" />
|
||||
@@ -374,6 +377,7 @@
|
||||
<Compile Include="Models\Consent.cs" />
|
||||
<Compile Include="Models\ConsentExtensions.cs" />
|
||||
<Compile Include="Models\ConsentState.cs" />
|
||||
<Compile Include="Models\DataTypeExtensions.cs" />
|
||||
<Compile Include="Models\EntityBase\EntityPath.cs" />
|
||||
<Compile Include="Models\EntityBase\IDeletableEntity.cs" />
|
||||
<Compile Include="Models\IAuditEntry.cs" />
|
||||
@@ -764,6 +768,7 @@
|
||||
<Compile Include="Services\ConsentService.cs" />
|
||||
<Compile Include="Services\ContentTypeServiceExtensions.cs" />
|
||||
<Compile Include="Models\RedirectUrl.cs" />
|
||||
<Compile Include="Services\DateTypeServiceExtensions.cs" />
|
||||
<Compile Include="Services\IConsentService.cs" />
|
||||
<Compile Include="Services\IContentServiceBase.cs" />
|
||||
<Compile Include="Services\IdkMap.cs" />
|
||||
|
||||
@@ -177,18 +177,7 @@ namespace Umbraco.Tests.Models
|
||||
};
|
||||
item.AdditionalData.Add("test1", 3);
|
||||
item.AdditionalData.Add("test2", "valuie");
|
||||
|
||||
item.AdditionalData.Add("test3", new UmbracoEntity.EntityProperty()
|
||||
{
|
||||
Value = "test",
|
||||
PropertyEditorAlias = "TestPropertyEditor"
|
||||
});
|
||||
item.AdditionalData.Add("test4", new UmbracoEntity.EntityProperty()
|
||||
{
|
||||
Value = "test2",
|
||||
PropertyEditorAlias = "TestPropertyEditor2"
|
||||
});
|
||||
|
||||
|
||||
var clone = (UmbracoEntity)item.DeepClone();
|
||||
|
||||
Assert.AreNotSame(clone, item);
|
||||
@@ -250,20 +239,10 @@ namespace Umbraco.Tests.Models
|
||||
};
|
||||
item.AdditionalData.Add("test1", 3);
|
||||
item.AdditionalData.Add("test2", "valuie");
|
||||
item.AdditionalData.Add("test3", new UmbracoEntity.EntityProperty()
|
||||
{
|
||||
Value = "test",
|
||||
PropertyEditorAlias = "TestPropertyEditor"
|
||||
});
|
||||
item.AdditionalData.Add("test4", new UmbracoEntity.EntityProperty()
|
||||
{
|
||||
Value = "test2",
|
||||
PropertyEditorAlias = "TestPropertyEditor2"
|
||||
});
|
||||
|
||||
|
||||
var result = ss.ToStream(item);
|
||||
var json = result.ResultStream.ToJsonString();
|
||||
Debug.Print(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ AnotherContentFinder
|
||||
public void Resolves_RestExtensions()
|
||||
{
|
||||
var types = _manager.ResolveRestExtensions();
|
||||
Assert.AreEqual(3, types.Count());
|
||||
Assert.AreEqual(2, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -398,6 +398,7 @@
|
||||
<Compile Include="Models\ContentExtensionsTests.cs" />
|
||||
<Compile Include="Models\UserExtensionsTests.cs" />
|
||||
<Compile Include="Web\Mvc\MergeParentContextViewDataAttributeTests.cs" />
|
||||
<Compile Include="Web\Mvc\ValidateUmbracoFormRouteStringAttributeTests.cs" />
|
||||
<Compile Include="Web\Mvc\ViewDataDictionaryExtensionTests.cs" />
|
||||
<Compile Include="Persistence\PetaPocoExtensionsTest.cs" />
|
||||
<Compile Include="Persistence\Querying\ContentTypeSqlMappingTests.cs" />
|
||||
|
||||
@@ -4,7 +4,8 @@ using Umbraco.Web;
|
||||
|
||||
namespace Umbraco.Tests.Web.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
|
||||
[TestFixture]
|
||||
public class HtmlHelperExtensionMethodsTests
|
||||
{
|
||||
[SetUp]
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Tests.Web.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class ValidateUmbracoFormRouteStringAttributeTests
|
||||
{
|
||||
[Test]
|
||||
public void Validate_Route_String()
|
||||
{
|
||||
var attribute = new ValidateUmbracoFormRouteStringAttribute();
|
||||
|
||||
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(null, null, null, null));
|
||||
|
||||
const string ControllerName = "Test";
|
||||
const string ControllerAction = "Index";
|
||||
const string Area = "MyArea";
|
||||
var validUfprt = UmbracoHelper.CreateEncryptedRouteString(ControllerName, ControllerAction, Area);
|
||||
|
||||
var invalidUfprt = validUfprt + "z";
|
||||
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(invalidUfprt, null, null, null));
|
||||
|
||||
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, ControllerName, ControllerAction, "doesntMatch"));
|
||||
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, ControllerName, ControllerAction, null));
|
||||
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, ControllerName, "doesntMatch", Area));
|
||||
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, ControllerName, null, Area));
|
||||
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, "doesntMatch", ControllerAction, Area));
|
||||
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, null, ControllerAction, Area));
|
||||
|
||||
Assert.DoesNotThrow(() => attribute.ValidateRouteString(validUfprt, ControllerName, ControllerAction, Area));
|
||||
Assert.DoesNotThrow(() => attribute.ValidateRouteString(validUfprt, ControllerName.ToLowerInvariant(), ControllerAction.ToLowerInvariant(), Area.ToLowerInvariant()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -266,7 +266,11 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
treeService.syncTree({
|
||||
node: treeNode,
|
||||
path: path,
|
||||
forceReload: forceReload
|
||||
forceReload: forceReload,
|
||||
//when the tree node is expanding during sync tree, handle it and raise appropriate events
|
||||
treeNodeExpanded: function (args) {
|
||||
emitEvent("treeNodeExpanded", { tree: scope.tree, node: args.node, children: args.children });
|
||||
}
|
||||
}).then(function (data) {
|
||||
|
||||
if (activate === undefined || activate === true) {
|
||||
|
||||
+5
-5
@@ -12,7 +12,7 @@ function treeSearchBox(localizationService, searchService, $q) {
|
||||
searchFromName: "@",
|
||||
showSearch: "@",
|
||||
section: "@",
|
||||
ignoreUserStartNodes: "@",
|
||||
datatypeId: "@",
|
||||
hideSearchCallback: "=",
|
||||
searchCallback: "="
|
||||
},
|
||||
@@ -62,10 +62,10 @@ function treeSearchBox(localizationService, searchService, $q) {
|
||||
searchArgs["searchFrom"] = scope.searchFromId;
|
||||
}
|
||||
|
||||
//append ignoreUserStartNodes value if there is one
|
||||
if (scope.ignoreUserStartNodes) {
|
||||
searchArgs["ignoreUserStartNodes"] = scope.ignoreUserStartNodes;
|
||||
}
|
||||
//append dataTypeId value if there is one
|
||||
if (scope.datatypeId) {
|
||||
searchArgs["dataTypeId"] = scope.datatypeId;
|
||||
}
|
||||
|
||||
searcher(searchArgs).then(function (data) {
|
||||
scope.searchCallback(data);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,8 @@
|
||||
* @name umbraco.services.mediaHelper
|
||||
* @description A helper object used for dealing with media items
|
||||
**/
|
||||
function mediaHelper(umbRequestHelper) {
|
||||
|
||||
function mediaHelper(umbRequestHelper, $log) {
|
||||
|
||||
//container of fileresolvers
|
||||
var _mediaFileResolvers = {};
|
||||
|
||||
@@ -13,11 +13,11 @@ function mediaHelper(umbRequestHelper) {
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.mediaHelper#getImagePropertyValue
|
||||
* @methodOf umbraco.services.mediaHelper
|
||||
* @function
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Returns the file path associated with the media property if there is one
|
||||
*
|
||||
*
|
||||
* @param {object} options Options object
|
||||
* @param {object} options.mediaModel The media object to retrieve the image path from
|
||||
* @param {object} options.imageOnly Optional, if true then will only return a path if the media item is an image
|
||||
@@ -75,16 +75,16 @@ function mediaHelper(umbRequestHelper) {
|
||||
|
||||
return "";
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.mediaHelper#getImagePropertyValue
|
||||
* @methodOf umbraco.services.mediaHelper
|
||||
* @function
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Returns the actual image path associated with the image property if there is one
|
||||
*
|
||||
*
|
||||
* @param {object} options Options object
|
||||
* @param {object} options.imageModel The media object to retrieve the image path from
|
||||
*/
|
||||
@@ -104,11 +104,11 @@ function mediaHelper(umbRequestHelper) {
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.mediaHelper#getThumbnail
|
||||
* @methodOf umbraco.services.mediaHelper
|
||||
* @function
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* formats the display model used to display the content to the model used to save the content
|
||||
*
|
||||
*
|
||||
* @param {object} options Options object
|
||||
* @param {object} options.imageModel The media object to retrieve the image path from
|
||||
*/
|
||||
@@ -133,54 +133,50 @@ function mediaHelper(umbRequestHelper) {
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.mediaHelper#resolveFileFromEntity
|
||||
* @methodOf umbraco.services.mediaHelper
|
||||
* @function
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Gets the media file url for a media entity returned with the entityResource
|
||||
*
|
||||
*
|
||||
* @param {object} mediaEntity A media Entity returned from the entityResource
|
||||
* @param {boolean} thumbnail Whether to return the thumbnail url or normal url
|
||||
*/
|
||||
resolveFileFromEntity : function(mediaEntity, thumbnail) {
|
||||
|
||||
if (!angular.isObject(mediaEntity.metaData)) {
|
||||
throw "Cannot resolve the file url from the mediaEntity, it does not contain the required metaData";
|
||||
resolveFileFromEntity: function (mediaEntity, thumbnail) {
|
||||
|
||||
if (!angular.isObject(mediaEntity.metaData) || !mediaEntity.metaData.MediaPath) {
|
||||
//don't throw since this image legitimately might not contain a media path, but output a warning
|
||||
$log.warn("Cannot resolve the file url from the mediaEntity, it does not contain the required metaData");
|
||||
return null;
|
||||
}
|
||||
|
||||
var values = _.values(mediaEntity.metaData);
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var val = values[i];
|
||||
if (angular.isObject(val) && val.PropertyEditorAlias) {
|
||||
for (var resolver in _mediaFileResolvers) {
|
||||
if (val.PropertyEditorAlias === resolver) {
|
||||
//we need to format a property variable that coincides with how the property would be structured
|
||||
// if it came from the mediaResource just to keep things slightly easier for the file resolvers.
|
||||
var property = { value: val.Value };
|
||||
|
||||
return _mediaFileResolvers[resolver](property, mediaEntity, thumbnail);
|
||||
}
|
||||
}
|
||||
if (thumbnail) {
|
||||
if (this.detectIfImageByExtension(mediaEntity.metaData.MediaPath)) {
|
||||
return this.getThumbnailFromPath(mediaEntity.metaData.MediaPath);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
else {
|
||||
return mediaEntity.metaData.MediaPath;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.mediaHelper#resolveFile
|
||||
* @methodOf umbraco.services.mediaHelper
|
||||
* @function
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Gets the media file url for a media object returned with the mediaResource
|
||||
*
|
||||
*
|
||||
* @param {object} mediaEntity A media Entity returned from the entityResource
|
||||
* @param {boolean} thumbnail Whether to return the thumbnail url or normal url
|
||||
*/
|
||||
/*jshint loopfunc: true */
|
||||
resolveFile : function(mediaItem, thumbnail){
|
||||
|
||||
|
||||
function iterateProps(props){
|
||||
var res = null;
|
||||
for(var resolver in _mediaFileResolvers) {
|
||||
@@ -191,7 +187,7 @@ function mediaHelper(umbRequestHelper) {
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
//we either have properties raw on the object, or spread out on tabs
|
||||
@@ -208,7 +204,7 @@ function mediaHelper(umbRequestHelper) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
},
|
||||
|
||||
/*jshint loopfunc: true */
|
||||
@@ -246,11 +242,11 @@ function mediaHelper(umbRequestHelper) {
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.mediaHelper#scaleToMaxSize
|
||||
* @methodOf umbraco.services.mediaHelper
|
||||
* @function
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Finds the corrct max width and max height, given maximum dimensions and keeping aspect ratios
|
||||
*
|
||||
*
|
||||
* @param {number} maxSize Maximum width & height
|
||||
* @param {number} width Current width
|
||||
* @param {number} height Current height
|
||||
@@ -289,11 +285,11 @@ function mediaHelper(umbRequestHelper) {
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.mediaHelper#getThumbnailFromPath
|
||||
* @methodOf umbraco.services.mediaHelper
|
||||
* @function
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Returns the path to the thumbnail version of a given media library image path
|
||||
*
|
||||
*
|
||||
* @param {string} imagePath Image path, ex: /media/1234/my-image.jpg
|
||||
*/
|
||||
getThumbnailFromPath: function (imagePath) {
|
||||
@@ -319,11 +315,11 @@ function mediaHelper(umbRequestHelper) {
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.mediaHelper#detectIfImageByExtension
|
||||
* @methodOf umbraco.services.mediaHelper
|
||||
* @function
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Returns true/false, indicating if the given path has an allowed image extension
|
||||
*
|
||||
*
|
||||
* @param {string} imagePath Image path, ex: /media/1234/my-image.jpg
|
||||
*/
|
||||
detectIfImageByExtension: function (imagePath) {
|
||||
@@ -331,7 +327,7 @@ function mediaHelper(umbRequestHelper) {
|
||||
if (!imagePath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var lowered = imagePath.toLowerCase();
|
||||
var ext = lowered.substr(lowered.lastIndexOf(".") + 1);
|
||||
return ("," + Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes + ",").indexOf("," + ext + ",") !== -1;
|
||||
@@ -388,6 +384,6 @@ function mediaHelper(umbRequestHelper) {
|
||||
var ext = lowered.substr(lowered.lastIndexOf(".") + 1);
|
||||
return ext;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}angular.module('umbraco.services').factory('mediaHelper', mediaHelper);
|
||||
|
||||
@@ -1,174 +1,160 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.searchService
|
||||
*
|
||||
*
|
||||
* @description
|
||||
* Service for handling the main application search, can currently search content, media and members
|
||||
*
|
||||
* ##usage
|
||||
* To use, simply inject the searchService into any controller that needs it, and make
|
||||
* sure the umbraco.services module is accesible - which it should be by default.
|
||||
*
|
||||
* <pre>
|
||||
* searchService.searchMembers({term: 'bob'}).then(function(results){
|
||||
* angular.forEach(results, function(result){
|
||||
* //returns:
|
||||
* {name: "name", id: 1234, menuUrl: "url", editorPath: "url", metaData: {}, subtitle: "/path/etc" }
|
||||
* })
|
||||
* var result =
|
||||
* })
|
||||
* </pre>
|
||||
*/
|
||||
angular.module('umbraco.services')
|
||||
.factory('searchService', function ($q, $log, entityResource, contentResource, umbRequestHelper, $injector, searchResultFormatter) {
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.searchService#searchMembers
|
||||
* @methodOf umbraco.services.searchService
|
||||
*
|
||||
* @description
|
||||
* Searches the default member search index
|
||||
* @param {Object} args argument object
|
||||
* @param {String} args.term seach term
|
||||
* @returns {Promise} returns promise containing all matching members
|
||||
*/
|
||||
searchMembers: function (args) {
|
||||
|
||||
if (!args.term) {
|
||||
throw "args.term is required";
|
||||
}
|
||||
|
||||
var options = {
|
||||
searchFrom: args.searchFrom
|
||||
}
|
||||
|
||||
return entityResource.search(args.term, "Member", options).then(function (data) {
|
||||
_.each(data, function (item) {
|
||||
searchResultFormatter.configureMemberResult(item);
|
||||
});
|
||||
return data;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.searchService#searchContent
|
||||
* @methodOf umbraco.services.searchService
|
||||
*
|
||||
* @description
|
||||
* Searches the default internal content search index
|
||||
* @param {Object} args argument object
|
||||
* @param {String} args.term seach term
|
||||
* @returns {Promise} returns promise containing all matching content items
|
||||
*/
|
||||
searchContent: function (args) {
|
||||
|
||||
if (!args.term) {
|
||||
throw "args.term is required";
|
||||
}
|
||||
|
||||
var options = {
|
||||
searchFrom: args.searchFrom,
|
||||
ignoreUserStartNodes: args.ignoreUserStartNodes
|
||||
}
|
||||
|
||||
return entityResource.search(args.term, "Document", options, args.canceler).then(function (data) {
|
||||
_.each(data, function (item) {
|
||||
searchResultFormatter.configureContentResult(item);
|
||||
});
|
||||
return data;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.searchService#searchMedia
|
||||
* @methodOf umbraco.services.searchService
|
||||
*
|
||||
* @description
|
||||
* Searches the default media search index
|
||||
* @param {Object} args argument object
|
||||
* @param {String} args.term seach term
|
||||
* @returns {Promise} returns promise containing all matching media items
|
||||
*/
|
||||
searchMedia: function (args) {
|
||||
|
||||
if (!args.term) {
|
||||
throw "args.term is required";
|
||||
}
|
||||
|
||||
var options = {
|
||||
searchFrom: args.searchFrom,
|
||||
ignoreUserStartNodes: args.ignoreUserStartNodes
|
||||
}
|
||||
|
||||
return entityResource.search(args.term, "Media", options).then(function (data) {
|
||||
_.each(data, function (item) {
|
||||
searchResultFormatter.configureMediaResult(item);
|
||||
});
|
||||
return data;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.searchService#searchAll
|
||||
* @methodOf umbraco.services.searchService
|
||||
*
|
||||
* @description
|
||||
* Searches all available indexes and returns all results in one collection
|
||||
* @param {Object} args argument object
|
||||
* @param {String} args.term seach term
|
||||
* @returns {Promise} returns promise containing all matching items
|
||||
*/
|
||||
searchAll: function (args) {
|
||||
|
||||
if (!args.term) {
|
||||
throw "args.term is required";
|
||||
}
|
||||
|
||||
return entityResource.searchAll(args.term, args.canceler).then(function (data) {
|
||||
|
||||
_.each(data, function (resultByType) {
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.searchService
|
||||
*
|
||||
*
|
||||
* @description
|
||||
* Service for handling the main application search, can currently search content, media and members
|
||||
*
|
||||
* ##usage
|
||||
* To use, simply inject the searchService into any controller that needs it, and make
|
||||
* sure the umbraco.services module is accesible - which it should be by default.
|
||||
*
|
||||
* <pre>
|
||||
* searchService.searchMembers({term: 'bob'}).then(function(results){
|
||||
* angular.forEach(results, function(result){
|
||||
* //returns:
|
||||
* {name: "name", id: 1234, menuUrl: "url", editorPath: "url", metaData: {}, subtitle: "/path/etc" }
|
||||
* })
|
||||
* var result =
|
||||
* })
|
||||
* </pre>
|
||||
*/
|
||||
angular.module('umbraco.services')
|
||||
.factory('searchService', function ($q, $log, entityResource, contentResource, umbRequestHelper, $injector, searchResultFormatter) {
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.searchService#searchMembers
|
||||
* @methodOf umbraco.services.searchService
|
||||
*
|
||||
* @description
|
||||
* Searches the default member search index
|
||||
* @param {Object} args argument object
|
||||
* @param {String} args.term seach term
|
||||
* @returns {Promise} returns promise containing all matching members
|
||||
*/
|
||||
searchMembers: function (args) {
|
||||
|
||||
if (!args.term) {
|
||||
throw "args.term is required";
|
||||
}
|
||||
|
||||
return entityResource.search(args.term, "Member", args.searchFrom).then(function (data) {
|
||||
_.each(data, function (item) {
|
||||
searchResultFormatter.configureMemberResult(item);
|
||||
});
|
||||
return data;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.searchService#searchContent
|
||||
* @methodOf umbraco.services.searchService
|
||||
*
|
||||
* @description
|
||||
* Searches the default internal content search index
|
||||
* @param {Object} args argument object
|
||||
* @param {String} args.term seach term
|
||||
* @returns {Promise} returns promise containing all matching content items
|
||||
*/
|
||||
searchContent: function (args) {
|
||||
|
||||
if (!args.term) {
|
||||
throw "args.term is required";
|
||||
}
|
||||
|
||||
return entityResource.search(args.term, "Document", args.searchFrom, args.canceler, args.dataTypeId).then(function (data) {
|
||||
_.each(data, function (item) {
|
||||
searchResultFormatter.configureContentResult(item);
|
||||
});
|
||||
return data;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.searchService#searchMedia
|
||||
* @methodOf umbraco.services.searchService
|
||||
*
|
||||
* @description
|
||||
* Searches the default media search index
|
||||
* @param {Object} args argument object
|
||||
* @param {String} args.term seach term
|
||||
* @returns {Promise} returns promise containing all matching media items
|
||||
*/
|
||||
searchMedia: function (args) {
|
||||
|
||||
if (!args.term) {
|
||||
throw "args.term is required";
|
||||
}
|
||||
|
||||
return entityResource.search(args.term, "Media", args.searchFrom, args.canceler, args.dataTypeId).then(function (data) {
|
||||
_.each(data, function (item) {
|
||||
searchResultFormatter.configureMediaResult(item);
|
||||
});
|
||||
return data;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.searchService#searchAll
|
||||
* @methodOf umbraco.services.searchService
|
||||
*
|
||||
* @description
|
||||
* Searches all available indexes and returns all results in one collection
|
||||
* @param {Object} args argument object
|
||||
* @param {String} args.term seach term
|
||||
* @returns {Promise} returns promise containing all matching items
|
||||
*/
|
||||
searchAll: function (args) {
|
||||
|
||||
if (!args.term) {
|
||||
throw "args.term is required";
|
||||
}
|
||||
|
||||
return entityResource.searchAll(args.term, args.canceler).then(function (data) {
|
||||
|
||||
_.each(data, function (resultByType) {
|
||||
|
||||
//we need to format the search result data to include things like the subtitle, urls, etc...
|
||||
// this is done with registered angular services as part of the SearchableTreeAttribute, if that
|
||||
// is not found, than we format with the default formatter
|
||||
// this is done with registered angular services as part of the SearchableTreeAttribute, if that
|
||||
// is not found, than we format with the default formatter
|
||||
var formatterMethod = searchResultFormatter.configureDefaultResult;
|
||||
//check if a custom formatter is specified...
|
||||
if (resultByType.jsSvc) {
|
||||
var searchFormatterService = $injector.get(resultByType.jsSvc);
|
||||
if (searchFormatterService) {
|
||||
if (!resultByType.jsMethod) {
|
||||
resultByType.jsMethod = "format";
|
||||
}
|
||||
formatterMethod = searchFormatterService[resultByType.jsMethod];
|
||||
|
||||
if (!formatterMethod) {
|
||||
throw "The method " + resultByType.jsMethod + " on the angular service " + resultByType.jsSvc + " could not be found";
|
||||
}
|
||||
}
|
||||
}
|
||||
//now apply the formatter for each result
|
||||
_.each(resultByType.results, function (item) {
|
||||
formatterMethod.apply(this, [item, resultByType.treeAlias, resultByType.appAlias]);
|
||||
if (resultByType.jsSvc) {
|
||||
var searchFormatterService = $injector.get(resultByType.jsSvc);
|
||||
if (searchFormatterService) {
|
||||
if (!resultByType.jsMethod) {
|
||||
resultByType.jsMethod = "format";
|
||||
}
|
||||
formatterMethod = searchFormatterService[resultByType.jsMethod];
|
||||
|
||||
if (!formatterMethod) {
|
||||
throw "The method " + resultByType.jsMethod + " on the angular service " + resultByType.jsSvc + " could not be found";
|
||||
}
|
||||
}
|
||||
}
|
||||
//now apply the formatter for each result
|
||||
_.each(resultByType.results, function (item) {
|
||||
formatterMethod.apply(this, [item, resultByType.treeAlias, resultByType.appAlias]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
//TODO: This doesn't do anything!
|
||||
setCurrent: function (sectionAlias) {
|
||||
|
||||
var currentSection = sectionAlias;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
//TODO: This doesn't do anything!
|
||||
setCurrent: function (sectionAlias) {
|
||||
|
||||
var currentSection = sectionAlias;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -759,7 +759,14 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
|
||||
}
|
||||
else {
|
||||
//couldn't find it in the
|
||||
self.loadNodeChildren({ node: node, section: node.section }).then(function () {
|
||||
self.loadNodeChildren({ node: node, section: node.section }).then(function (children) {
|
||||
|
||||
//we've reloaded a portion of the tree, call the callback if one is specified.
|
||||
//TODO: In v8, we can just use deferred.notify
|
||||
if (args.treeNodeExpanded && angular.isFunction(args.treeNodeExpanded)) {
|
||||
args.treeNodeExpanded({ node: node, children: children });
|
||||
}
|
||||
|
||||
//ok, got the children, let's find it
|
||||
var found = self.getChildNode(node, args.path[currPathIndex]);
|
||||
if (found) {
|
||||
@@ -796,4 +803,4 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
|
||||
};
|
||||
}
|
||||
|
||||
angular.module('umbraco.services').factory('treeService', treeService);
|
||||
angular.module('umbraco.services').factory('treeService', treeService);
|
||||
|
||||
@@ -327,27 +327,6 @@ li.root > div > a.umb-options {
|
||||
div.not-published > i.icon,div.not-published > a{
|
||||
opacity: 0.6;
|
||||
}
|
||||
div.protected:before{
|
||||
content:"\e256";
|
||||
font-family: 'icomoon';
|
||||
color: @red;
|
||||
position: absolute;
|
||||
font-size: 20px;
|
||||
padding-left: 7px;
|
||||
padding-top: 7px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
div.has-unpublished-version:before{
|
||||
content:"\e25a";
|
||||
font-family: 'icomoon';
|
||||
color: @green;
|
||||
position: absolute;
|
||||
font-size: 20px;
|
||||
padding-left: 7px;
|
||||
padding-top: 7px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
div.not-allowed > i.icon,div.not-allowed > a{
|
||||
cursor: not-allowed;
|
||||
@@ -380,6 +359,29 @@ div.locked:before{
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
div.has-unpublished-version:before {
|
||||
content: "\e25a";
|
||||
font-family: 'icomoon';
|
||||
color: @green;
|
||||
position: absolute;
|
||||
font-size: 20px;
|
||||
padding-left: 7px;
|
||||
padding-top: 7px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
div.protected:before {
|
||||
content: "\e256";
|
||||
font-family: 'icomoon';
|
||||
color: @red;
|
||||
position: absolute;
|
||||
font-size: 20px;
|
||||
padding-left: 7px;
|
||||
padding-top: 7px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.umb-tree li div.no-access .umb-tree-icon,
|
||||
.umb-tree li div.no-access .root-link,
|
||||
.umb-tree li div.no-access .umb-tree-item__label {
|
||||
|
||||
@@ -1,170 +1,171 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
|
||||
function ($scope, eventsService, dialogService, entityResource, contentResource, mediaHelper, userService, localizationService, tinyMceService) {
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
|
||||
var searchText = "Search...";
|
||||
localizationService.localize("general_search").then(function (value) {
|
||||
searchText = value + "...";
|
||||
});
|
||||
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.target = {};
|
||||
$scope.searchInfo = {
|
||||
searchFromId: null,
|
||||
searchFromName: null,
|
||||
showSearch: false,
|
||||
results: [],
|
||||
selectedSearchResults: []
|
||||
}
|
||||
|
||||
if (dialogOptions.currentTarget) {
|
||||
$scope.target = dialogOptions.currentTarget;
|
||||
|
||||
//if we have a node ID, we fetch the current node to build the form data
|
||||
if ($scope.target.id || $scope.target.udi) {
|
||||
|
||||
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id;
|
||||
|
||||
if (!$scope.target.path) {
|
||||
entityResource.getPath(id, "Document").then(function (path) {
|
||||
$scope.target.path = path;
|
||||
//now sync the tree to this path
|
||||
$scope.dialogTreeEventHandler.syncTree({
|
||||
path: $scope.target.path,
|
||||
tree: "content"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// if a link exists, get the properties to build the anchor name list
|
||||
contentResource.getById(id).then(function (resp) {
|
||||
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
|
||||
$scope.target.url = resp.urls[0];
|
||||
});
|
||||
} else if ($scope.target.url.length) {
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
|
||||
function ($scope, eventsService, dialogService, entityResource, mediaHelper, userService, localizationService, tinyMceService) {
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
|
||||
var searchText = "Search...";
|
||||
localizationService.localize("general_search").then(function (value) {
|
||||
searchText = value + "...";
|
||||
});
|
||||
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.target = {};
|
||||
$scope.searchInfo = {
|
||||
searchFromId: null,
|
||||
searchFromName: null,
|
||||
showSearch: false,
|
||||
dataTypeId: ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null,
|
||||
results: [],
|
||||
selectedSearchResults: []
|
||||
}
|
||||
|
||||
if (dialogOptions.currentTarget) {
|
||||
$scope.target = dialogOptions.currentTarget;
|
||||
|
||||
//if we have a node ID, we fetch the current node to build the form data
|
||||
if ($scope.target.id || $scope.target.udi) {
|
||||
|
||||
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id;
|
||||
|
||||
if (!$scope.target.path) {
|
||||
entityResource.getPath(id, "Document").then(function (path) {
|
||||
$scope.target.path = path;
|
||||
//now sync the tree to this path
|
||||
$scope.dialogTreeEventHandler.syncTree({
|
||||
path: $scope.target.path,
|
||||
tree: "content"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// if a link exists, get the properties to build the anchor name list
|
||||
entityResource.getUrlAndAnchors(id).then(function(resp){
|
||||
$scope.anchorValues = resp.anchorValues;
|
||||
$scope.target.url = resp.url;
|
||||
});
|
||||
} else if ($scope.target.url.length) {
|
||||
// a url but no id/udi indicates an external link - trim the url to remove the anchor/qs
|
||||
// only do the substring if there's a # or a ?
|
||||
var indexOfAnchor = $scope.target.url.search(/(#|\?)/);
|
||||
if (indexOfAnchor > -1) {
|
||||
// populate the anchor
|
||||
$scope.target.anchor = $scope.target.url.substring(indexOfAnchor);
|
||||
// then rewrite the model and populate the link
|
||||
if (indexOfAnchor > -1) {
|
||||
// populate the anchor
|
||||
$scope.target.anchor = $scope.target.url.substring(indexOfAnchor);
|
||||
// then rewrite the model and populate the link
|
||||
$scope.target.url = $scope.target.url.substring(0, indexOfAnchor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dialogOptions.anchors) {
|
||||
$scope.anchorValues = dialogOptions.anchors;
|
||||
}
|
||||
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if (args.node.metaData.listViewNode) {
|
||||
//check if list view 'search' node was selected
|
||||
|
||||
$scope.searchInfo.showSearch = true;
|
||||
$scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
||||
$scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
||||
} else {
|
||||
eventsService.emit("dialogs.linkPicker.select", args);
|
||||
|
||||
if ($scope.currentNode) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.currentNode.selected = false;
|
||||
}
|
||||
|
||||
$scope.currentNode = args.node;
|
||||
$scope.currentNode.selected = true;
|
||||
$scope.target.id = args.node.id;
|
||||
$scope.target.udi = args.node.udi;
|
||||
$scope.target.name = args.node.name;
|
||||
|
||||
if (args.node.id < 0) {
|
||||
$scope.target.url = "/";
|
||||
} else {
|
||||
contentResource.getById(args.node.id).then(function (resp) {
|
||||
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
|
||||
$scope.target.url = resp.urls[0];
|
||||
});
|
||||
}
|
||||
|
||||
if (!angular.isUndefined($scope.target.isMedia)) {
|
||||
delete $scope.target.isMedia;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nodeExpandedHandler(ev, args) {
|
||||
if (angular.isArray(args.children)) {
|
||||
|
||||
//iterate children
|
||||
_.each(args.children, function (child) {
|
||||
//check if any of the items are list views, if so we need to add a custom
|
||||
// child: A node to activate the search
|
||||
if (child.metaData.isContainer) {
|
||||
child.hasChildren = true;
|
||||
child.children = [
|
||||
{
|
||||
level: child.level + 1,
|
||||
hasChildren: false,
|
||||
name: searchText,
|
||||
metaData: {
|
||||
listViewNode: child
|
||||
},
|
||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
||||
cssClasses: ["not-published"]
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$scope.switchToMediaPicker = function () {
|
||||
userService.getCurrentUser().then(function (userData) {
|
||||
dialogService.mediaPicker({
|
||||
startNodeId: userData.startMediaIds.length == 0 ? -1 : userData.startMediaIds[0],
|
||||
callback: function (media) {
|
||||
$scope.target.id = media.id;
|
||||
$scope.target.isMedia = true;
|
||||
$scope.target.name = media.name;
|
||||
$scope.target.url = mediaHelper.resolveFile(media);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.hideSearch = function () {
|
||||
$scope.searchInfo.showSearch = false;
|
||||
$scope.searchInfo.searchFromId = null;
|
||||
$scope.searchInfo.searchFromName = null;
|
||||
$scope.searchInfo.results = [];
|
||||
}
|
||||
|
||||
// method to select a search result
|
||||
$scope.selectResult = function (evt, result) {
|
||||
result.selected = result.selected === true ? false : true;
|
||||
nodeSelectHandler(evt, {
|
||||
event: evt,
|
||||
node: result
|
||||
});
|
||||
};
|
||||
|
||||
//callback when there are search results
|
||||
$scope.onSearchResults = function (results) {
|
||||
$scope.searchInfo.results = results;
|
||||
$scope.searchInfo.showSearch = true;
|
||||
};
|
||||
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler);
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeExpanded", nodeExpandedHandler);
|
||||
|
||||
$scope.$on('$destroy', function () {
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dialogOptions.anchors) {
|
||||
$scope.anchorValues = dialogOptions.anchors;
|
||||
}
|
||||
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if (args.node.metaData.listViewNode) {
|
||||
//check if list view 'search' node was selected
|
||||
|
||||
$scope.searchInfo.showSearch = true;
|
||||
$scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
||||
$scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
||||
} else {
|
||||
eventsService.emit("dialogs.linkPicker.select", args);
|
||||
|
||||
if ($scope.currentNode) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.currentNode.selected = false;
|
||||
}
|
||||
|
||||
$scope.currentNode = args.node;
|
||||
$scope.currentNode.selected = true;
|
||||
$scope.target.id = args.node.id;
|
||||
$scope.target.udi = args.node.udi;
|
||||
$scope.target.name = args.node.name;
|
||||
|
||||
if (args.node.id < 0) {
|
||||
$scope.target.url = "/";
|
||||
} else {
|
||||
entityResource.getUrlAndAnchors(args.node.id).then(function(resp){
|
||||
$scope.anchorValues = resp.anchorValues;
|
||||
$scope.target.url = resp.url;
|
||||
});
|
||||
}
|
||||
|
||||
if (!angular.isUndefined($scope.target.isMedia)) {
|
||||
delete $scope.target.isMedia;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nodeExpandedHandler(ev, args) {
|
||||
if (angular.isArray(args.children)) {
|
||||
|
||||
//iterate children
|
||||
_.each(args.children, function (child) {
|
||||
//check if any of the items are list views, if so we need to add a custom
|
||||
// child: A node to activate the search
|
||||
if (child.metaData.isContainer) {
|
||||
child.hasChildren = true;
|
||||
child.children = [
|
||||
{
|
||||
level: child.level + 1,
|
||||
hasChildren: false,
|
||||
name: searchText,
|
||||
metaData: {
|
||||
listViewNode: child
|
||||
},
|
||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
||||
cssClasses: ["not-published"]
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$scope.switchToMediaPicker = function () {
|
||||
userService.getCurrentUser().then(function (userData) {
|
||||
dialogService.mediaPicker({
|
||||
startNodeId: userData.startMediaIds.length == 0 ? -1 : userData.startMediaIds[0],
|
||||
callback: function (media) {
|
||||
$scope.target.id = media.id;
|
||||
$scope.target.isMedia = true;
|
||||
$scope.target.name = media.name;
|
||||
$scope.target.url = media.image;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.hideSearch = function () {
|
||||
$scope.searchInfo.showSearch = false;
|
||||
$scope.searchInfo.searchFromId = null;
|
||||
$scope.searchInfo.searchFromName = null;
|
||||
$scope.searchInfo.results = [];
|
||||
}
|
||||
|
||||
// method to select a search result
|
||||
$scope.selectResult = function (evt, result) {
|
||||
result.selected = result.selected === true ? false : true;
|
||||
nodeSelectHandler(evt, {
|
||||
event: evt,
|
||||
node: result
|
||||
});
|
||||
};
|
||||
|
||||
//callback when there are search results
|
||||
$scope.onSearchResults = function (results) {
|
||||
$scope.searchInfo.results = results;
|
||||
$scope.searchInfo.showSearch = true;
|
||||
};
|
||||
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler);
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeExpanded", nodeExpandedHandler);
|
||||
|
||||
$scope.$on('$destroy', function () {
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,86 +1,87 @@
|
||||
<div class="umb-panel" ng-controller="Umbraco.Dialogs.LinkPickerController">
|
||||
<div class="umb-panel-body no-header with-footer compact">
|
||||
<umb-pane>
|
||||
<umb-control-group label="@defaultdialogs_urlLinkPicker" class="umb-property--pull">
|
||||
<input type="text"
|
||||
localize="placeholder"
|
||||
placeholder="@general_url"
|
||||
class="umb-editor umb-textstring"
|
||||
ng-model="target.url"
|
||||
ng-disabled="target.id || target.udi" />
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="@defaultdialogs_anchorLinkPicker" class="umb-property--push">
|
||||
<input type="text"
|
||||
list="anchors"
|
||||
localize="placeholder"
|
||||
placeholder="@placeholders_anchor"
|
||||
class="umb-editor umb-textstring"
|
||||
ng-model="target.anchor" />
|
||||
|
||||
<datalist id="anchors">
|
||||
<option value="{{a}}" ng-repeat="a in anchorValues"></option>
|
||||
</datalist>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="@defaultdialogs_nodeNameLinkPicker">
|
||||
<input type="text"
|
||||
localize="placeholder"
|
||||
placeholder="@placeholders_entername"
|
||||
class="umb-editor umb-textstring"
|
||||
ng-model="target.name" />
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="@content_target">
|
||||
<select class="umb-editor umb-dropdown" ng-model="target.target">
|
||||
<option value=""></option>
|
||||
<option value="_blank"><localize key="defaultdialogs_openInNewWindow">Opens the linked document in a new window or tab</localize></option>
|
||||
</select>
|
||||
</umb-control-group>
|
||||
</umb-pane>
|
||||
|
||||
<umb-tree-search-box hide-search-callback="hideSearch"
|
||||
search-callback="onSearchResults"
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
section="{{section}}">
|
||||
</umb-tree-search-box>
|
||||
|
||||
<br/>
|
||||
|
||||
<umb-tree-search-results ng-if="searchInfo.showSearch"
|
||||
results="searchInfo.results"
|
||||
select-result-callback="selectResult">
|
||||
</umb-tree-search-results>
|
||||
|
||||
<div ng-hide="searchInfo.showSearch">
|
||||
<umb-tree section="content"
|
||||
hideheader="true"
|
||||
hideoptions="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
isdialog="true"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-panel-footer">
|
||||
<div class="umb-el-wrap umb-panel-buttons">
|
||||
<div class="btn-toolbar umb-btn-toolbar pull-right">
|
||||
<a href ng-click="close()" class="btn btn-link">
|
||||
<localize key="general_cancel">Cancel</localize>
|
||||
</a>
|
||||
<a href ng-click="switchToMediaPicker()" class="btn">
|
||||
<localize key="defaultdialogs_selectMedia">Select media</localize>
|
||||
</a>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
ng-click="submit(target)">
|
||||
<localize key="buttons_select">Select</localize>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="umb-panel" ng-controller="Umbraco.Dialogs.LinkPickerController">
|
||||
<div class="umb-panel-body no-header with-footer compact">
|
||||
<umb-pane>
|
||||
<umb-control-group label="@defaultdialogs_urlLinkPicker" class="umb-property--pull">
|
||||
<input type="text"
|
||||
localize="placeholder"
|
||||
placeholder="@general_url"
|
||||
class="umb-editor umb-textstring"
|
||||
ng-model="target.url"
|
||||
ng-disabled="target.id || target.udi" />
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="@defaultdialogs_anchorLinkPicker" class="umb-property--push">
|
||||
<input type="text"
|
||||
list="anchors"
|
||||
localize="placeholder"
|
||||
placeholder="@placeholders_anchor"
|
||||
class="umb-editor umb-textstring"
|
||||
ng-model="target.anchor" />
|
||||
|
||||
<datalist id="anchors">
|
||||
<option value="{{a}}" ng-repeat="a in anchorValues"></option>
|
||||
</datalist>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="@defaultdialogs_nodeNameLinkPicker">
|
||||
<input type="text"
|
||||
localize="placeholder"
|
||||
placeholder="@placeholders_entername"
|
||||
class="umb-editor umb-textstring"
|
||||
ng-model="target.name" />
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="@content_target">
|
||||
<select class="umb-editor umb-dropdown" ng-model="target.target">
|
||||
<option value=""></option>
|
||||
<option value="_blank"><localize key="defaultdialogs_openInNewWindow">Opens the linked document in a new window or tab</localize></option>
|
||||
</select>
|
||||
</umb-control-group>
|
||||
</umb-pane>
|
||||
|
||||
<umb-tree-search-box hide-search-callback="hideSearch"
|
||||
search-callback="onSearchResults"
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
datatype-id="{{searchInfo.dataTypeId}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
section="{{section}}">
|
||||
</umb-tree-search-box>
|
||||
|
||||
<br/>
|
||||
|
||||
<umb-tree-search-results ng-if="searchInfo.showSearch"
|
||||
results="searchInfo.results"
|
||||
select-result-callback="selectResult">
|
||||
</umb-tree-search-results>
|
||||
|
||||
<div ng-hide="searchInfo.showSearch">
|
||||
<umb-tree section="content"
|
||||
hideheader="true"
|
||||
hideoptions="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
isdialog="true"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-panel-footer">
|
||||
<div class="umb-el-wrap umb-panel-buttons">
|
||||
<div class="btn-toolbar umb-btn-toolbar pull-right">
|
||||
<a href ng-click="close()" class="btn btn-link">
|
||||
<localize key="general_cancel">Cancel</localize>
|
||||
</a>
|
||||
<a href ng-click="switchToMediaPicker()" class="btn">
|
||||
<localize key="defaultdialogs_selectMedia">Select media</localize>
|
||||
</a>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
ng-click="submit(target)">
|
||||
<localize key="buttons_select">Select</localize>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,134 +1,140 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Dialogs.MediaPickerController",
|
||||
function($scope, mediaResource, umbRequestHelper, entityResource, $log, mediaHelper, mediaTypeHelper, eventsService, treeService) {
|
||||
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
|
||||
$scope.onlyImages = dialogOptions.onlyImages;
|
||||
$scope.showDetails = dialogOptions.showDetails;
|
||||
$scope.multiPicker = (dialogOptions.multiPicker && dialogOptions.multiPicker !== "0") ? true : false;
|
||||
$scope.startNodeId = dialogOptions.startNodeId ? dialogOptions.startNodeId : -1;
|
||||
$scope.cropSize = dialogOptions.cropSize;
|
||||
|
||||
//preload selected item
|
||||
$scope.target = undefined;
|
||||
if (dialogOptions.currentTarget) {
|
||||
$scope.target = dialogOptions.currentTarget;
|
||||
}
|
||||
|
||||
$scope.acceptedMediatypes = [];
|
||||
mediaTypeHelper.getAllowedImagetypes($scope.startNodeId)
|
||||
.then(function(types) {
|
||||
$scope.acceptedMediatypes = types;
|
||||
});
|
||||
|
||||
$scope.upload = function(v) {
|
||||
angular.element(".umb-file-dropzone-directive .file-select").click();
|
||||
};
|
||||
|
||||
$scope.dragLeave = function(el, event) {
|
||||
$scope.activeDrag = false;
|
||||
};
|
||||
|
||||
$scope.dragEnter = function(el, event) {
|
||||
$scope.activeDrag = true;
|
||||
};
|
||||
|
||||
$scope.submitFolder = function(e) {
|
||||
if (e.keyCode === 13) {
|
||||
e.preventDefault();
|
||||
|
||||
mediaResource
|
||||
.addFolder($scope.newFolderName, $scope.currentFolder.id)
|
||||
.then(function(data) {
|
||||
$scope.showFolderInput = false;
|
||||
$scope.newFolderName = "";
|
||||
|
||||
//we've added a new folder so lets clear the tree cache for that specific item
|
||||
treeService.clearCache({
|
||||
cacheKey: "__media", //this is the main media tree cache key
|
||||
childrenOf: data.parentId //clear the children of the parent
|
||||
});
|
||||
|
||||
$scope.gotoFolder(data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.gotoFolder = function(folder) {
|
||||
if (!folder) {
|
||||
folder = { id: -1, name: "Media", icon: "icon-folder" };
|
||||
}
|
||||
|
||||
if (folder.id > 0) {
|
||||
entityResource.getAncestors(folder.id, "media")
|
||||
.then(function(anc) {
|
||||
// anc.splice(0,1);
|
||||
$scope.path = _.filter(anc,
|
||||
function(f) {
|
||||
return f.path.indexOf($scope.startNodeId) !== -1;
|
||||
});
|
||||
});
|
||||
|
||||
mediaTypeHelper.getAllowedImagetypes(folder.id)
|
||||
.then(function(types) {
|
||||
$scope.acceptedMediatypes = types;
|
||||
});
|
||||
} else {
|
||||
$scope.path = [];
|
||||
}
|
||||
|
||||
//mediaResource.rootMedia()
|
||||
mediaResource.getChildren(folder.id)
|
||||
.then(function(data) {
|
||||
$scope.searchTerm = "";
|
||||
$scope.images = data.items ? data.items : [];
|
||||
});
|
||||
|
||||
$scope.currentFolder = folder;
|
||||
};
|
||||
|
||||
|
||||
$scope.clickHandler = function(image, ev, select) {
|
||||
ev.preventDefault();
|
||||
|
||||
if (image.isFolder && !select) {
|
||||
$scope.gotoFolder(image);
|
||||
} else {
|
||||
eventsService.emit("dialogs.mediaPicker.select", image);
|
||||
|
||||
//we have 3 options add to collection (if multi) show details, or submit it right back to the callback
|
||||
if ($scope.multiPicker) {
|
||||
$scope.select(image);
|
||||
image.cssclass = ($scope.dialogData.selection.indexOf(image) > -1) ? "selected" : "";
|
||||
} else if ($scope.showDetails) {
|
||||
$scope.target = image;
|
||||
$scope.target.url = mediaHelper.resolveFile(image);
|
||||
} else {
|
||||
$scope.submit(image);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.exitDetails = function() {
|
||||
if (!$scope.currentFolder) {
|
||||
$scope.gotoFolder();
|
||||
}
|
||||
|
||||
$scope.target = undefined;
|
||||
};
|
||||
|
||||
$scope.onUploadComplete = function() {
|
||||
$scope.gotoFolder($scope.currentFolder);
|
||||
};
|
||||
|
||||
$scope.onFilesQueue = function() {
|
||||
$scope.activeDrag = false;
|
||||
};
|
||||
|
||||
//default root item
|
||||
if (!$scope.target) {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
}
|
||||
});
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Dialogs.MediaPickerController",
|
||||
function($scope, mediaResource, umbRequestHelper, entityResource, $log, mediaHelper, mediaTypeHelper, eventsService, treeService) {
|
||||
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
|
||||
$scope.onlyImages = dialogOptions.onlyImages;
|
||||
$scope.showDetails = dialogOptions.showDetails;
|
||||
$scope.multiPicker = (dialogOptions.multiPicker && dialogOptions.multiPicker !== "0") ? true : false;
|
||||
$scope.startNodeId = dialogOptions.startNodeId ? dialogOptions.startNodeId : -1;
|
||||
$scope.cropSize = dialogOptions.cropSize;
|
||||
|
||||
//preload selected item
|
||||
$scope.target = undefined;
|
||||
if (dialogOptions.currentTarget) {
|
||||
$scope.target = dialogOptions.currentTarget;
|
||||
}
|
||||
|
||||
$scope.acceptedMediatypes = [];
|
||||
mediaTypeHelper.getAllowedImagetypes($scope.startNodeId)
|
||||
.then(function(types) {
|
||||
$scope.acceptedMediatypes = types;
|
||||
});
|
||||
|
||||
$scope.upload = function(v) {
|
||||
angular.element(".umb-file-dropzone-directive .file-select").click();
|
||||
};
|
||||
|
||||
$scope.dragLeave = function(el, event) {
|
||||
$scope.activeDrag = false;
|
||||
};
|
||||
|
||||
$scope.dragEnter = function(el, event) {
|
||||
$scope.activeDrag = true;
|
||||
};
|
||||
|
||||
$scope.submitFolder = function(e) {
|
||||
if (e.keyCode === 13) {
|
||||
e.preventDefault();
|
||||
|
||||
mediaResource
|
||||
.addFolder($scope.newFolderName, $scope.currentFolder.id)
|
||||
.then(function(data) {
|
||||
$scope.showFolderInput = false;
|
||||
$scope.newFolderName = "";
|
||||
|
||||
//we've added a new folder so lets clear the tree cache for that specific item
|
||||
treeService.clearCache({
|
||||
cacheKey: "__media", //this is the main media tree cache key
|
||||
childrenOf: data.parentId //clear the children of the parent
|
||||
});
|
||||
|
||||
$scope.gotoFolder(data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.gotoFolder = function(folder) {
|
||||
if (!folder) {
|
||||
folder = { id: -1, name: "Media", icon: "icon-folder" };
|
||||
}
|
||||
|
||||
if (folder.id > 0) {
|
||||
entityResource.getAncestors(folder.id, "media")
|
||||
.then(function(anc) {
|
||||
// anc.splice(0,1);
|
||||
$scope.path = _.filter(anc,
|
||||
function(f) {
|
||||
return f.path.indexOf($scope.startNodeId) !== -1;
|
||||
});
|
||||
});
|
||||
|
||||
mediaTypeHelper.getAllowedImagetypes(folder.id)
|
||||
.then(function(types) {
|
||||
$scope.acceptedMediatypes = types;
|
||||
});
|
||||
} else {
|
||||
$scope.path = [];
|
||||
}
|
||||
|
||||
//mediaResource.rootMedia()
|
||||
entityResource.getChildren(folder.id, "Media")
|
||||
.then(function(data) {
|
||||
for (i=0;i<data.length;i++){
|
||||
if(data[i].metaData.MediaPath){
|
||||
data[i].thumbnail = mediaHelper.resolveFileFromEntity(data[i], true);
|
||||
data[i].image = mediaHelper.resolveFileFromEntity(data[i], false);
|
||||
}
|
||||
}
|
||||
$scope.searchTerm = "";
|
||||
$scope.images = data ? data : [];
|
||||
});
|
||||
|
||||
$scope.currentFolder = folder;
|
||||
};
|
||||
|
||||
|
||||
$scope.clickHandler = function(image, ev, select) {
|
||||
ev.preventDefault();
|
||||
|
||||
if (image.isFolder && !select) {
|
||||
$scope.gotoFolder(image);
|
||||
} else {
|
||||
eventsService.emit("dialogs.mediaPicker.select", image);
|
||||
|
||||
//we have 3 options add to collection (if multi) show details, or submit it right back to the callback
|
||||
if ($scope.multiPicker) {
|
||||
$scope.select(image);
|
||||
image.cssclass = ($scope.dialogData.selection.indexOf(image) > -1) ? "selected" : "";
|
||||
} else if ($scope.showDetails) {
|
||||
$scope.target = image;
|
||||
$scope.target.url = mediaHelper.resolveFile(image);
|
||||
} else {
|
||||
$scope.submit(image);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.exitDetails = function() {
|
||||
if (!$scope.currentFolder) {
|
||||
$scope.gotoFolder();
|
||||
}
|
||||
|
||||
$scope.target = undefined;
|
||||
};
|
||||
|
||||
$scope.onUploadComplete = function() {
|
||||
$scope.gotoFolder($scope.currentFolder);
|
||||
};
|
||||
|
||||
$scope.onFilesQueue = function() {
|
||||
$scope.activeDrag = false;
|
||||
};
|
||||
|
||||
//default root item
|
||||
if (!$scope.target) {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,431 +1,431 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
|
||||
function ($scope, entityResource, eventsService, $log, searchService, angularHelper, $timeout, localizationService, treeService) {
|
||||
|
||||
var tree = null;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.section = dialogOptions.section;
|
||||
$scope.treeAlias = dialogOptions.treeAlias;
|
||||
$scope.multiPicker = dialogOptions.multiPicker;
|
||||
$scope.hideHeader = (typeof dialogOptions.hideHeader) === "boolean" ? dialogOptions.hideHeader : true;;
|
||||
$scope.searchInfo = {
|
||||
searchFromId: dialogOptions.startNodeId,
|
||||
searchFromName: null,
|
||||
showSearch: false,
|
||||
results: [],
|
||||
selectedSearchResults: []
|
||||
}
|
||||
|
||||
//create the custom query string param for this tree
|
||||
$scope.customTreeParams = dialogOptions.startNodeId ? "startNodeId=" + dialogOptions.startNodeId : "";
|
||||
$scope.customTreeParams += dialogOptions.customTreeParams ? "&" + dialogOptions.customTreeParams : "";
|
||||
|
||||
var searchText = "Search...";
|
||||
localizationService.localize("general_search").then(function (value) {
|
||||
searchText = value + "...";
|
||||
});
|
||||
|
||||
// Allow the entity type to be passed in but defaults to Document for backwards compatibility.
|
||||
var entityType = dialogOptions.entityType ? dialogOptions.entityType : "Document";
|
||||
|
||||
|
||||
//min / max values
|
||||
if (dialogOptions.minNumber) {
|
||||
dialogOptions.minNumber = parseInt(dialogOptions.minNumber, 10);
|
||||
}
|
||||
if (dialogOptions.maxNumber) {
|
||||
dialogOptions.maxNumber = parseInt(dialogOptions.maxNumber, 10);
|
||||
}
|
||||
|
||||
if (dialogOptions.section === "member") {
|
||||
entityType = "Member";
|
||||
}
|
||||
else if (dialogOptions.section === "media") {
|
||||
entityType = "Media";
|
||||
}
|
||||
|
||||
//Configures filtering
|
||||
if (dialogOptions.filter) {
|
||||
|
||||
dialogOptions.filterExclude = false;
|
||||
dialogOptions.filterAdvanced = false;
|
||||
|
||||
//used advanced filtering
|
||||
if (angular.isFunction(dialogOptions.filter)) {
|
||||
dialogOptions.filterAdvanced = true;
|
||||
}
|
||||
else if (angular.isObject(dialogOptions.filter)) {
|
||||
dialogOptions.filterAdvanced = true;
|
||||
}
|
||||
else {
|
||||
if (dialogOptions.filter.startsWith("!")) {
|
||||
dialogOptions.filterExclude = true;
|
||||
dialogOptions.filter = dialogOptions.filter.substring(1);
|
||||
}
|
||||
|
||||
//used advanced filtering
|
||||
if (dialogOptions.filter.startsWith("{")) {
|
||||
dialogOptions.filterAdvanced = true;
|
||||
//convert to object
|
||||
dialogOptions.filter = angular.fromJson(dialogOptions.filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nodeExpandedHandler(ev, args) {
|
||||
if (angular.isArray(args.children)) {
|
||||
|
||||
//iterate children
|
||||
_.each(args.children, function (child) {
|
||||
|
||||
//check if any of the items are list views, if so we need to add some custom
|
||||
// children: A node to activate the search, any nodes that have already been
|
||||
// selected in the search
|
||||
if (child.metaData.isContainer) {
|
||||
child.hasChildren = true;
|
||||
child.children = [
|
||||
{
|
||||
level: child.level + 1,
|
||||
hasChildren: false,
|
||||
parent: function () {
|
||||
return child;
|
||||
},
|
||||
name: searchText,
|
||||
metaData: {
|
||||
listViewNode: child
|
||||
},
|
||||
cssClass: "icon-search",
|
||||
cssClasses: ["not-published"]
|
||||
}
|
||||
];
|
||||
//add base transition classes to this node
|
||||
child.cssClasses.push("tree-node-slide-up");
|
||||
|
||||
var listViewResults = _.filter($scope.searchInfo.selectedSearchResults, function(i) {
|
||||
return i.parentId == child.id;
|
||||
});
|
||||
_.each(listViewResults, function(item) {
|
||||
child.children.unshift({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
cssClass: "icon umb-tree-icon sprTree " + item.icon,
|
||||
level: child.level + 1,
|
||||
metaData: {
|
||||
isSearchResult: true
|
||||
},
|
||||
hasChildren: false,
|
||||
parent: function () {
|
||||
return child;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//now we need to look in the already selected search results and
|
||||
// toggle the check boxes for those ones that are listed
|
||||
var exists = _.find($scope.searchInfo.selectedSearchResults, function (selected) {
|
||||
return child.id == selected.id;
|
||||
});
|
||||
if (exists) {
|
||||
child.selected = true;
|
||||
}
|
||||
});
|
||||
|
||||
//check filter
|
||||
performFiltering(args.children);
|
||||
}
|
||||
}
|
||||
|
||||
//gets the tree object when it loads
|
||||
function treeLoadedHandler(ev, args) {
|
||||
tree = args.tree;
|
||||
}
|
||||
|
||||
//wires up selection
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if (args.node.metaData.listViewNode) {
|
||||
//check if list view 'search' node was selected
|
||||
|
||||
$scope.searchInfo.showSearch = true;
|
||||
$scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
||||
$scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
||||
|
||||
//add transition classes
|
||||
var listViewNode = args.node.parent();
|
||||
listViewNode.cssClasses.push('tree-node-slide-up-hide-active');
|
||||
}
|
||||
else if (args.node.metaData.isSearchResult) {
|
||||
//check if the item selected was a search result from a list view
|
||||
|
||||
//unselect
|
||||
select(args.node.name, args.node.id);
|
||||
|
||||
//remove it from the list view children
|
||||
var listView = args.node.parent();
|
||||
listView.children = _.reject(listView.children, function(child) {
|
||||
return child.id == args.node.id;
|
||||
});
|
||||
|
||||
//remove it from the custom tracked search result list
|
||||
$scope.searchInfo.selectedSearchResults = _.reject($scope.searchInfo.selectedSearchResults, function (i) {
|
||||
return i.id == args.node.id;
|
||||
});
|
||||
}
|
||||
else {
|
||||
eventsService.emit("dialogs.treePickerController.select", args);
|
||||
|
||||
if (args.node.filtered) {
|
||||
return;
|
||||
}
|
||||
|
||||
//This is a tree node, so we don't have an entity to pass in, it will need to be looked up
|
||||
//from the server in this method.
|
||||
select(args.node.name, args.node.id);
|
||||
|
||||
//toggle checked state
|
||||
args.node.selected = args.node.selected === true ? false : true;
|
||||
}
|
||||
}
|
||||
|
||||
/** Method used for selecting a node */
|
||||
function select(text, id, entity) {
|
||||
//if we get the root, we just return a constructed entity, no need for server data
|
||||
if (id < 0) {
|
||||
if ($scope.multiPicker) {
|
||||
$scope.select(id);
|
||||
}
|
||||
else {
|
||||
var node = {
|
||||
alias: null,
|
||||
icon: "icon-folder",
|
||||
id: id,
|
||||
name: text
|
||||
};
|
||||
$scope.submit(node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if ($scope.multiPicker) {
|
||||
$scope.select(Number(id));
|
||||
}
|
||||
else {
|
||||
|
||||
$scope.hideSearch();
|
||||
|
||||
//if an entity has been passed in, use it
|
||||
if (entity) {
|
||||
$scope.submit(entity);
|
||||
} else {
|
||||
//otherwise we have to get it from the server
|
||||
entityResource.getById(id, entityType).then(function (ent) {
|
||||
$scope.submit(ent);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function performFiltering(nodes) {
|
||||
|
||||
if (!dialogOptions.filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
//remove any list view search nodes from being filtered since these are special nodes that always must
|
||||
// be allowed to be clicked on
|
||||
nodes = _.filter(nodes, function(n) {
|
||||
return !angular.isObject(n.metaData.listViewNode);
|
||||
});
|
||||
|
||||
if (dialogOptions.filterAdvanced) {
|
||||
|
||||
//filter either based on a method or an object
|
||||
var filtered = angular.isFunction(dialogOptions.filter)
|
||||
? _.filter(nodes, dialogOptions.filter)
|
||||
: _.where(nodes, dialogOptions.filter);
|
||||
|
||||
angular.forEach(filtered, function (value, key) {
|
||||
value.filtered = true;
|
||||
if (dialogOptions.filterCssClass) {
|
||||
if (!value.cssClasses) {
|
||||
value.cssClasses = [];
|
||||
}
|
||||
value.cssClasses.push(dialogOptions.filterCssClass);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var a = dialogOptions.filter.toLowerCase().replace(/\s/g, '').split(',');
|
||||
angular.forEach(nodes, function (value, key) {
|
||||
|
||||
var found = a.indexOf(value.metaData.contentType.toLowerCase()) >= 0;
|
||||
|
||||
if (!dialogOptions.filterExclude && !found || dialogOptions.filterExclude && found) {
|
||||
value.filtered = true;
|
||||
|
||||
if (dialogOptions.filterCssClass) {
|
||||
if (!value.cssClasses) {
|
||||
value.cssClasses = [];
|
||||
}
|
||||
value.cssClasses.push(dialogOptions.filterCssClass);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$scope.multiSubmit = function (result) {
|
||||
entityResource.getByIds(result, entityType).then(function (ents) {
|
||||
$scope.submit(ents);
|
||||
});
|
||||
};
|
||||
|
||||
/** method to select a search result */
|
||||
$scope.selectResult = function (evt, result) {
|
||||
|
||||
if (result.filtered) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.selected = result.selected === true ? false : true;
|
||||
|
||||
//since result = an entity, we'll pass it in so we don't have to go back to the server
|
||||
select(result.name, result.id, result);
|
||||
|
||||
//add/remove to our custom tracked list of selected search results
|
||||
if (result.selected) {
|
||||
$scope.searchInfo.selectedSearchResults.push(result);
|
||||
}
|
||||
else {
|
||||
$scope.searchInfo.selectedSearchResults = _.reject($scope.searchInfo.selectedSearchResults, function(i) {
|
||||
return i.id == result.id;
|
||||
});
|
||||
}
|
||||
|
||||
//ensure the tree node in the tree is checked/unchecked if it already exists there
|
||||
if (tree) {
|
||||
var found = treeService.getDescendantNode(tree.root, result.id);
|
||||
if (found) {
|
||||
found.selected = result.selected;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$scope.hideSearch = function () {
|
||||
|
||||
//Traverse the entire displayed tree and update each node to sync with the selected search results
|
||||
if (tree) {
|
||||
|
||||
//we need to ensure that any currently displayed nodes that get selected
|
||||
// from the search get updated to have a check box!
|
||||
function checkChildren(children) {
|
||||
_.each(children, function (child) {
|
||||
//check if the id is in the selection, if so ensure it's flagged as selected
|
||||
var exists = _.find($scope.searchInfo.selectedSearchResults, function (selected) {
|
||||
return child.id == selected.id;
|
||||
});
|
||||
//if the curr node exists in selected search results, ensure it's checked
|
||||
if (exists) {
|
||||
child.selected = true;
|
||||
}
|
||||
//if the curr node does not exist in the selected search result, and the curr node is a child of a list view search result
|
||||
else if (child.metaData.isSearchResult) {
|
||||
//if this tree node is under a list view it means that the node was added
|
||||
// to the tree dynamically under the list view that was searched, so we actually want to remove
|
||||
// it all together from the tree
|
||||
var listView = child.parent();
|
||||
listView.children = _.reject(listView.children, function(c) {
|
||||
return c.id == child.id;
|
||||
});
|
||||
}
|
||||
|
||||
//check if the current node is a list view and if so, check if there's any new results
|
||||
// that need to be added as child nodes to it based on search results selected
|
||||
if (child.metaData.isContainer) {
|
||||
|
||||
child.cssClasses = _.reject(child.cssClasses, function(c) {
|
||||
return c === 'tree-node-slide-up-hide-active';
|
||||
});
|
||||
|
||||
var listViewResults = _.filter($scope.searchInfo.selectedSearchResults, function (i) {
|
||||
return i.parentId == child.id;
|
||||
});
|
||||
_.each(listViewResults, function (item) {
|
||||
var childExists = _.find(child.children, function(c) {
|
||||
return c.id == item.id;
|
||||
});
|
||||
if (!childExists) {
|
||||
var parent = child;
|
||||
child.children.unshift({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
cssClass: "icon umb-tree-icon sprTree " + item.icon,
|
||||
level: child.level + 1,
|
||||
metaData: {
|
||||
isSearchResult: true
|
||||
},
|
||||
hasChildren: false,
|
||||
parent: function () {
|
||||
return parent;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//recurse
|
||||
if (child.children && child.children.length > 0) {
|
||||
checkChildren(child.children);
|
||||
}
|
||||
});
|
||||
}
|
||||
checkChildren(tree.root.children);
|
||||
}
|
||||
|
||||
|
||||
$scope.searchInfo.showSearch = false;
|
||||
$scope.searchInfo.searchFromId = dialogOptions.startNodeId;
|
||||
$scope.searchInfo.searchFromName = null;
|
||||
$scope.searchInfo.results = [];
|
||||
}
|
||||
|
||||
$scope.onSearchResults = function(results) {
|
||||
|
||||
//filter all items - this will mark an item as filtered
|
||||
performFiltering(results);
|
||||
|
||||
//now actually remove all filtered items so they are not even displayed
|
||||
results = _.filter(results, function(item) {
|
||||
return !item.filtered;
|
||||
});
|
||||
|
||||
$scope.searchInfo.results = results;
|
||||
|
||||
//sync with the curr selected results
|
||||
_.each($scope.searchInfo.results, function (result) {
|
||||
var exists = _.find($scope.dialogData.selection, function (selectedId) {
|
||||
return result.id == selectedId;
|
||||
});
|
||||
if (exists) {
|
||||
result.selected = true;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.searchInfo.showSearch = true;
|
||||
};
|
||||
|
||||
$scope.dialogTreeEventHandler.bind("treeLoaded", treeLoadedHandler);
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeExpanded", nodeExpandedHandler);
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler);
|
||||
|
||||
$scope.$on('$destroy', function () {
|
||||
$scope.dialogTreeEventHandler.unbind("treeLoaded", treeLoadedHandler);
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||
});
|
||||
});
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
|
||||
function ($scope, entityResource, eventsService, $log, searchService, angularHelper, $timeout, localizationService, treeService) {
|
||||
|
||||
var tree = null;
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.section = dialogOptions.section;
|
||||
$scope.treeAlias = dialogOptions.treeAlias;
|
||||
$scope.multiPicker = dialogOptions.multiPicker;
|
||||
$scope.hideHeader = (typeof dialogOptions.hideHeader) === "boolean" ? dialogOptions.hideHeader : true;;
|
||||
$scope.searchInfo = {
|
||||
searchFromId: dialogOptions.startNodeId,
|
||||
searchFromName: null,
|
||||
showSearch: false,
|
||||
results: [],
|
||||
selectedSearchResults: []
|
||||
}
|
||||
|
||||
//create the custom query string param for this tree
|
||||
$scope.customTreeParams = dialogOptions.startNodeId ? "startNodeId=" + dialogOptions.startNodeId : "";
|
||||
$scope.customTreeParams += dialogOptions.customTreeParams ? "&" + dialogOptions.customTreeParams : "";
|
||||
|
||||
var searchText = "Search...";
|
||||
localizationService.localize("general_search").then(function (value) {
|
||||
searchText = value + "...";
|
||||
});
|
||||
|
||||
// Allow the entity type to be passed in but defaults to Document for backwards compatibility.
|
||||
var entityType = dialogOptions.entityType ? dialogOptions.entityType : "Document";
|
||||
|
||||
|
||||
//min / max values
|
||||
if (dialogOptions.minNumber) {
|
||||
dialogOptions.minNumber = parseInt(dialogOptions.minNumber, 10);
|
||||
}
|
||||
if (dialogOptions.maxNumber) {
|
||||
dialogOptions.maxNumber = parseInt(dialogOptions.maxNumber, 10);
|
||||
}
|
||||
|
||||
if (dialogOptions.section === "member") {
|
||||
entityType = "Member";
|
||||
}
|
||||
else if (dialogOptions.section === "media") {
|
||||
entityType = "Media";
|
||||
}
|
||||
|
||||
//Configures filtering
|
||||
if (dialogOptions.filter) {
|
||||
|
||||
dialogOptions.filterExclude = false;
|
||||
dialogOptions.filterAdvanced = false;
|
||||
|
||||
//used advanced filtering
|
||||
if (angular.isFunction(dialogOptions.filter)) {
|
||||
dialogOptions.filterAdvanced = true;
|
||||
}
|
||||
else if (angular.isObject(dialogOptions.filter)) {
|
||||
dialogOptions.filterAdvanced = true;
|
||||
}
|
||||
else {
|
||||
if (dialogOptions.filter.startsWith("!")) {
|
||||
dialogOptions.filterExclude = true;
|
||||
dialogOptions.filter = dialogOptions.filter.substring(1);
|
||||
}
|
||||
|
||||
//used advanced filtering
|
||||
if (dialogOptions.filter.startsWith("{")) {
|
||||
dialogOptions.filterAdvanced = true;
|
||||
//convert to object
|
||||
dialogOptions.filter = angular.fromJson(dialogOptions.filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nodeExpandedHandler(ev, args) {
|
||||
if (angular.isArray(args.children)) {
|
||||
|
||||
//iterate children
|
||||
_.each(args.children, function (child) {
|
||||
|
||||
//check if any of the items are list views, if so we need to add some custom
|
||||
// children: A node to activate the search, any nodes that have already been
|
||||
// selected in the search
|
||||
if (child.metaData.isContainer) {
|
||||
child.hasChildren = true;
|
||||
child.children = [
|
||||
{
|
||||
level: child.level + 1,
|
||||
hasChildren: false,
|
||||
parent: function () {
|
||||
return child;
|
||||
},
|
||||
name: searchText,
|
||||
metaData: {
|
||||
listViewNode: child
|
||||
},
|
||||
cssClass: "icon-search",
|
||||
cssClasses: ["not-published"]
|
||||
}
|
||||
];
|
||||
//add base transition classes to this node
|
||||
child.cssClasses.push("tree-node-slide-up");
|
||||
|
||||
var listViewResults = _.filter($scope.searchInfo.selectedSearchResults, function(i) {
|
||||
return i.parentId == child.id;
|
||||
});
|
||||
_.each(listViewResults, function(item) {
|
||||
child.children.unshift({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
cssClass: "icon umb-tree-icon sprTree " + item.icon,
|
||||
level: child.level + 1,
|
||||
metaData: {
|
||||
isSearchResult: true
|
||||
},
|
||||
hasChildren: false,
|
||||
parent: function () {
|
||||
return child;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//now we need to look in the already selected search results and
|
||||
// toggle the check boxes for those ones that are listed
|
||||
var exists = _.find($scope.searchInfo.selectedSearchResults, function (selected) {
|
||||
return child.id == selected.id;
|
||||
});
|
||||
if (exists) {
|
||||
child.selected = true;
|
||||
}
|
||||
});
|
||||
|
||||
//check filter
|
||||
performFiltering(args.children);
|
||||
}
|
||||
}
|
||||
|
||||
//gets the tree object when it loads
|
||||
function treeLoadedHandler(ev, args) {
|
||||
tree = args.tree;
|
||||
}
|
||||
|
||||
//wires up selection
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if (args.node.metaData.listViewNode) {
|
||||
//check if list view 'search' node was selected
|
||||
|
||||
$scope.searchInfo.showSearch = true;
|
||||
$scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
||||
$scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
||||
|
||||
//add transition classes
|
||||
var listViewNode = args.node.parent();
|
||||
listViewNode.cssClasses.push('tree-node-slide-up-hide-active');
|
||||
}
|
||||
else if (args.node.metaData.isSearchResult) {
|
||||
//check if the item selected was a search result from a list view
|
||||
|
||||
//unselect
|
||||
select(args.node.name, args.node.id);
|
||||
|
||||
//remove it from the list view children
|
||||
var listView = args.node.parent();
|
||||
listView.children = _.reject(listView.children, function(child) {
|
||||
return child.id == args.node.id;
|
||||
});
|
||||
|
||||
//remove it from the custom tracked search result list
|
||||
$scope.searchInfo.selectedSearchResults = _.reject($scope.searchInfo.selectedSearchResults, function (i) {
|
||||
return i.id == args.node.id;
|
||||
});
|
||||
}
|
||||
else {
|
||||
eventsService.emit("dialogs.treePickerController.select", args);
|
||||
|
||||
if (args.node.filtered) {
|
||||
return;
|
||||
}
|
||||
|
||||
//This is a tree node, so we don't have an entity to pass in, it will need to be looked up
|
||||
//from the server in this method.
|
||||
select(args.node.name, args.node.id);
|
||||
|
||||
//toggle checked state
|
||||
args.node.selected = args.node.selected === true ? false : true;
|
||||
}
|
||||
}
|
||||
|
||||
/** Method used for selecting a node */
|
||||
function select(text, id, entity) {
|
||||
//if we get the root, we just return a constructed entity, no need for server data
|
||||
if (id < 0) {
|
||||
if ($scope.multiPicker) {
|
||||
$scope.select(id);
|
||||
}
|
||||
else {
|
||||
var node = {
|
||||
alias: null,
|
||||
icon: "icon-folder",
|
||||
id: id,
|
||||
name: text
|
||||
};
|
||||
$scope.submit(node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if ($scope.multiPicker) {
|
||||
$scope.select(Number(id));
|
||||
}
|
||||
else {
|
||||
|
||||
$scope.hideSearch();
|
||||
|
||||
//if an entity has been passed in, use it
|
||||
if (entity) {
|
||||
$scope.submit(entity);
|
||||
} else {
|
||||
//otherwise we have to get it from the server
|
||||
entityResource.getById(id, entityType).then(function (ent) {
|
||||
$scope.submit(ent);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function performFiltering(nodes) {
|
||||
|
||||
if (!dialogOptions.filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
//remove any list view search nodes from being filtered since these are special nodes that always must
|
||||
// be allowed to be clicked on
|
||||
nodes = _.filter(nodes, function(n) {
|
||||
return !angular.isObject(n.metaData.listViewNode);
|
||||
});
|
||||
|
||||
if (dialogOptions.filterAdvanced) {
|
||||
|
||||
//filter either based on a method or an object
|
||||
var filtered = angular.isFunction(dialogOptions.filter)
|
||||
? _.filter(nodes, dialogOptions.filter)
|
||||
: _.where(nodes, dialogOptions.filter);
|
||||
|
||||
angular.forEach(filtered, function (value, key) {
|
||||
value.filtered = true;
|
||||
if (dialogOptions.filterCssClass) {
|
||||
if (!value.cssClasses) {
|
||||
value.cssClasses = [];
|
||||
}
|
||||
value.cssClasses.push(dialogOptions.filterCssClass);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var a = dialogOptions.filter.toLowerCase().replace(/\s/g, '').split(',');
|
||||
angular.forEach(nodes, function (value, key) {
|
||||
|
||||
var found = a.indexOf(value.metaData.contentType.toLowerCase()) >= 0;
|
||||
|
||||
if (!dialogOptions.filterExclude && !found || dialogOptions.filterExclude && found) {
|
||||
value.filtered = true;
|
||||
|
||||
if (dialogOptions.filterCssClass) {
|
||||
if (!value.cssClasses) {
|
||||
value.cssClasses = [];
|
||||
}
|
||||
value.cssClasses.push(dialogOptions.filterCssClass);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$scope.multiSubmit = function (result) {
|
||||
entityResource.getByIds(result, entityType).then(function (ents) {
|
||||
$scope.submit(ents);
|
||||
});
|
||||
};
|
||||
|
||||
/** method to select a search result */
|
||||
$scope.selectResult = function (evt, result) {
|
||||
|
||||
if (result.filtered) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.selected = result.selected === true ? false : true;
|
||||
|
||||
//since result = an entity, we'll pass it in so we don't have to go back to the server
|
||||
select(result.name, result.id, result);
|
||||
|
||||
//add/remove to our custom tracked list of selected search results
|
||||
if (result.selected) {
|
||||
$scope.searchInfo.selectedSearchResults.push(result);
|
||||
}
|
||||
else {
|
||||
$scope.searchInfo.selectedSearchResults = _.reject($scope.searchInfo.selectedSearchResults, function(i) {
|
||||
return i.id == result.id;
|
||||
});
|
||||
}
|
||||
|
||||
//ensure the tree node in the tree is checked/unchecked if it already exists there
|
||||
if (tree) {
|
||||
var found = treeService.getDescendantNode(tree.root, result.id);
|
||||
if (found) {
|
||||
found.selected = result.selected;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$scope.hideSearch = function () {
|
||||
|
||||
//Traverse the entire displayed tree and update each node to sync with the selected search results
|
||||
if (tree) {
|
||||
|
||||
//we need to ensure that any currently displayed nodes that get selected
|
||||
// from the search get updated to have a check box!
|
||||
function checkChildren(children) {
|
||||
_.each(children, function (child) {
|
||||
//check if the id is in the selection, if so ensure it's flagged as selected
|
||||
var exists = _.find($scope.searchInfo.selectedSearchResults, function (selected) {
|
||||
return child.id == selected.id;
|
||||
});
|
||||
//if the curr node exists in selected search results, ensure it's checked
|
||||
if (exists) {
|
||||
child.selected = true;
|
||||
}
|
||||
//if the curr node does not exist in the selected search result, and the curr node is a child of a list view search result
|
||||
else if (child.metaData.isSearchResult) {
|
||||
//if this tree node is under a list view it means that the node was added
|
||||
// to the tree dynamically under the list view that was searched, so we actually want to remove
|
||||
// it all together from the tree
|
||||
var listView = child.parent();
|
||||
listView.children = _.reject(listView.children, function(c) {
|
||||
return c.id == child.id;
|
||||
});
|
||||
}
|
||||
|
||||
//check if the current node is a list view and if so, check if there's any new results
|
||||
// that need to be added as child nodes to it based on search results selected
|
||||
if (child.metaData.isContainer) {
|
||||
|
||||
child.cssClasses = _.reject(child.cssClasses, function(c) {
|
||||
return c === 'tree-node-slide-up-hide-active';
|
||||
});
|
||||
|
||||
var listViewResults = _.filter($scope.searchInfo.selectedSearchResults, function (i) {
|
||||
return i.parentId == child.id;
|
||||
});
|
||||
_.each(listViewResults, function (item) {
|
||||
var childExists = _.find(child.children, function(c) {
|
||||
return c.id == item.id;
|
||||
});
|
||||
if (!childExists) {
|
||||
var parent = child;
|
||||
child.children.unshift({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
cssClass: "icon umb-tree-icon sprTree " + item.icon,
|
||||
level: child.level + 1,
|
||||
metaData: {
|
||||
isSearchResult: true
|
||||
},
|
||||
hasChildren: false,
|
||||
parent: function () {
|
||||
return parent;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//recurse
|
||||
if (child.children && child.children.length > 0) {
|
||||
checkChildren(child.children);
|
||||
}
|
||||
});
|
||||
}
|
||||
checkChildren(tree.root.children);
|
||||
}
|
||||
|
||||
|
||||
$scope.searchInfo.showSearch = false;
|
||||
$scope.searchInfo.searchFromId = dialogOptions.startNodeId;
|
||||
$scope.searchInfo.searchFromName = null;
|
||||
$scope.searchInfo.results = [];
|
||||
}
|
||||
|
||||
$scope.onSearchResults = function(results) {
|
||||
|
||||
//filter all items - this will mark an item as filtered
|
||||
performFiltering(results);
|
||||
|
||||
//now actually remove all filtered items so they are not even displayed
|
||||
results = _.filter(results, function(item) {
|
||||
return !item.filtered;
|
||||
});
|
||||
|
||||
$scope.searchInfo.results = results;
|
||||
|
||||
//sync with the curr selected results
|
||||
_.each($scope.searchInfo.results, function (result) {
|
||||
var exists = _.find($scope.dialogData.selection, function (selectedId) {
|
||||
return result.id == selectedId;
|
||||
});
|
||||
if (exists) {
|
||||
result.selected = true;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.searchInfo.showSearch = true;
|
||||
};
|
||||
|
||||
$scope.dialogTreeEventHandler.bind("treeLoaded", treeLoadedHandler);
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeExpanded", nodeExpandedHandler);
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler);
|
||||
|
||||
$scope.$on('$destroy', function () {
|
||||
$scope.dialogTreeEventHandler.unbind("treeLoaded", treeLoadedHandler);
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
ignore-user-startnodes="{{searchInfo.ignoreUserStartNodes}}"
|
||||
datatype-id="{{searchInfo.dataTypeId}}"
|
||||
section="content">
|
||||
</umb-tree-search-box>
|
||||
</div>
|
||||
|
||||
+21
-16
@@ -1,6 +1,6 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
|
||||
function ($scope, eventsService, dialogService, entityResource, contentResource, mediaHelper, userService, localizationService, tinyMceService) {
|
||||
function ($scope, eventsService, dialogService, entityResource, mediaHelper, userService, localizationService, tinyMceService) {
|
||||
var dialogOptions = $scope.model;
|
||||
|
||||
var searchText = "Search...";
|
||||
@@ -12,43 +12,47 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
|
||||
$scope.model.title = localizationService.localize("defaultdialogs_selectLink");
|
||||
}
|
||||
|
||||
var dataTypeId = null;
|
||||
if(dialogOptions && dialogOptions.dataTypeId){
|
||||
dataTypeId = dialogOptions.dataTypeId;
|
||||
}
|
||||
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.model.target = {};
|
||||
$scope.searchInfo = {
|
||||
searchFromId: null,
|
||||
searchFromName: null,
|
||||
showSearch: false,
|
||||
ignoreUserStartNodes: dialogOptions.ignoreUserStartNodes,
|
||||
dataTypeId: dataTypeId,
|
||||
results: [],
|
||||
selectedSearchResults: []
|
||||
};
|
||||
$scope.customTreeParams = dialogOptions.ignoreUserStartNodes ? "ignoreUserStartNodes=" + dialogOptions.ignoreUserStartNodes : "";
|
||||
$scope.customTreeParams = dataTypeId !== null ? "dataTypeId=" + dataTypeId : "";
|
||||
$scope.showTarget = $scope.model.hideTarget !== true;
|
||||
|
||||
if (dialogOptions.currentTarget) {
|
||||
// clone the current target so we don't accidentally update the caller's model while manipulating $scope.model.target
|
||||
$scope.model.target = angular.copy(dialogOptions.currentTarget);
|
||||
//if we have a node ID, we fetch the current node to build the form data
|
||||
// if we have a node ID, we fetch the current node to build the form data
|
||||
if ($scope.model.target.id || $scope.model.target.udi) {
|
||||
|
||||
//will be either a udi or an int
|
||||
// will be either a udi or an int
|
||||
var id = $scope.model.target.udi ? $scope.model.target.udi : $scope.model.target.id;
|
||||
|
||||
// is it a content link?
|
||||
if (!$scope.model.target.isMedia) {
|
||||
// get the content path
|
||||
entityResource.getPath(id, "Document").then(function (path) {
|
||||
//now sync the tree to this path
|
||||
// now sync the tree to this path
|
||||
$scope.dialogTreeEventHandler.syncTree({
|
||||
path: path,
|
||||
tree: "content"
|
||||
});
|
||||
});
|
||||
|
||||
// if a link exists, get the properties to build the anchor name list
|
||||
contentResource.getById(id, { ignoreUserStartNodes: dialogOptions.ignoreUserStartNodes }).then(function (resp) {
|
||||
$scope.model.target.url = resp.urls[0];
|
||||
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
|
||||
entityResource.getUrlAndAnchors(id).then(function(resp){
|
||||
$scope.anchorValues = resp.anchorValues;
|
||||
$scope.model.target.url = resp.url;
|
||||
});
|
||||
}
|
||||
} else if ($scope.model.target.url.length) {
|
||||
@@ -88,9 +92,9 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
|
||||
if (args.node.id < 0) {
|
||||
$scope.model.target.url = "/";
|
||||
} else {
|
||||
contentResource.getById(args.node.id, { ignoreUserStartNodes: dialogOptions.ignoreUserStartNodes }).then(function (resp) {
|
||||
$scope.model.target.url = resp.urls[0];
|
||||
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
|
||||
entityResource.getUrlAndAnchors(args.node.id).then(function(resp){
|
||||
$scope.anchorValues = resp.anchorValues;
|
||||
$scope.model.target.url = resp.url;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -115,12 +119,13 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
|
||||
startNodeId = -1;
|
||||
startNodeIsVirtual = true;
|
||||
}
|
||||
|
||||
$scope.mediaPickerOverlay = {
|
||||
view: "mediapicker",
|
||||
startNodeId: startNodeId,
|
||||
startNodeIsVirtual: startNodeIsVirtual,
|
||||
show: true,
|
||||
ignoreUserStartNodes: dialogOptions.ignoreUserStartNodes,
|
||||
dataTypeId: dataTypeId,
|
||||
submit: function (model) {
|
||||
var media = model.selectedImages[0];
|
||||
|
||||
@@ -128,12 +133,12 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
|
||||
$scope.model.target.udi = media.udi;
|
||||
$scope.model.target.isMedia = true;
|
||||
$scope.model.target.name = media.name;
|
||||
$scope.model.target.url = mediaHelper.resolveFile(media);
|
||||
$scope.model.target.url = media.image;
|
||||
|
||||
$scope.mediaPickerOverlay.show = false;
|
||||
$scope.mediaPickerOverlay = null;
|
||||
|
||||
// make sure the content tree has nothing highlighted
|
||||
// make sure the content tree has nothing highlighted
|
||||
$scope.dialogTreeEventHandler.syncTree({
|
||||
path: "-1",
|
||||
tree: "content"
|
||||
|
||||
@@ -43,14 +43,13 @@
|
||||
<h5>
|
||||
<localize key="defaultdialogs_linkToPage">Link to page</localize>
|
||||
</h5>
|
||||
|
||||
<div ng-hide="miniListView">
|
||||
<umb-tree-search-box hide-search-callback="hideSearch"
|
||||
search-callback="onSearchResults"
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
datatype-id="{{searchInfo.dataTypeId}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
ignore-user-startnodes="{{searchInfo.ignoreUserStartNodes}}"
|
||||
section="{{section}}">
|
||||
</umb-tree-search-box>
|
||||
|
||||
|
||||
+439
-426
@@ -1,426 +1,439 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Overlays.MediaPickerController",
|
||||
function ($scope, mediaResource, umbRequestHelper, entityResource, $log, mediaHelper, mediaTypeHelper, eventsService, treeService, $element, $timeout, userService, $cookies, localStorageService, localizationService) {
|
||||
|
||||
if (!$scope.model.title) {
|
||||
$scope.model.title = localizationService.localize("defaultdialogs_selectMedia");
|
||||
}
|
||||
|
||||
var dialogOptions = $scope.model;
|
||||
|
||||
$scope.disableFolderSelect = dialogOptions.disableFolderSelect;
|
||||
$scope.onlyImages = dialogOptions.onlyImages;
|
||||
$scope.showDetails = dialogOptions.showDetails;
|
||||
$scope.multiPicker = (dialogOptions.multiPicker && dialogOptions.multiPicker !== "0") ? true : false;
|
||||
$scope.startNodeId = dialogOptions.startNodeId ? dialogOptions.startNodeId : -1;
|
||||
$scope.cropSize = dialogOptions.cropSize;
|
||||
$scope.lastOpenedNode = localStorageService.get("umbLastOpenedMediaNodeId");
|
||||
$scope.lockedFolder = true;
|
||||
|
||||
var userStartNodes = [];
|
||||
|
||||
var umbracoSettings = Umbraco.Sys.ServerVariables.umbracoSettings;
|
||||
var allowedUploadFiles = mediaHelper.formatFileTypes(umbracoSettings.allowedUploadFiles);
|
||||
if ($scope.onlyImages) {
|
||||
$scope.acceptedFileTypes = mediaHelper.formatFileTypes(umbracoSettings.imageFileTypes);
|
||||
} else {
|
||||
// Use whitelist of allowed file types if provided
|
||||
if (allowedUploadFiles !== '') {
|
||||
$scope.acceptedFileTypes = allowedUploadFiles;
|
||||
} else {
|
||||
// If no whitelist, we pass in a blacklist by adding ! to the file extensions, allowing everything EXCEPT for disallowedUploadFiles
|
||||
$scope.acceptedFileTypes = !mediaHelper.formatFileTypes(umbracoSettings.disallowedUploadFiles);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.maxFileSize = umbracoSettings.maxFileSize + "KB";
|
||||
|
||||
$scope.model.selectedImages = [];
|
||||
|
||||
$scope.acceptedMediatypes = [];
|
||||
mediaTypeHelper.getAllowedImagetypes($scope.startNodeId)
|
||||
.then(function(types) {
|
||||
$scope.acceptedMediatypes = types;
|
||||
});
|
||||
|
||||
$scope.searchOptions = {
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
filter: '',
|
||||
ignoreUserStartNodes: $scope.model.ignoreUserStartNodes
|
||||
};
|
||||
|
||||
//preload selected item
|
||||
$scope.target = undefined;
|
||||
if (dialogOptions.currentTarget) {
|
||||
$scope.target = dialogOptions.currentTarget;
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
userService.getCurrentUser().then(function (userData) {
|
||||
userStartNodes = userData.startMediaIds;
|
||||
|
||||
if ($scope.startNodeId !== -1) {
|
||||
entityResource.getById($scope.startNodeId, "media")
|
||||
.then(function (ent) {
|
||||
$scope.startNodeId = ent.id;
|
||||
run();
|
||||
});
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function run() {
|
||||
//default root item
|
||||
if (!$scope.target) {
|
||||
if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
|
||||
entityResource.getById($scope.lastOpenedNode, "media")
|
||||
.then(ensureWithinStartNode, gotoStartNode);
|
||||
} else {
|
||||
gotoStartNode();
|
||||
}
|
||||
} else {
|
||||
//if a target is specified, go look it up - generally this target will just contain ids not the actual full
|
||||
//media object so we need to look it up
|
||||
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
|
||||
var altText = $scope.target.altText;
|
||||
if (id) {
|
||||
mediaResource.getById(id)
|
||||
.then(function (node) {
|
||||
$scope.target = node;
|
||||
if (ensureWithinStartNode(node)) {
|
||||
selectImage(node);
|
||||
$scope.target.url = mediaHelper.resolveFile(node);
|
||||
$scope.target.altText = altText;
|
||||
$scope.openDetailsDialog();
|
||||
}
|
||||
},
|
||||
gotoStartNode);
|
||||
} else {
|
||||
gotoStartNode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$scope.upload = function(v) {
|
||||
angular.element(".umb-file-dropzone-directive .file-select").click();
|
||||
};
|
||||
|
||||
$scope.dragLeave = function(el, event) {
|
||||
$scope.activeDrag = false;
|
||||
};
|
||||
|
||||
$scope.dragEnter = function(el, event) {
|
||||
$scope.activeDrag = true;
|
||||
};
|
||||
|
||||
$scope.submitFolder = function() {
|
||||
if ($scope.newFolderName) {
|
||||
$scope.creatingFolder = true;
|
||||
mediaResource
|
||||
.addFolder($scope.newFolderName, $scope.currentFolder.id)
|
||||
.then(function(data) {
|
||||
//we've added a new folder so lets clear the tree cache for that specific item
|
||||
treeService.clearCache({
|
||||
cacheKey: "__media", //this is the main media tree cache key
|
||||
childrenOf: data.parentId //clear the children of the parent
|
||||
});
|
||||
$scope.creatingFolder = false;
|
||||
$scope.gotoFolder(data);
|
||||
$scope.showFolderInput = false;
|
||||
$scope.newFolderName = "";
|
||||
});
|
||||
} else {
|
||||
$scope.showFolderInput = false;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.enterSubmitFolder = function(event) {
|
||||
if (event.keyCode === 13) {
|
||||
$scope.submitFolder();
|
||||
event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.gotoFolder = function(folder) {
|
||||
if (!$scope.multiPicker) {
|
||||
deselectAllImages($scope.model.selectedImages);
|
||||
}
|
||||
|
||||
if (!folder) {
|
||||
folder = { id: -1, name: "Media", icon: "icon-folder" };
|
||||
}
|
||||
|
||||
if (folder.id > 0) {
|
||||
entityResource.getAncestors(folder.id, "media", { ignoreUserStartNodes: $scope.model.ignoreUserStartNodes })
|
||||
.then(function(anc) {
|
||||
$scope.path = _.filter(anc,
|
||||
function(f) {
|
||||
return f.path.indexOf($scope.startNodeId) !== -1;
|
||||
});
|
||||
});
|
||||
|
||||
} else {
|
||||
$scope.path = [];
|
||||
}
|
||||
|
||||
mediaTypeHelper.getAllowedImagetypes(folder.id)
|
||||
.then(function (types) {
|
||||
$scope.acceptedMediatypes = types;
|
||||
});
|
||||
|
||||
$scope.lockedFolder = (folder.id === -1 && $scope.model.startNodeIsVirtual) || hasFolderAccess(folder) === false;
|
||||
|
||||
$scope.currentFolder = folder;
|
||||
localStorageService.set("umbLastOpenedMediaNodeId", folder.id);
|
||||
return getChildren(folder.id);
|
||||
};
|
||||
|
||||
$scope.clickHandler = function(image, event, index) {
|
||||
if (image.isFolder) {
|
||||
if ($scope.disableFolderSelect) {
|
||||
$scope.gotoFolder(image);
|
||||
} else {
|
||||
eventsService.emit("dialogs.mediaPicker.select", image);
|
||||
selectImage(image);
|
||||
}
|
||||
} else {
|
||||
eventsService.emit("dialogs.mediaPicker.select", image);
|
||||
if ($scope.showDetails) {
|
||||
|
||||
$scope.target = image;
|
||||
|
||||
// handle both entity and full media object
|
||||
if (image.image) {
|
||||
$scope.target.url = image.image;
|
||||
} else {
|
||||
$scope.target.url = mediaHelper.resolveFile(image);
|
||||
}
|
||||
|
||||
$scope.openDetailsDialog();
|
||||
} else {
|
||||
selectImage(image);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.clickItemName = function(item) {
|
||||
if (item.isFolder) {
|
||||
$scope.gotoFolder(item);
|
||||
}
|
||||
};
|
||||
|
||||
function selectImage(image) {
|
||||
if (image.selected) {
|
||||
for (var i = 0; $scope.model.selectedImages.length > i; i++) {
|
||||
var imageInSelection = $scope.model.selectedImages[i];
|
||||
if (image.key === imageInSelection.key) {
|
||||
image.selected = false;
|
||||
$scope.model.selectedImages.splice(i, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!$scope.multiPicker) {
|
||||
deselectAllImages($scope.model.selectedImages);
|
||||
}
|
||||
image.selected = true;
|
||||
$scope.model.selectedImages.push(image);
|
||||
}
|
||||
}
|
||||
|
||||
function deselectAllImages(images) {
|
||||
for (var i = 0; i < images.length; i++) {
|
||||
var image = images[i];
|
||||
image.selected = false;
|
||||
}
|
||||
images.length = 0;
|
||||
}
|
||||
|
||||
$scope.onUploadComplete = function(files) {
|
||||
$scope.gotoFolder($scope.currentFolder).then(function() {
|
||||
if (files.length === 1 && $scope.model.selectedImages.length === 0) {
|
||||
var image = $scope.images[$scope.images.length - 1];
|
||||
$scope.target = image;
|
||||
$scope.target.url = mediaHelper.resolveFile(image);
|
||||
selectImage(image);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.onFilesQueue = function() {
|
||||
$scope.activeDrag = false;
|
||||
};
|
||||
|
||||
function ensureWithinStartNode(node) {
|
||||
// make sure that last opened node is on the same path as start node
|
||||
var nodePath = node.path.split(",");
|
||||
|
||||
// also make sure the node is not trashed
|
||||
if (nodePath.indexOf($scope.startNodeId.toString()) !== -1 && node.trashed === false) {
|
||||
$scope.gotoFolder({ id: $scope.lastOpenedNode, name: "Media", icon: "icon-folder" });
|
||||
return true;
|
||||
} else {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function hasFolderAccess(node) {
|
||||
var nodePath = node.path ? node.path.split(',') : [node.id];
|
||||
|
||||
for (var i = 0; i < nodePath.length; i++) {
|
||||
if (userStartNodes.indexOf(parseInt(nodePath[i])) !== -1)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function gotoStartNode(err) {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
}
|
||||
|
||||
$scope.openDetailsDialog = function() {
|
||||
|
||||
$scope.mediaPickerDetailsOverlay = {};
|
||||
$scope.mediaPickerDetailsOverlay.show = true;
|
||||
|
||||
$scope.mediaPickerDetailsOverlay.submit = function(model) {
|
||||
$scope.model.selectedImages.push($scope.target);
|
||||
$scope.model.submit($scope.model);
|
||||
|
||||
$scope.mediaPickerDetailsOverlay.show = false;
|
||||
$scope.mediaPickerDetailsOverlay = null;
|
||||
};
|
||||
|
||||
$scope.mediaPickerDetailsOverlay.close = function(oldModel) {
|
||||
$scope.mediaPickerDetailsOverlay.show = false;
|
||||
$scope.mediaPickerDetailsOverlay = null;
|
||||
};
|
||||
};
|
||||
|
||||
var debounceSearchMedia = _.debounce(function() {
|
||||
$scope.$apply(function() {
|
||||
if ($scope.searchOptions.filter) {
|
||||
searchMedia();
|
||||
} else {
|
||||
// reset pagination
|
||||
$scope.searchOptions = {
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
filter: '',
|
||||
ignoreUserStartNodes: $scope.model.ignoreUserStartNodes
|
||||
};
|
||||
getChildren($scope.currentFolder.id);
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
|
||||
$scope.changeSearch = function() {
|
||||
$scope.loading = true;
|
||||
debounceSearchMedia();
|
||||
};
|
||||
|
||||
$scope.toggle = function() {
|
||||
// Make sure to activate the changeSearch function everytime the toggle is clicked
|
||||
$scope.changeSearch();
|
||||
}
|
||||
|
||||
$scope.changePagination = function(pageNumber) {
|
||||
$scope.loading = true;
|
||||
$scope.searchOptions.pageNumber = pageNumber;
|
||||
searchMedia();
|
||||
};
|
||||
|
||||
function searchMedia() {
|
||||
$scope.loading = true;
|
||||
entityResource.getPagedDescendants($scope.currentFolder.id, "Media", $scope.searchOptions)
|
||||
.then(function(data) {
|
||||
// update image data to work with image grid
|
||||
angular.forEach(data.items,
|
||||
function(mediaItem) {
|
||||
// set thumbnail and src
|
||||
mediaItem.thumbnail = mediaHelper.resolveFileFromEntity(mediaItem, true);
|
||||
mediaItem.image = mediaHelper.resolveFileFromEntity(mediaItem, false);
|
||||
// set properties to match a media object
|
||||
mediaItem.properties = [];
|
||||
if (mediaItem.metaData) {
|
||||
if (mediaItem.metaData.umbracoWidth && mediaItem.metaData.umbracoHeight) {
|
||||
mediaItem.properties.push({
|
||||
alias: "umbracoWidth",
|
||||
value: mediaItem.metaData.umbracoWidth.Value
|
||||
});
|
||||
mediaItem.properties.push({
|
||||
alias: "umbracoHeight",
|
||||
value: mediaItem.metaData.umbracoHeight.Value
|
||||
});
|
||||
}
|
||||
if (mediaItem.metaData.umbracoFile) {
|
||||
mediaItem.properties.push({
|
||||
alias: "umbracoFile",
|
||||
editor: mediaItem.metaData.umbracoFile.PropertyEditorAlias,
|
||||
value: mediaItem.metaData.umbracoFile.Value
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
// update images
|
||||
$scope.images = data.items ? data.items : [];
|
||||
// update pagination
|
||||
if (data.pageNumber > 0)
|
||||
$scope.searchOptions.pageNumber = data.pageNumber;
|
||||
if (data.pageSize > 0)
|
||||
$scope.searchOptions.pageSize = data.pageSize;
|
||||
$scope.searchOptions.totalItems = data.totalItems;
|
||||
$scope.searchOptions.totalPages = data.totalPages;
|
||||
// set already selected images to selected
|
||||
preSelectImages();
|
||||
$scope.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
function getChildren(id) {
|
||||
$scope.loading = true;
|
||||
return mediaResource.getChildren(id, { ignoreUserStartNodes: $scope.model.ignoreUserStartNodes })
|
||||
.then(function(data) {
|
||||
$scope.searchOptions.filter = "";
|
||||
$scope.images = data.items ? data.items : [];
|
||||
// set already selected images to selected
|
||||
preSelectImages();
|
||||
$scope.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
function preSelectImages() {
|
||||
for (var folderImageIndex = 0; folderImageIndex < $scope.images.length; folderImageIndex++) {
|
||||
var folderImage = $scope.images[folderImageIndex];
|
||||
var imageIsSelected = false;
|
||||
|
||||
if ($scope.model && angular.isArray($scope.model.selectedImages)) {
|
||||
for (var selectedImageIndex = 0;
|
||||
selectedImageIndex < $scope.model.selectedImages.length;
|
||||
selectedImageIndex++) {
|
||||
var selectedImage = $scope.model.selectedImages[selectedImageIndex];
|
||||
|
||||
if (folderImage.key === selectedImage.key) {
|
||||
imageIsSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (imageIsSelected) {
|
||||
folderImage.selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onInit();
|
||||
|
||||
});
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Overlays.MediaPickerController",
|
||||
function ($scope, mediaResource, umbRequestHelper, entityResource, $log, mediaHelper, mediaTypeHelper, eventsService, treeService, $element, $timeout, userService, $cookies, localStorageService, localizationService) {
|
||||
|
||||
if (!$scope.model.title) {
|
||||
$scope.model.title = localizationService.localize("defaultdialogs_selectMedia");
|
||||
}
|
||||
|
||||
var dialogOptions = $scope.model;
|
||||
|
||||
$scope.disableFolderSelect = dialogOptions.disableFolderSelect;
|
||||
$scope.onlyImages = dialogOptions.onlyImages;
|
||||
$scope.showDetails = dialogOptions.showDetails;
|
||||
$scope.multiPicker = (dialogOptions.multiPicker && dialogOptions.multiPicker !== "0") ? true : false;
|
||||
$scope.startNodeId = dialogOptions.startNodeId ? dialogOptions.startNodeId : -1;
|
||||
$scope.cropSize = dialogOptions.cropSize;
|
||||
$scope.lastOpenedNode = localStorageService.get("umbLastOpenedMediaNodeId");
|
||||
$scope.lockedFolder = true;
|
||||
|
||||
var userStartNodes = [];
|
||||
|
||||
var umbracoSettings = Umbraco.Sys.ServerVariables.umbracoSettings;
|
||||
var allowedUploadFiles = mediaHelper.formatFileTypes(umbracoSettings.allowedUploadFiles);
|
||||
if ($scope.onlyImages) {
|
||||
$scope.acceptedFileTypes = mediaHelper.formatFileTypes(umbracoSettings.imageFileTypes);
|
||||
} else {
|
||||
// Use whitelist of allowed file types if provided
|
||||
if (allowedUploadFiles !== '') {
|
||||
$scope.acceptedFileTypes = allowedUploadFiles;
|
||||
} else {
|
||||
// If no whitelist, we pass in a blacklist by adding ! to the file extensions, allowing everything EXCEPT for disallowedUploadFiles
|
||||
$scope.acceptedFileTypes = !mediaHelper.formatFileTypes(umbracoSettings.disallowedUploadFiles);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.maxFileSize = umbracoSettings.maxFileSize + "KB";
|
||||
|
||||
$scope.model.selectedImages = [];
|
||||
|
||||
$scope.acceptedMediatypes = [];
|
||||
mediaTypeHelper.getAllowedImagetypes($scope.startNodeId)
|
||||
.then(function (types) {
|
||||
$scope.acceptedMediatypes = types;
|
||||
});
|
||||
|
||||
var dataTypeId = null;
|
||||
if($scope.model && $scope.model.dataTypeId) {
|
||||
dataTypeId = $scope.model.dataTypeId;
|
||||
}
|
||||
$scope.searchOptions = {
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
filter: '',
|
||||
dataTypeId: dataTypeId
|
||||
};
|
||||
|
||||
//preload selected item
|
||||
$scope.target = undefined;
|
||||
if (dialogOptions.currentTarget) {
|
||||
$scope.target = dialogOptions.currentTarget;
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
userService.getCurrentUser().then(function (userData) {
|
||||
userStartNodes = userData.startMediaIds;
|
||||
|
||||
if ($scope.startNodeId !== -1) {
|
||||
entityResource.getById($scope.startNodeId, "media")
|
||||
.then(function (ent) {
|
||||
$scope.startNodeId = ent.id;
|
||||
run();
|
||||
});
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function run() {
|
||||
//default root item
|
||||
if (!$scope.target) {
|
||||
if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
|
||||
entityResource.getById($scope.lastOpenedNode, "media")
|
||||
.then(ensureWithinStartNode, gotoStartNode);
|
||||
} else {
|
||||
gotoStartNode();
|
||||
}
|
||||
} else {
|
||||
//if a target is specified, go look it up - generally this target will just contain ids not the actual full
|
||||
//media object so we need to look it up
|
||||
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
|
||||
var altText = $scope.target.altText;
|
||||
if (id) {
|
||||
entityResource.getById(id, "Media")
|
||||
.then(function (node) {
|
||||
$scope.target = node;
|
||||
if (ensureWithinStartNode(node)) {
|
||||
selectImage(node);
|
||||
$scope.target.url = mediaHelper.resolveFile(node);
|
||||
$scope.target.altText = altText;
|
||||
$scope.openDetailsDialog();
|
||||
}
|
||||
},
|
||||
gotoStartNode);
|
||||
} else {
|
||||
gotoStartNode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$scope.upload = function (v) {
|
||||
angular.element(".umb-file-dropzone-directive .file-select").click();
|
||||
};
|
||||
|
||||
$scope.dragLeave = function (el, event) {
|
||||
$scope.activeDrag = false;
|
||||
};
|
||||
|
||||
$scope.dragEnter = function (el, event) {
|
||||
$scope.activeDrag = true;
|
||||
};
|
||||
|
||||
$scope.submitFolder = function () {
|
||||
if ($scope.newFolderName) {
|
||||
$scope.creatingFolder = true;
|
||||
mediaResource
|
||||
.addFolder($scope.newFolderName, $scope.currentFolder.id)
|
||||
.then(function (data) {
|
||||
//we've added a new folder so lets clear the tree cache for that specific item
|
||||
treeService.clearCache({
|
||||
cacheKey: "__media", //this is the main media tree cache key
|
||||
childrenOf: data.parentId //clear the children of the parent
|
||||
});
|
||||
$scope.creatingFolder = false;
|
||||
$scope.gotoFolder(data);
|
||||
$scope.showFolderInput = false;
|
||||
$scope.newFolderName = "";
|
||||
});
|
||||
} else {
|
||||
$scope.showFolderInput = false;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.enterSubmitFolder = function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
$scope.submitFolder();
|
||||
event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.gotoFolder = function (folder) {
|
||||
if (!$scope.multiPicker) {
|
||||
deselectAllImages($scope.model.selectedImages);
|
||||
}
|
||||
|
||||
if (!folder) {
|
||||
folder = { id: -1, name: "Media", icon: "icon-folder" };
|
||||
}
|
||||
|
||||
if (folder.id > 0) {
|
||||
|
||||
entityResource.getAncestors(folder.id, "media", { dataTypeId: dataTypeId })
|
||||
.then(function (anc) {
|
||||
$scope.path = _.filter(anc,
|
||||
function (f) {
|
||||
return f.path.indexOf($scope.startNodeId) !== -1;
|
||||
});
|
||||
});
|
||||
|
||||
} else {
|
||||
$scope.path = [];
|
||||
}
|
||||
|
||||
mediaTypeHelper.getAllowedImagetypes(folder.id)
|
||||
.then(function (types) {
|
||||
$scope.acceptedMediatypes = types;
|
||||
});
|
||||
|
||||
$scope.lockedFolder = (folder.id === -1 && $scope.model.startNodeIsVirtual) || hasFolderAccess(folder) === false;
|
||||
|
||||
$scope.currentFolder = folder;
|
||||
localStorageService.set("umbLastOpenedMediaNodeId", folder.id);
|
||||
return getChildren(folder.id);
|
||||
};
|
||||
|
||||
$scope.clickHandler = function (image, event, index) {
|
||||
if (image.isFolder) {
|
||||
if ($scope.disableFolderSelect) {
|
||||
$scope.gotoFolder(image);
|
||||
} else {
|
||||
eventsService.emit("dialogs.mediaPicker.select", image);
|
||||
selectImage(image);
|
||||
}
|
||||
} else {
|
||||
eventsService.emit("dialogs.mediaPicker.select", image);
|
||||
if ($scope.showDetails) {
|
||||
|
||||
$scope.target = image;
|
||||
|
||||
// handle both entity and full media object
|
||||
if (image.image) {
|
||||
$scope.target.url = image.image;
|
||||
} else {
|
||||
$scope.target.url = mediaHelper.resolveFile(image);
|
||||
}
|
||||
|
||||
$scope.openDetailsDialog();
|
||||
} else {
|
||||
selectImage(image);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.clickItemName = function (item) {
|
||||
if (item.isFolder) {
|
||||
$scope.gotoFolder(item);
|
||||
}
|
||||
};
|
||||
|
||||
function selectImage(image) {
|
||||
if (image.selected) {
|
||||
for (var i = 0; $scope.model.selectedImages.length > i; i++) {
|
||||
var imageInSelection = $scope.model.selectedImages[i];
|
||||
if (image.key === imageInSelection.key) {
|
||||
image.selected = false;
|
||||
$scope.model.selectedImages.splice(i, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!$scope.multiPicker) {
|
||||
deselectAllImages($scope.model.selectedImages);
|
||||
}
|
||||
image.selected = true;
|
||||
$scope.model.selectedImages.push(image);
|
||||
}
|
||||
}
|
||||
|
||||
function deselectAllImages(images) {
|
||||
for (var i = 0; i < images.length; i++) {
|
||||
var image = images[i];
|
||||
image.selected = false;
|
||||
}
|
||||
images.length = 0;
|
||||
}
|
||||
|
||||
$scope.onUploadComplete = function (files) {
|
||||
$scope.gotoFolder($scope.currentFolder).then(function () {
|
||||
if (files.length === 1 && $scope.model.selectedImages.length === 0) {
|
||||
var image = $scope.images[$scope.images.length - 1];
|
||||
$scope.target = image;
|
||||
$scope.target.url = mediaHelper.resolveFile(image);
|
||||
selectImage(image);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.onFilesQueue = function () {
|
||||
$scope.activeDrag = false;
|
||||
};
|
||||
|
||||
function ensureWithinStartNode(node) {
|
||||
// make sure that last opened node is on the same path as start node
|
||||
var nodePath = node.path.split(",");
|
||||
|
||||
// also make sure the node is not trashed
|
||||
if (nodePath.indexOf($scope.startNodeId.toString()) !== -1 && node.trashed === false) {
|
||||
$scope.gotoFolder({ id: $scope.lastOpenedNode, name: "Media", icon: "icon-folder", path: node.path });
|
||||
return true;
|
||||
} else {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function hasFolderAccess(node) {
|
||||
var nodePath = node.path ? node.path.split(',') : [node.id];
|
||||
|
||||
for (var i = 0; i < nodePath.length; i++) {
|
||||
if (userStartNodes.indexOf(parseInt(nodePath[i])) !== -1)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function gotoStartNode(err) {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
}
|
||||
|
||||
$scope.openDetailsDialog = function () {
|
||||
|
||||
$scope.mediaPickerDetailsOverlay = {};
|
||||
$scope.mediaPickerDetailsOverlay.show = true;
|
||||
|
||||
$scope.mediaPickerDetailsOverlay.submit = function (model) {
|
||||
$scope.model.selectedImages.push($scope.target);
|
||||
$scope.model.submit($scope.model);
|
||||
|
||||
$scope.mediaPickerDetailsOverlay.show = false;
|
||||
$scope.mediaPickerDetailsOverlay = null;
|
||||
};
|
||||
|
||||
$scope.mediaPickerDetailsOverlay.close = function (oldModel) {
|
||||
$scope.mediaPickerDetailsOverlay.show = false;
|
||||
$scope.mediaPickerDetailsOverlay = null;
|
||||
};
|
||||
};
|
||||
|
||||
var debounceSearchMedia = _.debounce(function () {
|
||||
$scope.$apply(function () {
|
||||
if ($scope.searchOptions.filter) {
|
||||
searchMedia();
|
||||
} else {
|
||||
|
||||
// reset pagination
|
||||
$scope.searchOptions = {
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
filter: '',
|
||||
dataTypeId: dataTypeId
|
||||
};
|
||||
getChildren($scope.currentFolder.id);
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
|
||||
$scope.changeSearch = function () {
|
||||
$scope.loading = true;
|
||||
debounceSearchMedia();
|
||||
};
|
||||
|
||||
$scope.toggle = function () {
|
||||
// Make sure to activate the changeSearch function everytime the toggle is clicked
|
||||
$scope.changeSearch();
|
||||
}
|
||||
|
||||
$scope.changePagination = function (pageNumber) {
|
||||
$scope.loading = true;
|
||||
$scope.searchOptions.pageNumber = pageNumber;
|
||||
searchMedia();
|
||||
};
|
||||
|
||||
function searchMedia() {
|
||||
$scope.loading = true;
|
||||
entityResource.getPagedDescendants($scope.currentFolder.id, "Media", $scope.searchOptions)
|
||||
.then(function (data) {
|
||||
// update image data to work with image grid
|
||||
angular.forEach(data.items,
|
||||
function (mediaItem) {
|
||||
// set thumbnail and src
|
||||
mediaItem.thumbnail = mediaHelper.resolveFileFromEntity(mediaItem, true);
|
||||
mediaItem.image = mediaHelper.resolveFileFromEntity(mediaItem, false);
|
||||
// set properties to match a media object
|
||||
mediaItem.properties = [];
|
||||
if (mediaItem.metaData) {
|
||||
if (mediaItem.metaData.umbracoWidth && mediaItem.metaData.umbracoHeight) {
|
||||
mediaItem.properties.push({
|
||||
alias: "umbracoWidth",
|
||||
value: mediaItem.metaData.umbracoWidth.Value
|
||||
});
|
||||
mediaItem.properties.push({
|
||||
alias: "umbracoHeight",
|
||||
value: mediaItem.metaData.umbracoHeight.Value
|
||||
});
|
||||
}
|
||||
if (mediaItem.metaData.umbracoFile) {
|
||||
mediaItem.properties.push({
|
||||
alias: "umbracoFile",
|
||||
editor: mediaItem.metaData.umbracoFile.PropertyEditorAlias,
|
||||
value: mediaItem.metaData.umbracoFile.Value
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
// update images
|
||||
$scope.images = data.items ? data.items : [];
|
||||
// update pagination
|
||||
if (data.pageNumber > 0)
|
||||
$scope.searchOptions.pageNumber = data.pageNumber;
|
||||
if (data.pageSize > 0)
|
||||
$scope.searchOptions.pageSize = data.pageSize;
|
||||
$scope.searchOptions.totalItems = data.totalItems;
|
||||
$scope.searchOptions.totalPages = data.totalPages;
|
||||
// set already selected images to selected
|
||||
preSelectImages();
|
||||
$scope.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
function getChildren(id) {
|
||||
$scope.loading = true;
|
||||
return entityResource.getChildren(id, "Media", $scope.searchOptions)
|
||||
.then(function (data) {
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (data[i].metaData.MediaPath !== null) {
|
||||
data[i].thumbnail = mediaHelper.resolveFileFromEntity(data[i], true);
|
||||
data[i].image = mediaHelper.resolveFileFromEntity(data[i], false);
|
||||
}
|
||||
}
|
||||
$scope.searchOptions.filter = "";
|
||||
$scope.images = data ? data : [];
|
||||
// set already selected images to selected
|
||||
preSelectImages();
|
||||
$scope.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
function preSelectImages() {
|
||||
for (var folderImageIndex = 0; folderImageIndex < $scope.images.length; folderImageIndex++) {
|
||||
var folderImage = $scope.images[folderImageIndex];
|
||||
var imageIsSelected = false;
|
||||
|
||||
if ($scope.model && angular.isArray($scope.model.selectedImages)) {
|
||||
for (var selectedImageIndex = 0;
|
||||
selectedImageIndex < $scope.model.selectedImages.length;
|
||||
selectedImageIndex++) {
|
||||
var selectedImage = $scope.model.selectedImages[selectedImageIndex];
|
||||
|
||||
if (folderImage.key === selectedImage.key) {
|
||||
imageIsSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (imageIsSelected) {
|
||||
folderImage.selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onInit();
|
||||
|
||||
});
|
||||
|
||||
+531
-530
File diff suppressed because it is too large
Load Diff
@@ -1,56 +1,56 @@
|
||||
<div ng-controller="Umbraco.Overlays.TreePickerController">
|
||||
|
||||
<div ng-hide="miniListView">
|
||||
|
||||
<div class="umb-control-group">
|
||||
<umb-tree-search-box
|
||||
ng-if="enableSearh"
|
||||
hide-search-callback="hideSearch"
|
||||
search-callback="onSearchResults"
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
ignore-user-startnodes="{{searchInfo.ignoreUserStartNodes}}"
|
||||
section="{{section}}">
|
||||
</umb-tree-search-box>
|
||||
</div>
|
||||
|
||||
<umb-tree-search-results
|
||||
ng-if="searchInfo.showSearch"
|
||||
results="searchInfo.results"
|
||||
select-result-callback="selectResult">
|
||||
</umb-tree-search-results>
|
||||
|
||||
<umb-empty-state ng-if="!hasItems && emptyStateMessage" position="center">
|
||||
{{ emptyStateMessage }}
|
||||
</umb-empty-state>
|
||||
|
||||
<div ng-if="treeReady" ng-hide="searchInfo.showSearch" ng-animate="'tree-fade-out'">
|
||||
<umb-tree
|
||||
section="{{section}}"
|
||||
treealias="{{treeAlias}}"
|
||||
hideheader="{{hideHeader}}"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
onlyinitialized="{{onlyInitialized}}"
|
||||
customtreeparams="{{customTreeParams}}"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablelistviewsearch="true"
|
||||
enablelistviewexpand="true"
|
||||
enablecheckboxes="{{multiPicker}}">
|
||||
</umb-tree>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<umb-mini-list-view
|
||||
ng-if="miniListView"
|
||||
node="miniListView"
|
||||
entity-type="{{entityType}}"
|
||||
start-node-id="model.startNodeId"
|
||||
on-select="selectListViewNode(node)"
|
||||
on-close="closeMiniListView()"
|
||||
entity-type-filter="filter">
|
||||
</umb-mini-list-view>
|
||||
|
||||
</div>
|
||||
<div ng-controller="Umbraco.Overlays.TreePickerController">
|
||||
|
||||
<div ng-hide="miniListView">
|
||||
|
||||
<div class="umb-control-group">
|
||||
<umb-tree-search-box
|
||||
ng-if="enableSearh"
|
||||
hide-search-callback="hideSearch"
|
||||
search-callback="onSearchResults"
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
datatype-id="{{searchInfo.dataTypeId}}"
|
||||
section="{{section}}">
|
||||
</umb-tree-search-box>
|
||||
</div>
|
||||
|
||||
<umb-tree-search-results
|
||||
ng-if="searchInfo.showSearch"
|
||||
results="searchInfo.results"
|
||||
select-result-callback="selectResult">
|
||||
</umb-tree-search-results>
|
||||
|
||||
<umb-empty-state ng-if="!hasItems && emptyStateMessage" position="center">
|
||||
{{ emptyStateMessage }}
|
||||
</umb-empty-state>
|
||||
|
||||
<div ng-if="treeReady" ng-hide="searchInfo.showSearch" ng-animate="'tree-fade-out'">
|
||||
<umb-tree
|
||||
section="{{section}}"
|
||||
treealias="{{treeAlias}}"
|
||||
hideheader="{{hideHeader}}"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
onlyinitialized="{{onlyInitialized}}"
|
||||
customtreeparams="{{customTreeParams}}"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablelistviewsearch="true"
|
||||
enablelistviewexpand="true"
|
||||
enablecheckboxes="{{multiPicker}}">
|
||||
</umb-tree>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<umb-mini-list-view
|
||||
ng-if="miniListView"
|
||||
node="miniListView"
|
||||
entity-type="{{entityType}}"
|
||||
start-node-id="model.startNodeId"
|
||||
on-select="selectListViewNode(node)"
|
||||
on-close="closeMiniListView()"
|
||||
entity-type-filter="filter">
|
||||
</umb-mini-list-view>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -133,7 +133,7 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS
|
||||
|
||||
//anytime a user is changing a member's password without the oldPassword, we are in effect resetting it so we need to set that flag here
|
||||
var passwordProp = _.find(contentEditingHelper.getAllProps($scope.content), function (e) { return e.alias === '_umb_password' });
|
||||
if (!passwordProp.value.reset) {
|
||||
if (passwordProp && passwordProp.value && !passwordProp.value.reset) {
|
||||
//so if the admin is not explicitly resetting the password, flag it for resetting if a new password is being entered
|
||||
passwordProp.value.reset = !passwordProp.value.oldPassword && passwordProp.config.allowManuallyChangingPassword;
|
||||
}
|
||||
|
||||
+367
-366
@@ -1,366 +1,367 @@
|
||||
//this controller simply tells the dialogs service to open a mediaPicker window
|
||||
//with a specified callback, this callback will receive an object with a selection on it
|
||||
|
||||
function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, miniEditorHelper, localizationService) {
|
||||
|
||||
var unsubscribe;
|
||||
|
||||
function subscribe() {
|
||||
unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
});
|
||||
$scope.model.value = trim(currIds.join(), ",");
|
||||
});
|
||||
}
|
||||
|
||||
function trim(str, chr) {
|
||||
var rgxtrim = (!chr) ? new RegExp('^\\s+|\\s+$', 'g') : new RegExp('^' + chr + '+|' + chr + '+$', 'g');
|
||||
return str.replace(rgxtrim, '');
|
||||
}
|
||||
|
||||
function startWatch() {
|
||||
//We need to watch our renderModel so that we can update the underlying $scope.model.value properly, this is required
|
||||
// because the ui-sortable doesn't dispatch an event after the digest of the sort operation. Any of the events for UI sortable
|
||||
// occur after the DOM has updated but BEFORE the digest has occured so the model has NOT changed yet - it even states so in the docs.
|
||||
// In their source code there is no event so we need to just subscribe to our model changes here.
|
||||
//This also makes it easier to manage models, we update one and the rest will just work.
|
||||
$scope.$watch(function () {
|
||||
//return the joined Ids as a string to watch
|
||||
return _.map($scope.renderModel, function (i) {
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
}).join();
|
||||
}, function (newVal) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
});
|
||||
$scope.model.value = trim(currIds.join(), ",");
|
||||
|
||||
//Validate!
|
||||
if ($scope.model.config && $scope.model.config.minNumber && parseInt($scope.model.config.minNumber) > $scope.renderModel.length) {
|
||||
$scope.contentPickerForm.minCount.$setValidity("minCount", false);
|
||||
}
|
||||
else {
|
||||
$scope.contentPickerForm.minCount.$setValidity("minCount", true);
|
||||
}
|
||||
|
||||
if ($scope.model.config && $scope.model.config.maxNumber && parseInt($scope.model.config.maxNumber) < $scope.renderModel.length) {
|
||||
$scope.contentPickerForm.maxCount.$setValidity("maxCount", false);
|
||||
}
|
||||
else {
|
||||
$scope.contentPickerForm.maxCount.$setValidity("maxCount", true);
|
||||
}
|
||||
|
||||
setSortingState($scope.renderModel);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$scope.renderModel = [];
|
||||
|
||||
$scope.dialogEditor = editorState && editorState.current && editorState.current.isDialogEditor === true;
|
||||
|
||||
//the default pre-values
|
||||
var defaultConfig = {
|
||||
multiPicker: false,
|
||||
showOpenButton: false,
|
||||
showEditButton: false,
|
||||
showPathOnHover: false,
|
||||
ignoreUserStartNodes: false,
|
||||
maxNumber: 1,
|
||||
minNumber : 0,
|
||||
startNode: {
|
||||
query: "",
|
||||
type: "content",
|
||||
id: $scope.model.config.startNodeId ? $scope.model.config.startNodeId : -1 // get start node for simple Content Picker
|
||||
}
|
||||
};
|
||||
|
||||
// sortable options
|
||||
$scope.sortableOptions = {
|
||||
axis: "y",
|
||||
containment: "parent",
|
||||
distance: 10,
|
||||
opacity: 0.7,
|
||||
tolerance: "pointer",
|
||||
scroll: true,
|
||||
zIndex: 6000,
|
||||
update: function (e, ui) {
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
}
|
||||
};
|
||||
|
||||
if ($scope.model.config) {
|
||||
//merge the server config on top of the default config, then set the server config to use the result
|
||||
$scope.model.config = angular.extend(defaultConfig, $scope.model.config);
|
||||
}
|
||||
|
||||
//Umbraco persists boolean for prevalues as "0" or "1" so we need to convert that!
|
||||
$scope.model.config.multiPicker = ($scope.model.config.multiPicker === "1" ? true : false);
|
||||
$scope.model.config.showOpenButton = ($scope.model.config.showOpenButton === "1" ? true : false);
|
||||
$scope.model.config.showEditButton = ($scope.model.config.showEditButton === "1" ? true : false);
|
||||
$scope.model.config.showPathOnHover = ($scope.model.config.showPathOnHover === "1" ? true : false);
|
||||
$scope.model.config.ignoreUserStartNodes = ($scope.model.config.ignoreUserStartNodes === "1" ? true : false);
|
||||
|
||||
var entityType = $scope.model.config.startNode.type === "member"
|
||||
? "Member"
|
||||
: $scope.model.config.startNode.type === "media"
|
||||
? "Media"
|
||||
: "Document";
|
||||
$scope.allowOpenButton = entityType === "Document";
|
||||
$scope.allowEditButton = entityType === "Document";
|
||||
$scope.allowRemoveButton = true;
|
||||
|
||||
//the dialog options for the picker
|
||||
var dialogOptions = {
|
||||
multiPicker: $scope.model.config.multiPicker,
|
||||
entityType: entityType,
|
||||
filterCssClass: "not-allowed not-published",
|
||||
startNodeId: null,
|
||||
currentNode: editorState ? editorState.current : null,
|
||||
callback: function (data) {
|
||||
if (angular.isArray(data)) {
|
||||
_.each(data, function (item, i) {
|
||||
$scope.add(item);
|
||||
});
|
||||
} else {
|
||||
$scope.clear();
|
||||
$scope.add(data);
|
||||
}
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
},
|
||||
treeAlias: $scope.model.config.startNode.type,
|
||||
section: $scope.model.config.startNode.type,
|
||||
idType: "int"
|
||||
};
|
||||
|
||||
//since most of the pre-value config's are used in the dialog options (i.e. maxNumber, minNumber, etc...) we'll merge the
|
||||
// pre-value config on to the dialog options
|
||||
angular.extend(dialogOptions, $scope.model.config);
|
||||
|
||||
//We need to manually handle the filter for members here since the tree displayed is different and only contains
|
||||
// searchable list views
|
||||
if (entityType === "Member") {
|
||||
//first change the not allowed filter css class
|
||||
dialogOptions.filterCssClass = "not-allowed";
|
||||
var currFilter = dialogOptions.filter;
|
||||
//now change the filter to be a method
|
||||
dialogOptions.filter = function(i) {
|
||||
//filter out the list view nodes
|
||||
if (i.metaData.isContainer) {
|
||||
return true;
|
||||
}
|
||||
if (!currFilter) {
|
||||
return false;
|
||||
}
|
||||
//now we need to filter based on what is stored in the pre-vals, this logic duplicates what is in the treepicker.controller,
|
||||
// but not much we can do about that since members require special filtering.
|
||||
var filterItem = currFilter.toLowerCase().split(',');
|
||||
var found = filterItem.indexOf(i.metaData.contentType.toLowerCase()) >= 0;
|
||||
if (!currFilter.startsWith("!") && !found || currFilter.startsWith("!") && found) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($routeParams.section === "settings" && $routeParams.tree === "documentTypes") {
|
||||
//if the content-picker is being rendered inside the document-type editor, we don't need to process the startnode query
|
||||
dialogOptions.startNodeId = -1;
|
||||
} else if ($scope.model.config.startNode.query) {
|
||||
//if we have a query for the startnode, we will use that.
|
||||
var rootId = $routeParams.id;
|
||||
entityResource.getByQuery($scope.model.config.startNode.query, rootId, "Document").then(function (ent) {
|
||||
dialogOptions.startNodeId = $scope.model.config.idType === "udi" ? ent.udi : ent.id;
|
||||
});
|
||||
}
|
||||
else {
|
||||
dialogOptions.startNodeId = $scope.model.config.startNode.id;
|
||||
}
|
||||
|
||||
//dialog
|
||||
$scope.openContentPicker = function() {
|
||||
$scope.contentPickerOverlay = dialogOptions;
|
||||
$scope.contentPickerOverlay.view = "treepicker";
|
||||
$scope.contentPickerOverlay.show = true;
|
||||
|
||||
$scope.contentPickerOverlay.submit = function(model) {
|
||||
|
||||
if (angular.isArray(model.selection)) {
|
||||
_.each(model.selection, function (item, i) {
|
||||
$scope.add(item);
|
||||
});
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
}
|
||||
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
}
|
||||
|
||||
$scope.contentPickerOverlay.close = function(oldModel) {
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$scope.remove = function (index) {
|
||||
$scope.renderModel.splice(index, 1);
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
};
|
||||
|
||||
$scope.showNode = function (index) {
|
||||
var item = $scope.renderModel[index];
|
||||
var id = item.id;
|
||||
var section = $scope.model.config.startNode.type.toLowerCase();
|
||||
|
||||
entityResource.getPath(id, entityType).then(function (path) {
|
||||
navigationService.changeSection(section);
|
||||
navigationService.showTree(section, {
|
||||
tree: section, path: path, forceReload: false, activate: true
|
||||
});
|
||||
var routePath = section + "/" + section + "/edit/" + id.toString();
|
||||
$location.path(routePath).search("");
|
||||
});
|
||||
}
|
||||
|
||||
$scope.add = function (item) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
});
|
||||
|
||||
var itemId = $scope.model.config.idType === "udi" ? item.udi : item.id;
|
||||
|
||||
if (currIds.indexOf(itemId) < 0) {
|
||||
setEntityUrl(item);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.clear = function () {
|
||||
$scope.renderModel = [];
|
||||
};
|
||||
|
||||
$scope.openMiniEditor = function(node) {
|
||||
miniEditorHelper.launchMiniEditor(node).then(function(updatedNode){
|
||||
// update the node
|
||||
node.name = updatedNode.name;
|
||||
node.published = updatedNode.hasPublishedVersion;
|
||||
if(entityType !== "Member") {
|
||||
entityResource.getUrl(updatedNode.id, entityType).then(function(data){
|
||||
node.url = data;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//when the scope is destroyed we need to unsubscribe
|
||||
$scope.$on('$destroy', function () {
|
||||
if(unsubscribe) {
|
||||
unsubscribe();
|
||||
}
|
||||
});
|
||||
|
||||
var modelIds = $scope.model.value ? $scope.model.value.split(',') : [];
|
||||
|
||||
//load current data if anything selected
|
||||
if (modelIds.length > 0) {
|
||||
entityResource.getByIds(modelIds, entityType).then(function(data) {
|
||||
|
||||
_.each(modelIds,
|
||||
function(id, i) {
|
||||
var entity = _.find(data,
|
||||
function(d) {
|
||||
return $scope.model.config.idType === "udi" ? (d.udi == id) : (d.id == id);
|
||||
});
|
||||
|
||||
if (entity) {
|
||||
setEntityUrl(entity);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//everything is loaded, start the watch on the model
|
||||
startWatch();
|
||||
subscribe();
|
||||
});
|
||||
}
|
||||
else {
|
||||
//everything is loaded, start the watch on the model
|
||||
startWatch();
|
||||
subscribe();
|
||||
}
|
||||
|
||||
function setEntityUrl(entity) {
|
||||
|
||||
// get url for content and media items
|
||||
if(entityType !== "Member") {
|
||||
entityResource.getUrl(entity.id, entityType).then(function(data){
|
||||
// update url
|
||||
angular.forEach($scope.renderModel, function(item){
|
||||
if (item.id === entity.id) {
|
||||
if (entity.trashed) {
|
||||
item.url = localizationService.dictionary.general_recycleBin;
|
||||
} else {
|
||||
item.url = data;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// add the selected item to the renderModel
|
||||
// if it needs to show a url the item will get
|
||||
// updated when the url comes back from server
|
||||
addSelectedItem(entity);
|
||||
|
||||
}
|
||||
|
||||
function addSelectedItem(item) {
|
||||
|
||||
// set icon
|
||||
if(item.icon) {
|
||||
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
|
||||
}
|
||||
|
||||
// set default icon
|
||||
if (!item.icon) {
|
||||
switch (entityType) {
|
||||
case "Document":
|
||||
item.icon = "icon-document";
|
||||
break;
|
||||
case "Media":
|
||||
item.icon = "icon-picture";
|
||||
break;
|
||||
case "Member":
|
||||
item.icon = "icon-user";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.renderModel.push({
|
||||
"name": item.name,
|
||||
"id": item.id,
|
||||
"udi": item.udi,
|
||||
"icon": item.icon,
|
||||
"path": item.path,
|
||||
"url": item.url,
|
||||
"trashed": item.trashed,
|
||||
"published": (item.metaData && item.metaData.IsPublished === false && entityType === "Document") ? false : true
|
||||
// only content supports published/unpublished content so we set everything else to published so the UI looks correct
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function setSortingState(items) {
|
||||
// disable sorting if the list only consist of one item
|
||||
if(items.length > 1) {
|
||||
$scope.sortableOptions.disabled = false;
|
||||
} else {
|
||||
$scope.sortableOptions.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco').controller("Umbraco.PropertyEditors.ContentPickerController", contentPickerController);
|
||||
//this controller simply tells the dialogs service to open a mediaPicker window
|
||||
//with a specified callback, this callback will receive an object with a selection on it
|
||||
|
||||
function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, miniEditorHelper, localizationService) {
|
||||
|
||||
var unsubscribe;
|
||||
|
||||
function subscribe() {
|
||||
unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
});
|
||||
$scope.model.value = trim(currIds.join(), ",");
|
||||
});
|
||||
}
|
||||
|
||||
function trim(str, chr) {
|
||||
var rgxtrim = (!chr) ? new RegExp('^\\s+|\\s+$', 'g') : new RegExp('^' + chr + '+|' + chr + '+$', 'g');
|
||||
return str.replace(rgxtrim, '');
|
||||
}
|
||||
|
||||
function startWatch() {
|
||||
//We need to watch our renderModel so that we can update the underlying $scope.model.value properly, this is required
|
||||
// because the ui-sortable doesn't dispatch an event after the digest of the sort operation. Any of the events for UI sortable
|
||||
// occur after the DOM has updated but BEFORE the digest has occured so the model has NOT changed yet - it even states so in the docs.
|
||||
// In their source code there is no event so we need to just subscribe to our model changes here.
|
||||
//This also makes it easier to manage models, we update one and the rest will just work.
|
||||
$scope.$watch(function () {
|
||||
//return the joined Ids as a string to watch
|
||||
return _.map($scope.renderModel, function (i) {
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
}).join();
|
||||
}, function (newVal) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
});
|
||||
$scope.model.value = trim(currIds.join(), ",");
|
||||
|
||||
//Validate!
|
||||
if ($scope.model.config && $scope.model.config.minNumber && parseInt($scope.model.config.minNumber) > $scope.renderModel.length) {
|
||||
$scope.contentPickerForm.minCount.$setValidity("minCount", false);
|
||||
}
|
||||
else {
|
||||
$scope.contentPickerForm.minCount.$setValidity("minCount", true);
|
||||
}
|
||||
|
||||
if ($scope.model.config && $scope.model.config.maxNumber && parseInt($scope.model.config.maxNumber) < $scope.renderModel.length) {
|
||||
$scope.contentPickerForm.maxCount.$setValidity("maxCount", false);
|
||||
}
|
||||
else {
|
||||
$scope.contentPickerForm.maxCount.$setValidity("maxCount", true);
|
||||
}
|
||||
|
||||
setSortingState($scope.renderModel);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$scope.renderModel = [];
|
||||
|
||||
$scope.dialogEditor = editorState && editorState.current && editorState.current.isDialogEditor === true;
|
||||
|
||||
//the default pre-values
|
||||
var defaultConfig = {
|
||||
multiPicker: false,
|
||||
showOpenButton: false,
|
||||
showEditButton: false,
|
||||
showPathOnHover: false,
|
||||
dataTypeId: null,
|
||||
maxNumber: 1,
|
||||
minNumber: 0,
|
||||
startNode: {
|
||||
query: "",
|
||||
type: "content",
|
||||
id: $scope.model.config.startNodeId ? $scope.model.config.startNodeId : -1 // get start node for simple Content Picker
|
||||
}
|
||||
};
|
||||
|
||||
// sortable options
|
||||
$scope.sortableOptions = {
|
||||
axis: "y",
|
||||
containment: "parent",
|
||||
distance: 10,
|
||||
opacity: 0.7,
|
||||
tolerance: "pointer",
|
||||
scroll: true,
|
||||
zIndex: 6000,
|
||||
update: function (e, ui) {
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
}
|
||||
};
|
||||
|
||||
if ($scope.model.config) {
|
||||
//merge the server config on top of the default config, then set the server config to use the result
|
||||
$scope.model.config = angular.extend(defaultConfig, $scope.model.config);
|
||||
}
|
||||
|
||||
//Umbraco persists boolean for prevalues as "0" or "1" so we need to convert that!
|
||||
$scope.model.config.multiPicker = ($scope.model.config.multiPicker === "1" ? true : false);
|
||||
$scope.model.config.showOpenButton = ($scope.model.config.showOpenButton === "1" ? true : false);
|
||||
$scope.model.config.showEditButton = ($scope.model.config.showEditButton === "1" ? true : false);
|
||||
$scope.model.config.showPathOnHover = ($scope.model.config.showPathOnHover === "1" ? true : false);
|
||||
|
||||
var entityType = $scope.model.config.startNode.type === "member"
|
||||
? "Member"
|
||||
: $scope.model.config.startNode.type === "media"
|
||||
? "Media"
|
||||
: "Document";
|
||||
$scope.allowOpenButton = entityType === "Document";
|
||||
$scope.allowEditButton = entityType === "Document";
|
||||
$scope.allowRemoveButton = true;
|
||||
|
||||
//the dialog options for the picker
|
||||
var dialogOptions = {
|
||||
multiPicker: $scope.model.config.multiPicker,
|
||||
entityType: entityType,
|
||||
filterCssClass: "not-allowed not-published",
|
||||
startNodeId: null,
|
||||
currentNode: editorState ? editorState.current : null,
|
||||
callback: function (data) {
|
||||
if (angular.isArray(data)) {
|
||||
_.each(data, function (item, i) {
|
||||
$scope.add(item);
|
||||
});
|
||||
} else {
|
||||
$scope.clear();
|
||||
$scope.add(data);
|
||||
}
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
},
|
||||
treeAlias: $scope.model.config.startNode.type,
|
||||
section: $scope.model.config.startNode.type,
|
||||
idType: "int"
|
||||
};
|
||||
|
||||
//since most of the pre-value config's are used in the dialog options (i.e. maxNumber, minNumber, etc...) we'll merge the
|
||||
// pre-value config on to the dialog options
|
||||
angular.extend(dialogOptions, $scope.model.config);
|
||||
|
||||
//We need to manually handle the filter for members here since the tree displayed is different and only contains
|
||||
// searchable list views
|
||||
if (entityType === "Member") {
|
||||
//first change the not allowed filter css class
|
||||
dialogOptions.filterCssClass = "not-allowed";
|
||||
var currFilter = dialogOptions.filter;
|
||||
//now change the filter to be a method
|
||||
dialogOptions.filter = function (i) {
|
||||
//filter out the list view nodes
|
||||
if (i.metaData.isContainer) {
|
||||
return true;
|
||||
}
|
||||
if (!currFilter) {
|
||||
return false;
|
||||
}
|
||||
//now we need to filter based on what is stored in the pre-vals, this logic duplicates what is in the treepicker.controller,
|
||||
// but not much we can do about that since members require special filtering.
|
||||
var filterItem = currFilter.toLowerCase().split(',');
|
||||
var found = filterItem.indexOf(i.metaData.contentType.toLowerCase()) >= 0;
|
||||
if (!currFilter.startsWith("!") && !found || currFilter.startsWith("!") && found) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($routeParams.section === "settings" && $routeParams.tree === "documentTypes") {
|
||||
//if the content-picker is being rendered inside the document-type editor, we don't need to process the startnode query
|
||||
dialogOptions.startNodeId = -1;
|
||||
} else if ($scope.model.config.startNode.query) {
|
||||
//if we have a query for the startnode, we will use that.
|
||||
var rootId = $routeParams.id;
|
||||
entityResource.getByQuery($scope.model.config.startNode.query, rootId, "Document").then(function (ent) {
|
||||
dialogOptions.startNodeId = $scope.model.config.idType === "udi" ? ent.udi : ent.id;
|
||||
});
|
||||
}
|
||||
else {
|
||||
dialogOptions.startNodeId = $scope.model.config.startNode.id;
|
||||
}
|
||||
|
||||
//dialog
|
||||
$scope.openContentPicker = function () {
|
||||
|
||||
$scope.contentPickerOverlay = dialogOptions;
|
||||
$scope.contentPickerOverlay.view = "treepicker";
|
||||
$scope.contentPickerOverlay.show = true;
|
||||
$scope.contentPickerOverlay.dataTypeId = ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null;
|
||||
|
||||
$scope.contentPickerOverlay.submit = function (model) {
|
||||
|
||||
if (angular.isArray(model.selection)) {
|
||||
_.each(model.selection, function (item, i) {
|
||||
$scope.add(item);
|
||||
});
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
}
|
||||
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
}
|
||||
|
||||
$scope.contentPickerOverlay.close = function (oldModel) {
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$scope.remove = function (index) {
|
||||
$scope.renderModel.splice(index, 1);
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
};
|
||||
|
||||
$scope.showNode = function (index) {
|
||||
var item = $scope.renderModel[index];
|
||||
var id = item.id;
|
||||
var section = $scope.model.config.startNode.type.toLowerCase();
|
||||
|
||||
entityResource.getPath(id, entityType).then(function (path) {
|
||||
navigationService.changeSection(section);
|
||||
navigationService.showTree(section, {
|
||||
tree: section, path: path, forceReload: false, activate: true
|
||||
});
|
||||
var routePath = section + "/" + section + "/edit/" + id.toString();
|
||||
$location.path(routePath).search("");
|
||||
});
|
||||
}
|
||||
|
||||
$scope.add = function (item) {
|
||||
var currIds = _.map($scope.renderModel, function (i) {
|
||||
return $scope.model.config.idType === "udi" ? i.udi : i.id;
|
||||
});
|
||||
|
||||
var itemId = $scope.model.config.idType === "udi" ? item.udi : item.id;
|
||||
|
||||
if (currIds.indexOf(itemId) < 0) {
|
||||
setEntityUrl(item);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.clear = function () {
|
||||
$scope.renderModel = [];
|
||||
};
|
||||
|
||||
$scope.openMiniEditor = function (node) {
|
||||
miniEditorHelper.launchMiniEditor(node).then(function (updatedNode) {
|
||||
// update the node
|
||||
node.name = updatedNode.name;
|
||||
node.published = updatedNode.hasPublishedVersion;
|
||||
if (entityType !== "Member") {
|
||||
entityResource.getUrl(updatedNode.id, entityType).then(function (data) {
|
||||
node.url = data;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//when the scope is destroyed we need to unsubscribe
|
||||
$scope.$on('$destroy', function () {
|
||||
if (unsubscribe) {
|
||||
unsubscribe();
|
||||
}
|
||||
});
|
||||
|
||||
var modelIds = $scope.model.value ? $scope.model.value.split(',') : [];
|
||||
|
||||
//load current data if anything selected
|
||||
if (modelIds.length > 0) {
|
||||
entityResource.getByIds(modelIds, entityType).then(function (data) {
|
||||
|
||||
_.each(modelIds,
|
||||
function (id, i) {
|
||||
var entity = _.find(data,
|
||||
function (d) {
|
||||
return $scope.model.config.idType === "udi" ? (d.udi == id) : (d.id == id);
|
||||
});
|
||||
|
||||
if (entity) {
|
||||
setEntityUrl(entity);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//everything is loaded, start the watch on the model
|
||||
startWatch();
|
||||
subscribe();
|
||||
});
|
||||
}
|
||||
else {
|
||||
//everything is loaded, start the watch on the model
|
||||
startWatch();
|
||||
subscribe();
|
||||
}
|
||||
|
||||
function setEntityUrl(entity) {
|
||||
|
||||
// get url for content and media items
|
||||
if (entityType !== "Member") {
|
||||
entityResource.getUrl(entity.id, entityType).then(function (data) {
|
||||
// update url
|
||||
angular.forEach($scope.renderModel, function (item) {
|
||||
if (item.id === entity.id) {
|
||||
if (entity.trashed) {
|
||||
item.url = localizationService.dictionary.general_recycleBin;
|
||||
} else {
|
||||
item.url = data;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// add the selected item to the renderModel
|
||||
// if it needs to show a url the item will get
|
||||
// updated when the url comes back from server
|
||||
addSelectedItem(entity);
|
||||
|
||||
}
|
||||
|
||||
function addSelectedItem(item) {
|
||||
|
||||
// set icon
|
||||
if (item.icon) {
|
||||
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
|
||||
}
|
||||
|
||||
// set default icon
|
||||
if (!item.icon) {
|
||||
switch (entityType) {
|
||||
case "Document":
|
||||
item.icon = "icon-document";
|
||||
break;
|
||||
case "Media":
|
||||
item.icon = "icon-picture";
|
||||
break;
|
||||
case "Member":
|
||||
item.icon = "icon-user";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.renderModel.push({
|
||||
"name": item.name,
|
||||
"id": item.id,
|
||||
"udi": item.udi,
|
||||
"icon": item.icon,
|
||||
"path": item.path,
|
||||
"url": item.url,
|
||||
"trashed": item.trashed,
|
||||
"published": (item.metaData && item.metaData.IsPublished === false && entityType === "Document") ? false : true
|
||||
// only content supports published/unpublished content so we set everything else to published so the UI looks correct
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function setSortingState(items) {
|
||||
// disable sorting if the list only consist of one item
|
||||
if (items.length > 1) {
|
||||
$scope.sortableOptions.disabled = false;
|
||||
} else {
|
||||
$scope.sortableOptions.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco').controller("Umbraco.PropertyEditors.ContentPickerController", contentPickerController);
|
||||
|
||||
+6
-7
@@ -1,11 +1,9 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.PropertyEditors.Grid.MediaController",
|
||||
function ($scope, $rootScope, $timeout, userService) {
|
||||
|
||||
var ignoreUserStartNodes = $scope.model.config.ignoreUserStartNodes === "1" ? true : false;
|
||||
|
||||
if (!$scope.model.config.startNodeId) {
|
||||
if (ignoreUserStartNodes === true) {
|
||||
if ($scope.model.config.ignoreUserStartNodes === "1" ) {
|
||||
$scope.model.config.startNodeId = -1;
|
||||
$scope.model.config.startNodeIsVirtual = true;
|
||||
|
||||
@@ -18,12 +16,13 @@ angular.module("umbraco")
|
||||
}
|
||||
|
||||
$scope.setImage = function(){
|
||||
|
||||
$scope.mediaPickerOverlay = {};
|
||||
$scope.mediaPickerOverlay.view = "mediapicker";
|
||||
$scope.mediaPickerOverlay.startNodeId = $scope.model.config && $scope.model.config.startNodeId ? $scope.model.config.startNodeId : undefined;
|
||||
$scope.mediaPickerOverlay.startNodeIsVirtual = $scope.mediaPickerOverlay.startNodeId ? $scope.model.config.startNodeIsVirtual : undefined;
|
||||
$scope.mediaPickerOverlay.ignoreUserStartNodes = ignoreUserStartNodes;
|
||||
$scope.mediaPickerOverlay.cropSize = $scope.control.editor.config && $scope.control.editor.config.size ? $scope.control.editor.config.size : undefined;
|
||||
$scope.mediaPickerOverlay.startNodeId = $scope.model.config && $scope.model.config.startNodeId ? $scope.model.config.startNodeId : null;
|
||||
$scope.mediaPickerOverlay.startNodeIsVirtual = $scope.mediaPickerOverlay.startNodeId ? $scope.model.config.startNodeIsVirtual : null;
|
||||
$scope.mediaPickerOverlay.dataTypeId = ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null;
|
||||
$scope.mediaPickerOverlay.cropSize = $scope.control.editor.config && $scope.control.editor.config.size ? $scope.control.editor.config.size : null;
|
||||
$scope.mediaPickerOverlay.showDetails = true;
|
||||
$scope.mediaPickerOverlay.disableFolderSelect = true;
|
||||
$scope.mediaPickerOverlay.onlyImages = true;
|
||||
|
||||
+24
-18
@@ -1,7 +1,7 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
function GridRichTextEditorController($scope, tinyMceService, macroService, editorState) {
|
||||
function GridRichTextEditorController($scope, tinyMceService, macroService, editorState, entityResource) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
@@ -10,29 +10,35 @@
|
||||
vm.openMacroPicker = openMacroPicker;
|
||||
vm.openEmbed = openEmbed;
|
||||
|
||||
var dataTypeId = ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null;
|
||||
|
||||
function openLinkPicker(editor, currentTarget, anchorElement) {
|
||||
|
||||
vm.linkPickerOverlay = {
|
||||
view: "linkpicker",
|
||||
currentTarget: currentTarget,
|
||||
anchors: tinyMceService.getAnchorNames(JSON.stringify(editorState.current.properties)),
|
||||
ignoreUserStartNodes: $scope.model.config.ignoreUserStartNodes === "1",
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
tinyMceService.insertLinkInEditor(editor, model.target, anchorElement);
|
||||
vm.linkPickerOverlay.show = false;
|
||||
vm.linkPickerOverlay = null;
|
||||
}
|
||||
};
|
||||
|
||||
entityResource.getAnchors(JSON.stringify($scope.model.value)).then(function(anchorValues) {
|
||||
|
||||
vm.linkPickerOverlay = {
|
||||
view: "linkpicker",
|
||||
currentTarget: currentTarget,
|
||||
anchors: anchorValues,
|
||||
dataTypeId: dataTypeId,
|
||||
ignoreUserStartNodes : $scope.model.config.ignoreUserStartNodes,
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
tinyMceService.insertLinkInEditor(editor, model.target, anchorElement);
|
||||
vm.linkPickerOverlay.show = false;
|
||||
vm.linkPickerOverlay = null;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function openMediaPicker(editor, currentTarget, userData) {
|
||||
var ignoreUserStartNodes = false;
|
||||
var startNodeId = userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0];
|
||||
var startNodeIsVirtual = userData.startMediaIds.length !== 1;
|
||||
|
||||
|
||||
if ($scope.model.config.ignoreUserStartNodes === "1") {
|
||||
ignoreUserStartNodes = true;
|
||||
startNodeId = -1;
|
||||
startNodeIsVirtual = true;
|
||||
}
|
||||
@@ -40,10 +46,10 @@
|
||||
vm.mediaPickerOverlay = {
|
||||
currentTarget: currentTarget,
|
||||
onlyImages: true,
|
||||
showDetails: true,
|
||||
showDetails: true,
|
||||
startNodeId: startNodeId,
|
||||
startNodeIsVirtual: startNodeIsVirtual,
|
||||
ignoreUserStartNodes: ignoreUserStartNodes,
|
||||
dataTypeId: dataTypeId,
|
||||
view: "mediapicker",
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
|
||||
+185
-184
@@ -1,184 +1,185 @@
|
||||
//this controller simply tells the dialogs service to open a mediaPicker window
|
||||
//with a specified callback, this callback will receive an object with a selection on it
|
||||
angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerController",
|
||||
function ($rootScope, $scope, dialogService, entityResource, mediaResource, mediaHelper, $timeout, userService, $location, localizationService) {
|
||||
|
||||
//check the pre-values for multi-picker
|
||||
var multiPicker = $scope.model.config.multiPicker && $scope.model.config.multiPicker !== '0' ? true : false;
|
||||
var onlyImages = $scope.model.config.onlyImages && $scope.model.config.onlyImages !== '0' ? true : false;
|
||||
var disableFolderSelect = $scope.model.config.disableFolderSelect && $scope.model.config.disableFolderSelect !== '0' ? true : false;
|
||||
var ignoreUserStartNodes = $scope.model.config.ignoreUserStartNodes === "1" ? true : false;
|
||||
|
||||
if (!$scope.model.config.startNodeId) {
|
||||
if (ignoreUserStartNodes === true) {
|
||||
$scope.model.config.startNodeId = -1;
|
||||
$scope.model.config.startNodeIsVirtual = true;
|
||||
|
||||
} else {
|
||||
userService.getCurrentUser().then(function (userData) {
|
||||
$scope.model.config.startNodeId = userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0];
|
||||
$scope.model.config.startNodeIsVirtual = userData.startMediaIds.length !== 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setupViewModel() {
|
||||
$scope.mediaItems = [];
|
||||
$scope.ids = [];
|
||||
|
||||
$scope.isMultiPicker = multiPicker;
|
||||
|
||||
if ($scope.model.value) {
|
||||
var ids = $scope.model.value.split(',');
|
||||
|
||||
//NOTE: We need to use the entityResource NOT the mediaResource here because
|
||||
// the mediaResource has server side auth configured for which the user must have
|
||||
// access to the media section, if they don't they'll get auth errors. The entityResource
|
||||
// acts differently in that it allows access if the user has access to any of the apps that
|
||||
// might require it's use. Therefore we need to use the metaData property to get at the thumbnail
|
||||
// value.
|
||||
|
||||
entityResource.getByIds(ids, "Media").then(function(medias) {
|
||||
|
||||
// The service only returns item results for ids that exist (deleted items are silently ignored).
|
||||
// This results in the picked items value to be set to contain only ids of picked items that could actually be found.
|
||||
// Since a referenced item could potentially be restored later on, instead of changing the selected values here based
|
||||
// on whether the items exist during a save event - we should keep "placeholder" items for picked items that currently
|
||||
// could not be fetched. This will preserve references and ensure that the state of an item does not differ depending
|
||||
// on whether it is simply resaved or not.
|
||||
// This is done by remapping the int/guid ids into a new array of items, where we create "Deleted item" placeholders
|
||||
// when there is no match for a selected id. This will ensure that the values being set on save, are the same as before.
|
||||
|
||||
medias = _.map(ids,
|
||||
function(id) {
|
||||
var found = _.find(medias,
|
||||
function(m) {
|
||||
// We could use coercion (two ='s) here .. but not sure if this works equally well in all browsers and
|
||||
// it's prone to someone "fixing" it at some point without knowing the effects. Rather use toString()
|
||||
// compares and be completely sure it works.
|
||||
return m.udi.toString() === id.toString() || m.id.toString() === id.toString();
|
||||
});
|
||||
if (found) {
|
||||
return found;
|
||||
} else {
|
||||
return {
|
||||
name: localizationService.dictionary.mediaPicker_deletedItem,
|
||||
id: $scope.model.config.idType !== "udi" ? id : null,
|
||||
udi: $scope.model.config.idType === "udi" ? id : null,
|
||||
icon: "icon-picture",
|
||||
thumbnail: null,
|
||||
trashed: true
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
_.each(medias,
|
||||
function(media, i) {
|
||||
// if there is no thumbnail, try getting one if the media is not a placeholder item
|
||||
if (!media.thumbnail && media.id && media.metaData) {
|
||||
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
|
||||
}
|
||||
|
||||
$scope.mediaItems.push(media);
|
||||
|
||||
if ($scope.model.config.idType === "udi") {
|
||||
$scope.ids.push(media.udi);
|
||||
} else {
|
||||
$scope.ids.push(media.id);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.sync();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setupViewModel();
|
||||
|
||||
$scope.remove = function(index) {
|
||||
$scope.mediaItems.splice(index, 1);
|
||||
$scope.ids.splice(index, 1);
|
||||
$scope.sync();
|
||||
};
|
||||
|
||||
$scope.goToItem = function(item) {
|
||||
$location.path('media/media/edit/' + item.id);
|
||||
};
|
||||
|
||||
$scope.add = function() {
|
||||
|
||||
$scope.mediaPickerOverlay = {
|
||||
view: "mediapicker",
|
||||
title: "Select media",
|
||||
startNodeId: $scope.model.config.startNodeId,
|
||||
startNodeIsVirtual: $scope.model.config.startNodeIsVirtual,
|
||||
ignoreUserStartNodes: ignoreUserStartNodes,
|
||||
multiPicker: multiPicker,
|
||||
onlyImages: onlyImages,
|
||||
disableFolderSelect: disableFolderSelect,
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
|
||||
_.each(model.selectedImages, function(media, i) {
|
||||
// if there is no thumbnail, try getting one if the media is not a placeholder item
|
||||
if (!media.thumbnail && media.id && media.metaData) {
|
||||
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
|
||||
}
|
||||
|
||||
$scope.mediaItems.push(media);
|
||||
|
||||
if ($scope.model.config.idType === "udi") {
|
||||
$scope.ids.push(media.udi);
|
||||
}
|
||||
else {
|
||||
$scope.ids.push(media.id);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.sync();
|
||||
|
||||
$scope.mediaPickerOverlay.show = false;
|
||||
$scope.mediaPickerOverlay = null;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
$scope.sortableOptions = {
|
||||
disabled: !$scope.isMultiPicker,
|
||||
items: "li:not(.add-wrapper)",
|
||||
cancel: ".unsortable",
|
||||
update: function(e, ui) {
|
||||
var r = [];
|
||||
// TODO: Instead of doing this with a half second delay would be better to use a watch like we do in the
|
||||
// content picker. Then we don't have to worry about setting ids, render models, models, we just set one and let the
|
||||
// watch do all the rest.
|
||||
$timeout(function(){
|
||||
angular.forEach($scope.mediaItems, function(value, key) {
|
||||
r.push($scope.model.config.idType === "udi" ? value.udi : value.id);
|
||||
});
|
||||
$scope.ids = r;
|
||||
$scope.sync();
|
||||
}, 500, false);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.sync = function() {
|
||||
$scope.model.value = $scope.ids.join();
|
||||
};
|
||||
|
||||
$scope.showAdd = function () {
|
||||
if (!multiPicker) {
|
||||
if ($scope.model.value && $scope.model.value !== "") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server
|
||||
setupViewModel();
|
||||
};
|
||||
});
|
||||
//this controller simply tells the dialogs service to open a mediaPicker window
|
||||
//with a specified callback, this callback will receive an object with a selection on it
|
||||
angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerController",
|
||||
function ($rootScope, $scope, dialogService, entityResource, mediaHelper, $timeout, userService, $location, localizationService) {
|
||||
|
||||
//check the pre-values for multi-picker
|
||||
var multiPicker = $scope.model.config.multiPicker && $scope.model.config.multiPicker !== '0' ? true : false;
|
||||
var onlyImages = $scope.model.config.onlyImages && $scope.model.config.onlyImages !== '0' ? true : false;
|
||||
var disableFolderSelect = $scope.model.config.disableFolderSelect && $scope.model.config.disableFolderSelect !== '0' ? true : false;
|
||||
|
||||
if (!$scope.model.config.startNodeId) {
|
||||
|
||||
|
||||
if ( $scope.model.config.ignoreUserStartNodes === "1") {
|
||||
$scope.model.config.startNodeId = -1;
|
||||
$scope.model.config.startNodeIsVirtual = true;
|
||||
|
||||
} else {
|
||||
userService.getCurrentUser().then(function (userData) {
|
||||
$scope.model.config.startNodeId = userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0];
|
||||
$scope.model.config.startNodeIsVirtual = userData.startMediaIds.length !== 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setupViewModel() {
|
||||
$scope.mediaItems = [];
|
||||
$scope.ids = [];
|
||||
|
||||
$scope.isMultiPicker = multiPicker;
|
||||
|
||||
if ($scope.model.value) {
|
||||
var ids = $scope.model.value.split(',');
|
||||
|
||||
//NOTE: We need to use the entityResource NOT the mediaResource here because
|
||||
// the mediaResource has server side auth configured for which the user must have
|
||||
// access to the media section, if they don't they'll get auth errors. The entityResource
|
||||
// acts differently in that it allows access if the user has access to any of the apps that
|
||||
// might require it's use. Therefore we need to use the metaData property to get at the thumbnail
|
||||
// value.
|
||||
|
||||
entityResource.getByIds(ids, "Media").then(function(medias) {
|
||||
|
||||
// The service only returns item results for ids that exist (deleted items are silently ignored).
|
||||
// This results in the picked items value to be set to contain only ids of picked items that could actually be found.
|
||||
// Since a referenced item could potentially be restored later on, instead of changing the selected values here based
|
||||
// on whether the items exist during a save event - we should keep "placeholder" items for picked items that currently
|
||||
// could not be fetched. This will preserve references and ensure that the state of an item does not differ depending
|
||||
// on whether it is simply resaved or not.
|
||||
// This is done by remapping the int/guid ids into a new array of items, where we create "Deleted item" placeholders
|
||||
// when there is no match for a selected id. This will ensure that the values being set on save, are the same as before.
|
||||
|
||||
medias = _.map(ids,
|
||||
function(id) {
|
||||
var found = _.find(medias,
|
||||
function(m) {
|
||||
// We could use coercion (two ='s) here .. but not sure if this works equally well in all browsers and
|
||||
// it's prone to someone "fixing" it at some point without knowing the effects. Rather use toString()
|
||||
// compares and be completely sure it works.
|
||||
return m.udi.toString() === id.toString() || m.id.toString() === id.toString();
|
||||
});
|
||||
if (found) {
|
||||
return found;
|
||||
} else {
|
||||
return {
|
||||
name: localizationService.dictionary.mediaPicker_deletedItem,
|
||||
id: $scope.model.config.idType !== "udi" ? id : null,
|
||||
udi: $scope.model.config.idType === "udi" ? id : null,
|
||||
icon: "icon-picture",
|
||||
thumbnail: null,
|
||||
trashed: true
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
_.each(medias,
|
||||
function(media, i) {
|
||||
// if there is no thumbnail, try getting one if the media is not a placeholder item
|
||||
if (!media.thumbnail && media.id && media.metaData) {
|
||||
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
|
||||
}
|
||||
|
||||
$scope.mediaItems.push(media);
|
||||
|
||||
if ($scope.model.config.idType === "udi") {
|
||||
$scope.ids.push(media.udi);
|
||||
} else {
|
||||
$scope.ids.push(media.id);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.sync();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setupViewModel();
|
||||
|
||||
$scope.remove = function(index) {
|
||||
$scope.mediaItems.splice(index, 1);
|
||||
$scope.ids.splice(index, 1);
|
||||
$scope.sync();
|
||||
};
|
||||
|
||||
$scope.goToItem = function(item) {
|
||||
$location.path('media/media/edit/' + item.id);
|
||||
};
|
||||
|
||||
$scope.add = function() {
|
||||
|
||||
$scope.mediaPickerOverlay = {
|
||||
view: "mediapicker",
|
||||
title: "Select media",
|
||||
startNodeId: $scope.model.config.startNodeId,
|
||||
startNodeIsVirtual: $scope.model.config.startNodeIsVirtual,
|
||||
dataTypeId: ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null,
|
||||
multiPicker: multiPicker,
|
||||
onlyImages: onlyImages,
|
||||
disableFolderSelect: disableFolderSelect,
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
|
||||
_.each(model.selectedImages, function(media, i) {
|
||||
// if there is no thumbnail, try getting one if the media is not a placeholder item
|
||||
if (!media.thumbnail && media.id && media.metaData) {
|
||||
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
|
||||
}
|
||||
|
||||
$scope.mediaItems.push(media);
|
||||
|
||||
if ($scope.model.config.idType === "udi") {
|
||||
$scope.ids.push(media.udi);
|
||||
}
|
||||
else {
|
||||
$scope.ids.push(media.id);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.sync();
|
||||
|
||||
$scope.mediaPickerOverlay.show = false;
|
||||
$scope.mediaPickerOverlay = null;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
$scope.sortableOptions = {
|
||||
disabled: !$scope.isMultiPicker,
|
||||
items: "li:not(.add-wrapper)",
|
||||
cancel: ".unsortable",
|
||||
update: function(e, ui) {
|
||||
var r = [];
|
||||
// TODO: Instead of doing this with a half second delay would be better to use a watch like we do in the
|
||||
// content picker. Then we don't have to worry about setting ids, render models, models, we just set one and let the
|
||||
// watch do all the rest.
|
||||
$timeout(function(){
|
||||
angular.forEach($scope.mediaItems, function(value, key) {
|
||||
r.push($scope.model.config.idType === "udi" ? value.udi : value.id);
|
||||
});
|
||||
$scope.ids = r;
|
||||
$scope.sync();
|
||||
}, 500, false);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.sync = function() {
|
||||
$scope.model.value = $scope.ids.join();
|
||||
};
|
||||
|
||||
$scope.showAdd = function () {
|
||||
if (!multiPicker) {
|
||||
if ($scope.model.value && $scope.model.value !== "") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server
|
||||
setupViewModel();
|
||||
};
|
||||
});
|
||||
|
||||
+3
-2
@@ -67,11 +67,12 @@ function multiUrlPickerController($scope, angularHelper, localizationService, en
|
||||
url: link.url,
|
||||
target: link.target
|
||||
} : null;
|
||||
|
||||
|
||||
$scope.linkPickerOverlay = {
|
||||
view: "linkpicker",
|
||||
currentTarget: target,
|
||||
ignoreUserStartNodes: $scope.model.config.ignoreUserStartNodes === "1",
|
||||
dataTypeId: ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null,
|
||||
ignoreUserStartNodes : $scope.model.config.ignoreUserStartNodes,
|
||||
show: true,
|
||||
submit: function (model) {
|
||||
if (model.target.url || model.target.anchor) {
|
||||
|
||||
+246
-242
@@ -1,242 +1,246 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.PropertyEditors.RelatedLinksController",
|
||||
function ($rootScope, $scope, dialogService, iconHelper) {
|
||||
|
||||
if (!$scope.model.value) {
|
||||
$scope.model.value = [];
|
||||
}
|
||||
|
||||
$scope.model.config.max = isNumeric($scope.model.config.max) && $scope.model.config.max !== 0 ? $scope.model.config.max : Number.MAX_VALUE;
|
||||
|
||||
$scope.newCaption = '';
|
||||
$scope.newLink = 'http://';
|
||||
$scope.newNewWindow = false;
|
||||
$scope.newInternal = null;
|
||||
$scope.newInternalName = '';
|
||||
$scope.newInternalIcon = null;
|
||||
$scope.addExternal = true;
|
||||
$scope.currentEditLink = null;
|
||||
$scope.hasError = false;
|
||||
|
||||
$scope.internal = function($event) {
|
||||
$scope.currentEditLink = null;
|
||||
|
||||
$scope.contentPickerOverlay = {};
|
||||
$scope.contentPickerOverlay.view = "contentpicker";
|
||||
$scope.contentPickerOverlay.multiPicker = false;
|
||||
$scope.contentPickerOverlay.show = true;
|
||||
$scope.contentPickerOverlay.ignoreUserStartNodes = $scope.model.config.ignoreUserStartNodes === "1" ? true: false;
|
||||
$scope.contentPickerOverlay.idType = $scope.model.config.idType ? $scope.model.config.idType : "int";
|
||||
|
||||
$scope.contentPickerOverlay.submit = function(model) {
|
||||
|
||||
select(model.selection[0]);
|
||||
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
};
|
||||
|
||||
$scope.contentPickerOverlay.close = function(oldModel) {
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
};
|
||||
|
||||
$event.preventDefault();
|
||||
};
|
||||
|
||||
$scope.selectInternal = function ($event, link) {
|
||||
$scope.currentEditLink = link;
|
||||
|
||||
$scope.contentPickerOverlay = {};
|
||||
$scope.contentPickerOverlay.view = "contentpicker";
|
||||
$scope.contentPickerOverlay.multiPicker = false;
|
||||
$scope.contentPickerOverlay.show = true;
|
||||
$scope.contentPickerOverlay.ignoreUserStartNodes = $scope.model.config.ignoreUserStartNodes === "1" ? true : false;
|
||||
$scope.contentPickerOverlay.idType = $scope.model.config.idType ? $scope.model.config.idType : "int";
|
||||
|
||||
$scope.contentPickerOverlay.submit = function(model) {
|
||||
|
||||
select(model.selection[0]);
|
||||
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
};
|
||||
|
||||
$scope.contentPickerOverlay.close = function(oldModel) {
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
};
|
||||
|
||||
$event.preventDefault();
|
||||
|
||||
};
|
||||
|
||||
$scope.edit = function (idx) {
|
||||
for (var i = 0; i < $scope.model.value.length; i++) {
|
||||
$scope.model.value[i].edit = false;
|
||||
}
|
||||
$scope.model.value[idx].edit = true;
|
||||
};
|
||||
|
||||
$scope.saveEdit = function (idx) {
|
||||
$scope.model.value[idx].title = $scope.model.value[idx].caption;
|
||||
$scope.model.value[idx].edit = false;
|
||||
};
|
||||
|
||||
$scope.delete = function (idx) {
|
||||
$scope.model.value.splice(idx, 1);
|
||||
};
|
||||
|
||||
$scope.add = function ($event) {
|
||||
if (!angular.isArray($scope.model.value)) {
|
||||
$scope.model.value = [];
|
||||
}
|
||||
|
||||
if ($scope.newCaption == "") {
|
||||
$scope.hasError = true;
|
||||
} else {
|
||||
if ($scope.addExternal) {
|
||||
var newExtLink = new function() {
|
||||
this.caption = $scope.newCaption;
|
||||
this.link = $scope.newLink;
|
||||
this.newWindow = $scope.newNewWindow;
|
||||
this.edit = false;
|
||||
this.isInternal = false;
|
||||
this.type = "external";
|
||||
this.title = $scope.newCaption;
|
||||
};
|
||||
$scope.model.value.push(newExtLink);
|
||||
} else {
|
||||
var newIntLink = new function() {
|
||||
this.caption = $scope.newCaption;
|
||||
this.link = $scope.newInternal;
|
||||
this.newWindow = $scope.newNewWindow;
|
||||
this.internal = $scope.newInternal;
|
||||
this.edit = false;
|
||||
this.isInternal = true;
|
||||
this.internalName = $scope.newInternalName;
|
||||
this.internalIcon = $scope.newInternalIcon;
|
||||
this.type = "internal";
|
||||
this.title = $scope.newCaption;
|
||||
};
|
||||
$scope.model.value.push(newIntLink);
|
||||
}
|
||||
$scope.newCaption = '';
|
||||
$scope.newLink = 'http://';
|
||||
$scope.newNewWindow = false;
|
||||
$scope.newInternal = null;
|
||||
$scope.newInternalName = '';
|
||||
$scope.newInternalIcon = null;
|
||||
}
|
||||
$event.preventDefault();
|
||||
};
|
||||
|
||||
$scope.switch = function ($event) {
|
||||
$scope.addExternal = !$scope.addExternal;
|
||||
$event.preventDefault();
|
||||
};
|
||||
|
||||
$scope.switchLinkType = function ($event, link) {
|
||||
link.isInternal = !link.isInternal;
|
||||
link.type = link.isInternal ? "internal" : "external";
|
||||
if (!link.isInternal)
|
||||
link.link = $scope.newLink;
|
||||
$event.preventDefault();
|
||||
};
|
||||
|
||||
$scope.move = function (index, direction) {
|
||||
var temp = $scope.model.value[index];
|
||||
$scope.model.value[index] = $scope.model.value[index + direction];
|
||||
$scope.model.value[index + direction] = temp;
|
||||
};
|
||||
|
||||
//helper for determining if a user can add items
|
||||
$scope.canAdd = function () {
|
||||
return $scope.model.config.max <= 0 || $scope.model.config.max > countVisible();
|
||||
}
|
||||
|
||||
//helper that returns if an item can be sorted
|
||||
$scope.canSort = function () {
|
||||
return countVisible() > 1;
|
||||
}
|
||||
|
||||
$scope.sortableOptions = {
|
||||
axis: 'y',
|
||||
handle: '.handle',
|
||||
cursor: 'move',
|
||||
cancel: '.no-drag',
|
||||
containment: 'parent',
|
||||
placeholder: 'sortable-placeholder',
|
||||
forcePlaceholderSize: true,
|
||||
helper: function (e, ui) {
|
||||
// When sorting table rows, the cells collapse. This helper fixes that: https://www.foliotek.com/devblog/make-table-rows-sortable-using-jquery-ui-sortable/
|
||||
ui.children().each(function () {
|
||||
$(this).width($(this).width());
|
||||
});
|
||||
return ui;
|
||||
},
|
||||
items: '> tr:not(.unsortable)',
|
||||
tolerance: 'pointer',
|
||||
update: function (e, ui) {
|
||||
// Get the new and old index for the moved element (using the URL as the identifier)
|
||||
var newIndex = ui.item.index();
|
||||
var movedLinkUrl = ui.item.attr('data-link');
|
||||
var originalIndex = getElementIndexByUrl(movedLinkUrl);
|
||||
|
||||
// Move the element in the model
|
||||
var movedElement = $scope.model.value[originalIndex];
|
||||
$scope.model.value.splice(originalIndex, 1);
|
||||
$scope.model.value.splice(newIndex, 0, movedElement);
|
||||
},
|
||||
start: function (e, ui) {
|
||||
//ui.placeholder.html("<td colspan='5'></td>");
|
||||
|
||||
// Build a placeholder cell that spans all the cells in the row: https://stackoverflow.com/questions/25845310/jquery-ui-sortable-and-table-cell-size
|
||||
var cellCount = 0;
|
||||
$('td, th', ui.helper).each(function () {
|
||||
// For each td or th try and get it's colspan attribute, and add that or 1 to the total
|
||||
var colspan = 1;
|
||||
var colspanAttr = $(this).attr('colspan');
|
||||
if (colspanAttr > 1) {
|
||||
colspan = colspanAttr;
|
||||
}
|
||||
cellCount += colspan;
|
||||
});
|
||||
|
||||
// Add the placeholder UI - note that this is the item's content, so td rather than tr - and set height of tr
|
||||
ui.placeholder.html('<td colspan="' + cellCount + '"></td>').height(ui.item.height());
|
||||
}
|
||||
};
|
||||
|
||||
//helper to count what is visible
|
||||
function countVisible() {
|
||||
return $scope.model.value.length;
|
||||
}
|
||||
|
||||
function isNumeric(n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||
}
|
||||
|
||||
function getElementIndexByUrl(url) {
|
||||
for (var i = 0; i < $scope.model.value.length; i++) {
|
||||
if ($scope.model.value[i].link == url) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
function select(data) {
|
||||
if ($scope.currentEditLink != null) {
|
||||
$scope.currentEditLink.internal = $scope.model.config.idType === "udi" ? data.udi : data.id;
|
||||
$scope.currentEditLink.internalName = data.name;
|
||||
$scope.currentEditLink.internalIcon = iconHelper.convertFromLegacyIcon(data.icon);
|
||||
$scope.currentEditLink.link = $scope.model.config.idType === "udi" ? data.udi : data.id;
|
||||
} else {
|
||||
$scope.newInternal = $scope.model.config.idType === "udi" ? data.udi : data.id;
|
||||
$scope.newInternalName = data.name;
|
||||
$scope.newInternalIcon = iconHelper.convertFromLegacyIcon(data.icon);
|
||||
}
|
||||
}
|
||||
});
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.PropertyEditors.RelatedLinksController",
|
||||
function ($rootScope, $scope, dialogService, iconHelper) {
|
||||
|
||||
if (!$scope.model.value) {
|
||||
$scope.model.value = [];
|
||||
}
|
||||
|
||||
$scope.model.config.max = isNumeric($scope.model.config.max) && $scope.model.config.max !== 0 ? $scope.model.config.max : Number.MAX_VALUE;
|
||||
|
||||
$scope.newCaption = '';
|
||||
$scope.newLink = 'http://';
|
||||
$scope.newNewWindow = false;
|
||||
$scope.newInternal = null;
|
||||
$scope.newInternalName = '';
|
||||
$scope.newInternalIcon = null;
|
||||
$scope.addExternal = true;
|
||||
$scope.currentEditLink = null;
|
||||
$scope.hasError = false;
|
||||
|
||||
var dataTypeId = ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null;
|
||||
|
||||
$scope.internal = function($event) {
|
||||
|
||||
$scope.currentEditLink = null;
|
||||
|
||||
$scope.contentPickerOverlay = {};
|
||||
$scope.contentPickerOverlay.view = "contentpicker";
|
||||
$scope.contentPickerOverlay.multiPicker = false;
|
||||
$scope.contentPickerOverlay.show = true;
|
||||
$scope.contentPickerOverlay.dataTypeId = dataTypeId;
|
||||
$scope.contentPickerOverlay.idType = $scope.model.config.idType ? $scope.model.config.idType : "int";
|
||||
|
||||
$scope.contentPickerOverlay.submit = function(model) {
|
||||
|
||||
select(model.selection[0]);
|
||||
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
};
|
||||
|
||||
$scope.contentPickerOverlay.close = function(oldModel) {
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
};
|
||||
|
||||
$event.preventDefault();
|
||||
};
|
||||
|
||||
$scope.selectInternal = function ($event, link) {
|
||||
|
||||
$scope.currentEditLink = link;
|
||||
|
||||
$scope.contentPickerOverlay = {};
|
||||
$scope.contentPickerOverlay.view = "contentpicker";
|
||||
$scope.contentPickerOverlay.multiPicker = false;
|
||||
$scope.contentPickerOverlay.show = true;
|
||||
$scope.contentPickerOverlay.dataTypeId = dataTypeId;
|
||||
$scope.contentPickerOverlay.idType = $scope.model.config.idType ? $scope.model.config.idType : "int";
|
||||
|
||||
$scope.contentPickerOverlay.submit = function(model) {
|
||||
|
||||
select(model.selection[0]);
|
||||
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
};
|
||||
|
||||
$scope.contentPickerOverlay.close = function(oldModel) {
|
||||
$scope.contentPickerOverlay.show = false;
|
||||
$scope.contentPickerOverlay = null;
|
||||
};
|
||||
|
||||
$event.preventDefault();
|
||||
|
||||
};
|
||||
|
||||
$scope.edit = function (idx) {
|
||||
for (var i = 0; i < $scope.model.value.length; i++) {
|
||||
$scope.model.value[i].edit = false;
|
||||
}
|
||||
$scope.model.value[idx].edit = true;
|
||||
};
|
||||
|
||||
$scope.saveEdit = function (idx) {
|
||||
$scope.model.value[idx].title = $scope.model.value[idx].caption;
|
||||
$scope.model.value[idx].edit = false;
|
||||
};
|
||||
|
||||
$scope.delete = function (idx) {
|
||||
$scope.model.value.splice(idx, 1);
|
||||
};
|
||||
|
||||
$scope.add = function ($event) {
|
||||
if (!angular.isArray($scope.model.value)) {
|
||||
$scope.model.value = [];
|
||||
}
|
||||
|
||||
if ($scope.newCaption == "") {
|
||||
$scope.hasError = true;
|
||||
} else {
|
||||
if ($scope.addExternal) {
|
||||
var newExtLink = new function() {
|
||||
this.caption = $scope.newCaption;
|
||||
this.link = $scope.newLink;
|
||||
this.newWindow = $scope.newNewWindow;
|
||||
this.edit = false;
|
||||
this.isInternal = false;
|
||||
this.type = "external";
|
||||
this.title = $scope.newCaption;
|
||||
};
|
||||
$scope.model.value.push(newExtLink);
|
||||
} else {
|
||||
var newIntLink = new function() {
|
||||
this.caption = $scope.newCaption;
|
||||
this.link = $scope.newInternal;
|
||||
this.newWindow = $scope.newNewWindow;
|
||||
this.internal = $scope.newInternal;
|
||||
this.edit = false;
|
||||
this.isInternal = true;
|
||||
this.internalName = $scope.newInternalName;
|
||||
this.internalIcon = $scope.newInternalIcon;
|
||||
this.type = "internal";
|
||||
this.title = $scope.newCaption;
|
||||
};
|
||||
$scope.model.value.push(newIntLink);
|
||||
}
|
||||
$scope.newCaption = '';
|
||||
$scope.newLink = 'http://';
|
||||
$scope.newNewWindow = false;
|
||||
$scope.newInternal = null;
|
||||
$scope.newInternalName = '';
|
||||
$scope.newInternalIcon = null;
|
||||
}
|
||||
$event.preventDefault();
|
||||
};
|
||||
|
||||
$scope.switch = function ($event) {
|
||||
$scope.addExternal = !$scope.addExternal;
|
||||
$event.preventDefault();
|
||||
};
|
||||
|
||||
$scope.switchLinkType = function ($event, link) {
|
||||
link.isInternal = !link.isInternal;
|
||||
link.type = link.isInternal ? "internal" : "external";
|
||||
if (!link.isInternal)
|
||||
link.link = $scope.newLink;
|
||||
$event.preventDefault();
|
||||
};
|
||||
|
||||
$scope.move = function (index, direction) {
|
||||
var temp = $scope.model.value[index];
|
||||
$scope.model.value[index] = $scope.model.value[index + direction];
|
||||
$scope.model.value[index + direction] = temp;
|
||||
};
|
||||
|
||||
//helper for determining if a user can add items
|
||||
$scope.canAdd = function () {
|
||||
return $scope.model.config.max <= 0 || $scope.model.config.max > countVisible();
|
||||
}
|
||||
|
||||
//helper that returns if an item can be sorted
|
||||
$scope.canSort = function () {
|
||||
return countVisible() > 1;
|
||||
}
|
||||
|
||||
$scope.sortableOptions = {
|
||||
axis: 'y',
|
||||
handle: '.handle',
|
||||
cursor: 'move',
|
||||
cancel: '.no-drag',
|
||||
containment: 'parent',
|
||||
placeholder: 'sortable-placeholder',
|
||||
forcePlaceholderSize: true,
|
||||
helper: function (e, ui) {
|
||||
// When sorting table rows, the cells collapse. This helper fixes that: https://www.foliotek.com/devblog/make-table-rows-sortable-using-jquery-ui-sortable/
|
||||
ui.children().each(function () {
|
||||
$(this).width($(this).width());
|
||||
});
|
||||
return ui;
|
||||
},
|
||||
items: '> tr:not(.unsortable)',
|
||||
tolerance: 'pointer',
|
||||
update: function (e, ui) {
|
||||
// Get the new and old index for the moved element (using the URL as the identifier)
|
||||
var newIndex = ui.item.index();
|
||||
var movedLinkUrl = ui.item.attr('data-link');
|
||||
var originalIndex = getElementIndexByUrl(movedLinkUrl);
|
||||
|
||||
// Move the element in the model
|
||||
var movedElement = $scope.model.value[originalIndex];
|
||||
$scope.model.value.splice(originalIndex, 1);
|
||||
$scope.model.value.splice(newIndex, 0, movedElement);
|
||||
},
|
||||
start: function (e, ui) {
|
||||
//ui.placeholder.html("<td colspan='5'></td>");
|
||||
|
||||
// Build a placeholder cell that spans all the cells in the row: https://stackoverflow.com/questions/25845310/jquery-ui-sortable-and-table-cell-size
|
||||
var cellCount = 0;
|
||||
$('td, th', ui.helper).each(function () {
|
||||
// For each td or th try and get it's colspan attribute, and add that or 1 to the total
|
||||
var colspan = 1;
|
||||
var colspanAttr = $(this).attr('colspan');
|
||||
if (colspanAttr > 1) {
|
||||
colspan = colspanAttr;
|
||||
}
|
||||
cellCount += colspan;
|
||||
});
|
||||
|
||||
// Add the placeholder UI - note that this is the item's content, so td rather than tr - and set height of tr
|
||||
ui.placeholder.html('<td colspan="' + cellCount + '"></td>').height(ui.item.height());
|
||||
}
|
||||
};
|
||||
|
||||
//helper to count what is visible
|
||||
function countVisible() {
|
||||
return $scope.model.value.length;
|
||||
}
|
||||
|
||||
function isNumeric(n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||
}
|
||||
|
||||
function getElementIndexByUrl(url) {
|
||||
for (var i = 0; i < $scope.model.value.length; i++) {
|
||||
if ($scope.model.value[i].link == url) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
function select(data) {
|
||||
if ($scope.currentEditLink != null) {
|
||||
$scope.currentEditLink.internal = $scope.model.config.idType === "udi" ? data.udi : data.id;
|
||||
$scope.currentEditLink.internalName = data.name;
|
||||
$scope.currentEditLink.internalIcon = iconHelper.convertFromLegacyIcon(data.icon);
|
||||
$scope.currentEditLink.link = $scope.model.config.idType === "udi" ? data.udi : data.id;
|
||||
} else {
|
||||
$scope.newInternal = $scope.model.config.idType === "udi" ? data.udi : data.id;
|
||||
$scope.newInternalName = data.name;
|
||||
$scope.newInternalIcon = iconHelper.convertFromLegacyIcon(data.icon);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,403 +1,411 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.PropertyEditors.RTEController",
|
||||
function ($rootScope, $scope, $q, $locale, dialogService, $log, imageHelper, assetsService, $timeout, tinyMceService, angularHelper, stylesheetResource, macroService, editorState) {
|
||||
|
||||
$scope.isLoading = true;
|
||||
|
||||
//To id the html textarea we need to use the datetime ticks because we can have multiple rte's per a single property alias
|
||||
// because now we have to support having 2x (maybe more at some stage) content editors being displayed at once. This is because
|
||||
// we have this mini content editor panel that can be launched with MNTP.
|
||||
var d = new Date();
|
||||
var n = d.getTime();
|
||||
$scope.textAreaHtmlId = $scope.model.alias + "_" + n + "_rte";
|
||||
|
||||
function syncContent(editor){
|
||||
editor.save();
|
||||
angularHelper.safeApply($scope, function () {
|
||||
$scope.model.value = editor.getContent();
|
||||
});
|
||||
|
||||
//make the form dirty manually so that the track changes works, setting our model doesn't trigger
|
||||
// the angular bits because tinymce replaces the textarea.
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
}
|
||||
|
||||
tinyMceService.configuration().then(function (tinyMceConfig) {
|
||||
|
||||
//config value from general tinymce.config file
|
||||
var validElements = tinyMceConfig.validElements;
|
||||
|
||||
//These are absolutely required in order for the macros to render inline
|
||||
//we put these as extended elements because they get merged on top of the normal allowed elements by tiny mce
|
||||
var extendedValidElements = "@[id|class|style],-div[id|dir|class|align|style],ins[datetime|cite],-ul[class|style],-li[class|style],span[id|class|style]";
|
||||
|
||||
var invalidElements = tinyMceConfig.inValidElements;
|
||||
var plugins = _.map(tinyMceConfig.plugins, function (plugin) {
|
||||
if (plugin.useOnFrontend) {
|
||||
return plugin.name;
|
||||
}
|
||||
}).join(" ");
|
||||
|
||||
var editorConfig = $scope.model.config.editor;
|
||||
if (!editorConfig || angular.isString(editorConfig)) {
|
||||
editorConfig = tinyMceService.defaultPrevalues();
|
||||
}
|
||||
|
||||
//config value on the data type
|
||||
var toolbar = editorConfig.toolbar.join(" | ");
|
||||
var stylesheets = [];
|
||||
var styleFormats = [];
|
||||
var await = [];
|
||||
if (!editorConfig.maxImageSize && editorConfig.maxImageSize != 0) {
|
||||
editorConfig.maxImageSize = tinyMceService.defaultPrevalues().maxImageSize;
|
||||
}
|
||||
|
||||
//queue file loading
|
||||
if (typeof tinymce === "undefined") { // Don't reload tinymce if already loaded
|
||||
await.push(assetsService.loadJs("lib/tinymce/tinymce.min.js", $scope));
|
||||
}
|
||||
|
||||
//queue rules loading
|
||||
angular.forEach(editorConfig.stylesheets, function (val, key) {
|
||||
stylesheets.push(Umbraco.Sys.ServerVariables.umbracoSettings.cssPath + "/" + val + ".css?" + new Date().getTime());
|
||||
await.push(stylesheetResource.getRulesByName(val).then(function (rules) {
|
||||
angular.forEach(rules, function (rule) {
|
||||
var r = {};
|
||||
r.title = rule.name;
|
||||
if (rule.selector[0] == ".") {
|
||||
r.inline = "span";
|
||||
r.classes = rule.selector.substring(1);
|
||||
}
|
||||
else if (rule.selector[0] == "#") {
|
||||
r.inline = "span";
|
||||
r.attributes = { id: rule.selector.substring(1) };
|
||||
}
|
||||
else if (rule.selector[0] != "." && rule.selector.indexOf(".") > -1) {
|
||||
var split = rule.selector.split(".");
|
||||
r.block = split[0];
|
||||
r.classes = rule.selector.substring(rule.selector.indexOf(".") + 1).replace(".", " ");
|
||||
}
|
||||
else if (rule.selector[0] != "#" && rule.selector.indexOf("#") > -1) {
|
||||
var split = rule.selector.split("#");
|
||||
r.block = split[0];
|
||||
r.classes = rule.selector.substring(rule.selector.indexOf("#") + 1);
|
||||
}
|
||||
else {
|
||||
r.block = rule.selector;
|
||||
}
|
||||
|
||||
styleFormats.push(r);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
//stores a reference to the editor
|
||||
var tinyMceEditor = null;
|
||||
|
||||
// these languages are available for localization
|
||||
var availableLanguages = [
|
||||
'da',
|
||||
'de',
|
||||
'en',
|
||||
'en_us',
|
||||
'fi',
|
||||
'fr',
|
||||
'he',
|
||||
'it',
|
||||
'ja',
|
||||
'nl',
|
||||
'no',
|
||||
'pl',
|
||||
'pt',
|
||||
'ru',
|
||||
'sv',
|
||||
'zh'
|
||||
];
|
||||
|
||||
//define fallback language
|
||||
var language = 'en_us';
|
||||
//get locale from angular and match tinymce format. Angular localization is always in the format of ru-ru, de-de, en-gb, etc.
|
||||
//wheras tinymce is in the format of ru, de, en, en_us, etc.
|
||||
var localeId = $locale.id.replace('-', '_');
|
||||
//try matching the language using full locale format
|
||||
var languageMatch = _.find(availableLanguages, function(o) { return o === localeId; });
|
||||
//if no matches, try matching using only the language
|
||||
if (languageMatch === undefined) {
|
||||
var localeParts = localeId.split('_');
|
||||
languageMatch = _.find(availableLanguages, function(o) { return o === localeParts[0]; });
|
||||
}
|
||||
//if a match was found - set the language
|
||||
if (languageMatch !== undefined) {
|
||||
language = languageMatch;
|
||||
}
|
||||
|
||||
//wait for queue to end
|
||||
$q.all(await).then(function () {
|
||||
|
||||
//create a baseline Config to exten upon
|
||||
var baseLineConfigObj = {
|
||||
mode: "exact",
|
||||
skin: "umbraco",
|
||||
plugins: plugins,
|
||||
valid_elements: validElements,
|
||||
invalid_elements: invalidElements,
|
||||
extended_valid_elements: extendedValidElements,
|
||||
menubar: false,
|
||||
statusbar: false,
|
||||
relative_urls: false,
|
||||
height: editorConfig.dimensions.height,
|
||||
width: editorConfig.dimensions.width,
|
||||
maxImageSize: editorConfig.maxImageSize,
|
||||
toolbar: toolbar,
|
||||
content_css: stylesheets,
|
||||
style_formats: styleFormats,
|
||||
language: language,
|
||||
//see http://archive.tinymce.com/wiki.php/Configuration:cache_suffix
|
||||
cache_suffix: "?umb__rnd=" + Umbraco.Sys.ServerVariables.application.cacheBuster
|
||||
};
|
||||
|
||||
if (tinyMceConfig.customConfig) {
|
||||
|
||||
//if there is some custom config, we need to see if the string value of each item might actually be json and if so, we need to
|
||||
// convert it to json instead of having it as a string since this is what tinymce requires
|
||||
for (var i in tinyMceConfig.customConfig) {
|
||||
var val = tinyMceConfig.customConfig[i];
|
||||
if (val) {
|
||||
val = val.toString().trim();
|
||||
if (val.detectIsJson()) {
|
||||
try {
|
||||
tinyMceConfig.customConfig[i] = JSON.parse(val);
|
||||
//now we need to check if this custom config key is defined in our baseline, if it is we don't want to
|
||||
//overwrite the baseline config item if it is an array, we want to concat the items in the array, otherwise
|
||||
//if it's an object it will overwrite the baseline
|
||||
if (angular.isArray(baseLineConfigObj[i]) && angular.isArray(tinyMceConfig.customConfig[i])) {
|
||||
//concat it and below this concat'd array will overwrite the baseline in angular.extend
|
||||
tinyMceConfig.customConfig[i] = baseLineConfigObj[i].concat(tinyMceConfig.customConfig[i]);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
//cannot parse, we'll just leave it
|
||||
}
|
||||
}
|
||||
if (val === "true") {
|
||||
tinyMceConfig.customConfig[i] = true;
|
||||
}
|
||||
if (val === "false") {
|
||||
tinyMceConfig.customConfig[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
angular.extend(baseLineConfigObj, tinyMceConfig.customConfig);
|
||||
}
|
||||
|
||||
//set all the things that user configs should not be able to override
|
||||
baseLineConfigObj.elements = $scope.textAreaHtmlId; //this is the exact textarea id to replace!
|
||||
baseLineConfigObj.setup = function (editor) {
|
||||
|
||||
//set the reference
|
||||
tinyMceEditor = editor;
|
||||
|
||||
//enable browser based spell checking
|
||||
editor.on('init', function (e) {
|
||||
editor.getBody().setAttribute('spellcheck', true);
|
||||
});
|
||||
|
||||
//We need to listen on multiple things here because of the nature of tinymce, it doesn't
|
||||
//fire events when you think!
|
||||
//The change event doesn't fire when content changes, only when cursor points are changed and undo points
|
||||
//are created. the blur event doesn't fire if you insert content into the editor with a button and then
|
||||
//press save.
|
||||
//We have a couple of options, one is to do a set timeout and check for isDirty on the editor, or we can
|
||||
//listen to both change and blur and also on our own 'saving' event. I think this will be best because a
|
||||
//timer might end up using unwanted cpu and we'd still have to listen to our saving event in case they clicked
|
||||
//save before the timeout elapsed.
|
||||
|
||||
//TODO: We need to re-enable something like this to ensure the track changes is working with tinymce
|
||||
// so we can detect if the form is dirty or not, Per has some better events to use as this one triggers
|
||||
// even if you just enter/exit with mouse cursuor which doesn't really mean it's changed.
|
||||
// see: http://issues.umbraco.org/issue/U4-4485
|
||||
//var alreadyDirty = false;
|
||||
//editor.on('change', function (e) {
|
||||
// angularHelper.safeApply($scope, function () {
|
||||
// $scope.model.value = editor.getContent();
|
||||
|
||||
// if (!alreadyDirty) {
|
||||
// //make the form dirty manually so that the track changes works, setting our model doesn't trigger
|
||||
// // the angular bits because tinymce replaces the textarea.
|
||||
// var currForm = angularHelper.getCurrentForm($scope);
|
||||
// currForm.$setDirty();
|
||||
// alreadyDirty = true;
|
||||
// }
|
||||
|
||||
// });
|
||||
//});
|
||||
|
||||
//when we leave the editor (maybe)
|
||||
editor.on('blur', function (e) {
|
||||
editor.save();
|
||||
angularHelper.safeApply($scope, function () {
|
||||
$scope.model.value = editor.getContent();
|
||||
});
|
||||
});
|
||||
|
||||
//when buttons modify content
|
||||
editor.on('ExecCommand', function (e) {
|
||||
syncContent(editor);
|
||||
});
|
||||
|
||||
// Update model on keypress
|
||||
editor.on('KeyUp', function (e) {
|
||||
syncContent(editor);
|
||||
});
|
||||
|
||||
// Update model on change, i.e. copy/pasted text, plugins altering content
|
||||
editor.on('SetContent', function (e) {
|
||||
if (!e.initial) {
|
||||
syncContent(editor);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
editor.on('ObjectResized', function (e) {
|
||||
var qs = "?width=" + e.width + "&height=" + e.height + "&mode=max";
|
||||
var srcAttr = $(e.target).attr("src");
|
||||
var path = srcAttr.split("?")[0];
|
||||
$(e.target).attr("data-mce-src", path + qs);
|
||||
|
||||
syncContent(editor);
|
||||
});
|
||||
|
||||
tinyMceService.createLinkPicker(editor, $scope, function(currentTarget, anchorElement) {
|
||||
$scope.linkPickerOverlay = {
|
||||
view: "linkpicker",
|
||||
currentTarget: currentTarget,
|
||||
anchors: editorState.current ? tinyMceService.getAnchorNames(JSON.stringify(editorState.current.properties)) : [],
|
||||
ignoreUserStartNodes: $scope.model.config.ignoreUserStartNodes === "1",
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
tinyMceService.insertLinkInEditor(editor, model.target, anchorElement);
|
||||
$scope.linkPickerOverlay.show = false;
|
||||
$scope.linkPickerOverlay = null;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
//Create the insert media plugin
|
||||
tinyMceService.createMediaPicker(editor, $scope, function(currentTarget, userData){
|
||||
var ignoreUserStartNodes = false;
|
||||
var startNodeId = userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0];
|
||||
var startNodeIsVirtual = userData.startMediaIds.length !== 1;
|
||||
|
||||
if ($scope.model.config.ignoreUserStartNodes === "1") {
|
||||
ignoreUserStartNodes = true;
|
||||
startNodeId = -1;
|
||||
startNodeIsVirtual = true;
|
||||
}
|
||||
|
||||
$scope.mediaPickerOverlay = {
|
||||
currentTarget: currentTarget,
|
||||
onlyImages: true,
|
||||
showDetails: true,
|
||||
disableFolderSelect: true,
|
||||
startNodeId: startNodeId,
|
||||
startNodeIsVirtual: startNodeIsVirtual,
|
||||
ignoreUserStartNodes: ignoreUserStartNodes,
|
||||
view: "mediapicker",
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
tinyMceService.insertMediaInEditor(editor, model.selectedImages[0]);
|
||||
$scope.mediaPickerOverlay.show = false;
|
||||
$scope.mediaPickerOverlay = null;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
//Create the embedded plugin
|
||||
tinyMceService.createInsertEmbeddedMedia(editor, $scope, function() {
|
||||
|
||||
$scope.embedOverlay = {
|
||||
view: "embed",
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
tinyMceService.insertEmbeddedMediaInEditor(editor, model.embed.preview);
|
||||
$scope.embedOverlay.show = false;
|
||||
$scope.embedOverlay = null;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
|
||||
//Create the insert macro plugin
|
||||
tinyMceService.createInsertMacro(editor, $scope, function(dialogData) {
|
||||
|
||||
$scope.macroPickerOverlay = {
|
||||
view: "macropicker",
|
||||
dialogData: dialogData,
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
var macroObject = macroService.collectValueData(model.selectedMacro, model.macroParams, dialogData.renderingEngine);
|
||||
tinyMceService.insertMacroInEditor(editor, macroObject, $scope);
|
||||
$scope.macroPickerOverlay.show = false;
|
||||
$scope.macroPickerOverlay = null;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
/** Loads in the editor */
|
||||
function loadTinyMce() {
|
||||
|
||||
//we need to add a timeout here, to force a redraw so TinyMCE can find
|
||||
//the elements needed
|
||||
$timeout(function () {
|
||||
tinymce.DOM.events.domLoaded = true;
|
||||
tinymce.init(baseLineConfigObj);
|
||||
|
||||
$scope.isLoading = false;
|
||||
|
||||
}, 200, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
loadTinyMce();
|
||||
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server;
|
||||
//uses an empty string in the editor when the value is null
|
||||
tinyMceEditor.setContent(newVal || "", { format: 'raw' });
|
||||
//we need to manually fire this event since it is only ever fired based on loading from the DOM, this
|
||||
// is required for our plugins listening to this event to execute
|
||||
tinyMceEditor.fire('LoadContent', null);
|
||||
};
|
||||
|
||||
//listen for formSubmitting event (the result is callback used to remove the event subscription)
|
||||
var unsubscribe = $scope.$on("formSubmitting", function () {
|
||||
//TODO: Here we should parse out the macro rendered content so we can save on a lot of bytes in data xfer
|
||||
// we do parse it out on the server side but would be nice to do that on the client side before as well.
|
||||
if (tinyMceEditor !== undefined && tinyMceEditor != null && !$scope.isLoading) {
|
||||
$scope.model.value = tinyMceEditor.getContent();
|
||||
}
|
||||
});
|
||||
|
||||
//when the element is disposed we need to unsubscribe!
|
||||
// NOTE: this is very important otherwise if this is part of a modal, the listener still exists because the dom
|
||||
// element might still be there even after the modal has been hidden.
|
||||
$scope.$on('$destroy', function () {
|
||||
unsubscribe();
|
||||
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
|
||||
tinyMceEditor.destroy();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.PropertyEditors.RTEController",
|
||||
function ($rootScope, $scope, $q, $locale, dialogService, $log, imageHelper, assetsService, $timeout, tinyMceService, angularHelper, stylesheetResource, macroService, editorState, entityResource) {
|
||||
|
||||
$scope.isLoading = true;
|
||||
|
||||
//To id the html textarea we need to use the datetime ticks because we can have multiple rte's per a single property alias
|
||||
// because now we have to support having 2x (maybe more at some stage) content editors being displayed at once. This is because
|
||||
// we have this mini content editor panel that can be launched with MNTP.
|
||||
var d = new Date();
|
||||
var n = d.getTime();
|
||||
$scope.textAreaHtmlId = $scope.model.alias + "_" + n + "_rte";
|
||||
|
||||
function syncContent(editor){
|
||||
editor.save();
|
||||
angularHelper.safeApply($scope, function () {
|
||||
$scope.model.value = editor.getContent();
|
||||
});
|
||||
|
||||
//make the form dirty manually so that the track changes works, setting our model doesn't trigger
|
||||
// the angular bits because tinymce replaces the textarea.
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
}
|
||||
|
||||
tinyMceService.configuration().then(function (tinyMceConfig) {
|
||||
|
||||
//config value from general tinymce.config file
|
||||
var validElements = tinyMceConfig.validElements;
|
||||
|
||||
//These are absolutely required in order for the macros to render inline
|
||||
//we put these as extended elements because they get merged on top of the normal allowed elements by tiny mce
|
||||
var extendedValidElements = "@[id|class|style],-div[id|dir|class|align|style],ins[datetime|cite],-ul[class|style],-li[class|style],span[id|class|style]";
|
||||
|
||||
var invalidElements = tinyMceConfig.inValidElements;
|
||||
var plugins = _.map(tinyMceConfig.plugins, function (plugin) {
|
||||
if (plugin.useOnFrontend) {
|
||||
return plugin.name;
|
||||
}
|
||||
}).join(" ");
|
||||
|
||||
var editorConfig = $scope.model.config.editor;
|
||||
if (!editorConfig || angular.isString(editorConfig)) {
|
||||
editorConfig = tinyMceService.defaultPrevalues();
|
||||
}
|
||||
|
||||
//config value on the data type
|
||||
var toolbar = editorConfig.toolbar.join(" | ");
|
||||
var stylesheets = [];
|
||||
var styleFormats = [];
|
||||
var await = [];
|
||||
if (!editorConfig.maxImageSize && editorConfig.maxImageSize != 0) {
|
||||
editorConfig.maxImageSize = tinyMceService.defaultPrevalues().maxImageSize;
|
||||
}
|
||||
|
||||
var dataTypeId = ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null;
|
||||
|
||||
//queue file loading
|
||||
if (typeof tinymce === "undefined") { // Don't reload tinymce if already loaded
|
||||
await.push(assetsService.loadJs("lib/tinymce/tinymce.min.js", $scope));
|
||||
}
|
||||
|
||||
//queue rules loading
|
||||
angular.forEach(editorConfig.stylesheets, function (val, key) {
|
||||
stylesheets.push(Umbraco.Sys.ServerVariables.umbracoSettings.cssPath + "/" + val + ".css?" + new Date().getTime());
|
||||
await.push(stylesheetResource.getRulesByName(val).then(function (rules) {
|
||||
angular.forEach(rules, function (rule) {
|
||||
var r = {};
|
||||
r.title = rule.name;
|
||||
if (rule.selector[0] == ".") {
|
||||
r.inline = "span";
|
||||
r.classes = rule.selector.substring(1);
|
||||
}
|
||||
else if (rule.selector[0] == "#") {
|
||||
r.inline = "span";
|
||||
r.attributes = { id: rule.selector.substring(1) };
|
||||
}
|
||||
else if (rule.selector[0] != "." && rule.selector.indexOf(".") > -1) {
|
||||
var split = rule.selector.split(".");
|
||||
r.block = split[0];
|
||||
r.classes = rule.selector.substring(rule.selector.indexOf(".") + 1).replace(".", " ");
|
||||
}
|
||||
else if (rule.selector[0] != "#" && rule.selector.indexOf("#") > -1) {
|
||||
var split = rule.selector.split("#");
|
||||
r.block = split[0];
|
||||
r.classes = rule.selector.substring(rule.selector.indexOf("#") + 1);
|
||||
}
|
||||
else {
|
||||
r.block = rule.selector;
|
||||
}
|
||||
|
||||
styleFormats.push(r);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
//stores a reference to the editor
|
||||
var tinyMceEditor = null;
|
||||
|
||||
// these languages are available for localization
|
||||
var availableLanguages = [
|
||||
'da',
|
||||
'de',
|
||||
'en',
|
||||
'en_us',
|
||||
'fi',
|
||||
'fr',
|
||||
'he',
|
||||
'it',
|
||||
'ja',
|
||||
'nl',
|
||||
'no',
|
||||
'pl',
|
||||
'pt',
|
||||
'ru',
|
||||
'sv',
|
||||
'zh'
|
||||
];
|
||||
|
||||
//define fallback language
|
||||
var language = 'en_us';
|
||||
//get locale from angular and match tinymce format. Angular localization is always in the format of ru-ru, de-de, en-gb, etc.
|
||||
//wheras tinymce is in the format of ru, de, en, en_us, etc.
|
||||
var localeId = $locale.id.replace('-', '_');
|
||||
//try matching the language using full locale format
|
||||
var languageMatch = _.find(availableLanguages, function(o) { return o === localeId; });
|
||||
//if no matches, try matching using only the language
|
||||
if (languageMatch === undefined) {
|
||||
var localeParts = localeId.split('_');
|
||||
languageMatch = _.find(availableLanguages, function(o) { return o === localeParts[0]; });
|
||||
}
|
||||
//if a match was found - set the language
|
||||
if (languageMatch !== undefined) {
|
||||
language = languageMatch;
|
||||
}
|
||||
|
||||
//wait for queue to end
|
||||
$q.all(await).then(function () {
|
||||
|
||||
//create a baseline Config to exten upon
|
||||
var baseLineConfigObj = {
|
||||
mode: "exact",
|
||||
skin: "umbraco",
|
||||
plugins: plugins,
|
||||
valid_elements: validElements,
|
||||
invalid_elements: invalidElements,
|
||||
extended_valid_elements: extendedValidElements,
|
||||
menubar: false,
|
||||
statusbar: false,
|
||||
relative_urls: false,
|
||||
height: editorConfig.dimensions.height,
|
||||
width: editorConfig.dimensions.width,
|
||||
maxImageSize: editorConfig.maxImageSize,
|
||||
toolbar: toolbar,
|
||||
content_css: stylesheets,
|
||||
style_formats: styleFormats,
|
||||
language: language,
|
||||
//see http://archive.tinymce.com/wiki.php/Configuration:cache_suffix
|
||||
cache_suffix: "?umb__rnd=" + Umbraco.Sys.ServerVariables.application.cacheBuster
|
||||
};
|
||||
|
||||
if (tinyMceConfig.customConfig) {
|
||||
|
||||
//if there is some custom config, we need to see if the string value of each item might actually be json and if so, we need to
|
||||
// convert it to json instead of having it as a string since this is what tinymce requires
|
||||
for (var i in tinyMceConfig.customConfig) {
|
||||
var val = tinyMceConfig.customConfig[i];
|
||||
if (val) {
|
||||
val = val.toString().trim();
|
||||
if (val.detectIsJson()) {
|
||||
try {
|
||||
tinyMceConfig.customConfig[i] = JSON.parse(val);
|
||||
//now we need to check if this custom config key is defined in our baseline, if it is we don't want to
|
||||
//overwrite the baseline config item if it is an array, we want to concat the items in the array, otherwise
|
||||
//if it's an object it will overwrite the baseline
|
||||
if (angular.isArray(baseLineConfigObj[i]) && angular.isArray(tinyMceConfig.customConfig[i])) {
|
||||
//concat it and below this concat'd array will overwrite the baseline in angular.extend
|
||||
tinyMceConfig.customConfig[i] = baseLineConfigObj[i].concat(tinyMceConfig.customConfig[i]);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
//cannot parse, we'll just leave it
|
||||
}
|
||||
}
|
||||
if (val === "true") {
|
||||
tinyMceConfig.customConfig[i] = true;
|
||||
}
|
||||
if (val === "false") {
|
||||
tinyMceConfig.customConfig[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
angular.extend(baseLineConfigObj, tinyMceConfig.customConfig);
|
||||
}
|
||||
|
||||
//set all the things that user configs should not be able to override
|
||||
baseLineConfigObj.elements = $scope.textAreaHtmlId; //this is the exact textarea id to replace!
|
||||
baseLineConfigObj.setup = function (editor) {
|
||||
|
||||
//set the reference
|
||||
tinyMceEditor = editor;
|
||||
|
||||
//enable browser based spell checking
|
||||
editor.on('init', function (e) {
|
||||
editor.getBody().setAttribute('spellcheck', true);
|
||||
});
|
||||
|
||||
//We need to listen on multiple things here because of the nature of tinymce, it doesn't
|
||||
//fire events when you think!
|
||||
//The change event doesn't fire when content changes, only when cursor points are changed and undo points
|
||||
//are created. the blur event doesn't fire if you insert content into the editor with a button and then
|
||||
//press save.
|
||||
//We have a couple of options, one is to do a set timeout and check for isDirty on the editor, or we can
|
||||
//listen to both change and blur and also on our own 'saving' event. I think this will be best because a
|
||||
//timer might end up using unwanted cpu and we'd still have to listen to our saving event in case they clicked
|
||||
//save before the timeout elapsed.
|
||||
|
||||
//TODO: We need to re-enable something like this to ensure the track changes is working with tinymce
|
||||
// so we can detect if the form is dirty or not, Per has some better events to use as this one triggers
|
||||
// even if you just enter/exit with mouse cursuor which doesn't really mean it's changed.
|
||||
// see: http://issues.umbraco.org/issue/U4-4485
|
||||
//var alreadyDirty = false;
|
||||
//editor.on('change', function (e) {
|
||||
// angularHelper.safeApply($scope, function () {
|
||||
// $scope.model.value = editor.getContent();
|
||||
|
||||
// if (!alreadyDirty) {
|
||||
// //make the form dirty manually so that the track changes works, setting our model doesn't trigger
|
||||
// // the angular bits because tinymce replaces the textarea.
|
||||
// var currForm = angularHelper.getCurrentForm($scope);
|
||||
// currForm.$setDirty();
|
||||
// alreadyDirty = true;
|
||||
// }
|
||||
|
||||
// });
|
||||
//});
|
||||
|
||||
//when we leave the editor (maybe)
|
||||
editor.on('blur', function (e) {
|
||||
editor.save();
|
||||
angularHelper.safeApply($scope, function () {
|
||||
$scope.model.value = editor.getContent();
|
||||
});
|
||||
});
|
||||
|
||||
//when buttons modify content
|
||||
editor.on('ExecCommand', function (e) {
|
||||
syncContent(editor);
|
||||
});
|
||||
|
||||
// Update model on keypress
|
||||
editor.on('KeyUp', function (e) {
|
||||
syncContent(editor);
|
||||
});
|
||||
|
||||
// Update model on change, i.e. copy/pasted text, plugins altering content
|
||||
editor.on('SetContent', function (e) {
|
||||
if (!e.initial) {
|
||||
syncContent(editor);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
editor.on('ObjectResized', function (e) {
|
||||
var qs = "?width=" + e.width + "&height=" + e.height + "&mode=max";
|
||||
var srcAttr = $(e.target).attr("src");
|
||||
var path = srcAttr.split("?")[0];
|
||||
$(e.target).attr("data-mce-src", path + qs);
|
||||
|
||||
syncContent(editor);
|
||||
});
|
||||
|
||||
tinyMceService.createLinkPicker(editor, $scope, function(currentTarget, anchorElement) {
|
||||
|
||||
entityResource.getAnchors($scope.model.value).then(function(anchorValues){
|
||||
|
||||
$scope.linkPickerOverlay = {
|
||||
view: "linkpicker",
|
||||
currentTarget: currentTarget,
|
||||
anchors: anchorValues,
|
||||
dataTypeId: dataTypeId,
|
||||
ignoreUserStartNodes: $scope.model.config.ignoreUserStartNodes,
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
tinyMceService.insertLinkInEditor(editor, model.target, anchorElement);
|
||||
$scope.linkPickerOverlay.show = false;
|
||||
$scope.linkPickerOverlay = null;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
//Create the insert media plugin
|
||||
tinyMceService.createMediaPicker(editor, $scope, function(currentTarget, userData){
|
||||
var startNodeId = userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0];
|
||||
var startNodeIsVirtual = userData.startMediaIds.length !== 1;
|
||||
|
||||
if ($scope.model.config.ignoreUserStartNodes === "1") {
|
||||
startNodeId = -1;
|
||||
startNodeIsVirtual = true;
|
||||
}
|
||||
|
||||
$scope.mediaPickerOverlay = {
|
||||
currentTarget: currentTarget,
|
||||
onlyImages: true,
|
||||
showDetails: true,
|
||||
disableFolderSelect: true,
|
||||
startNodeId: startNodeId,
|
||||
startNodeIsVirtual: startNodeIsVirtual,
|
||||
dataTypeId: dataTypeId,
|
||||
view: "mediapicker",
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
tinyMceService.insertMediaInEditor(editor, model.selectedImages[0]);
|
||||
$scope.mediaPickerOverlay.show = false;
|
||||
$scope.mediaPickerOverlay = null;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
//Create the embedded plugin
|
||||
tinyMceService.createInsertEmbeddedMedia(editor, $scope, function() {
|
||||
|
||||
$scope.embedOverlay = {
|
||||
view: "embed",
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
tinyMceService.insertEmbeddedMediaInEditor(editor, model.embed.preview);
|
||||
$scope.embedOverlay.show = false;
|
||||
$scope.embedOverlay = null;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
|
||||
//Create the insert macro plugin
|
||||
tinyMceService.createInsertMacro(editor, $scope, function(dialogData) {
|
||||
|
||||
$scope.macroPickerOverlay = {
|
||||
view: "macropicker",
|
||||
dialogData: dialogData,
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
var macroObject = macroService.collectValueData(model.selectedMacro, model.macroParams, dialogData.renderingEngine);
|
||||
tinyMceService.insertMacroInEditor(editor, macroObject, $scope);
|
||||
$scope.macroPickerOverlay.show = false;
|
||||
$scope.macroPickerOverlay = null;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
/** Loads in the editor */
|
||||
function loadTinyMce() {
|
||||
|
||||
//we need to add a timeout here, to force a redraw so TinyMCE can find
|
||||
//the elements needed
|
||||
$timeout(function () {
|
||||
tinymce.DOM.events.domLoaded = true;
|
||||
tinymce.init(baseLineConfigObj);
|
||||
|
||||
$scope.isLoading = false;
|
||||
|
||||
}, 200, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
loadTinyMce();
|
||||
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server;
|
||||
//uses an empty string in the editor when the value is null
|
||||
tinyMceEditor.setContent(newVal || "", { format: 'raw' });
|
||||
//we need to manually fire this event since it is only ever fired based on loading from the DOM, this
|
||||
// is required for our plugins listening to this event to execute
|
||||
tinyMceEditor.fire('LoadContent', null);
|
||||
};
|
||||
|
||||
//listen for formSubmitting event (the result is callback used to remove the event subscription)
|
||||
var unsubscribe = $scope.$on("formSubmitting", function () {
|
||||
//TODO: Here we should parse out the macro rendered content so we can save on a lot of bytes in data xfer
|
||||
// we do parse it out on the server side but would be nice to do that on the client side before as well.
|
||||
if (tinyMceEditor !== undefined && tinyMceEditor != null && !$scope.isLoading) {
|
||||
$scope.model.value = tinyMceEditor.getContent();
|
||||
}
|
||||
});
|
||||
|
||||
//when the element is disposed we need to unsubscribe!
|
||||
// NOTE: this is very important otherwise if this is part of a modal, the listener still exists because the dom
|
||||
// element might still be there even after the modal has been hidden.
|
||||
$scope.$on('$destroy', function () {
|
||||
unsubscribe();
|
||||
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
|
||||
tinyMceEditor.destroy();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
|
||||
<Import Project="..\packages\MSBuild.Microsoft.VisualStudio.Web.targets.14.0.0.3\build\MSBuild.Microsoft.VisualStudio.Web.targets.props" Condition="Exists('..\packages\MSBuild.Microsoft.VisualStudio.Web.targets.14.0.0.3\build\MSBuild.Microsoft.VisualStudio.Web.targets.props')" />
|
||||
<Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
|
||||
<Import Project="..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
@@ -155,11 +156,11 @@
|
||||
<Reference Include="Microsoft.AspNet.Identity.Owin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.Identity.Owin.2.2.2\lib\net45\Microsoft.AspNet.Identity.Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CodeAnalysis, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
|
||||
<Reference Include="Microsoft.CodeAnalysis, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.1.0.0\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
|
||||
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.1.0.0\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
|
||||
@@ -204,8 +205,8 @@
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Collections.Immutable, Version=1.2.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Collections.Immutable.1.5.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
|
||||
<Reference Include="System.Collections.Immutable, Version=1.1.36.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.configuration" />
|
||||
@@ -236,8 +237,8 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Reflection.Metadata, Version=1.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Reflection.Metadata.1.6.0\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
|
||||
<Reference Include="System.Reflection.Metadata, Version=1.0.21.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Reflection.Metadata.1.0.21\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
@@ -1002,8 +1003,8 @@
|
||||
<Folder Include="Views\MacroPartials\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
|
||||
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
|
||||
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.0.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
|
||||
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.0.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
|
||||
@@ -1027,9 +1028,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7150</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7151</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7150</IISUrl>
|
||||
<IISUrl>http://localhost:7151</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
@@ -1088,5 +1089,6 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props'))" />
|
||||
<Error Condition="!Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
|
||||
<Error Condition="!Exists('..\packages\MSBuild.Microsoft.VisualStudio.Web.targets.14.0.0.3\build\MSBuild.Microsoft.VisualStudio.Web.targets.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSBuild.Microsoft.VisualStudio.Web.targets.14.0.0.3\build\MSBuild.Microsoft.VisualStudio.Web.targets.props'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -130,5 +130,12 @@
|
||||
<apiEndpoint><![CDATA[https://publish.twitter.com/oembed]]></apiEndpoint>
|
||||
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco">
|
||||
</requestParams>
|
||||
</provider>
|
||||
<!-- Giphy Embed support -->
|
||||
<provider name="Giphy" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
|
||||
<urlShemeRegex><![CDATA[giphy\.com/]]></urlShemeRegex>
|
||||
<apiEndpoint><![CDATA[https://giphy.com/services/oembed?url=]]></apiEndpoint>
|
||||
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco">
|
||||
</requestParams>
|
||||
</provider>
|
||||
</embed>
|
||||
|
||||
@@ -130,5 +130,12 @@
|
||||
<apiEndpoint><![CDATA[https://publish.twitter.com/oembed]]></apiEndpoint>
|
||||
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco">
|
||||
</requestParams>
|
||||
</provider>
|
||||
<!-- Giphy Embed support -->
|
||||
<provider name="Giphy" type="Umbraco.Web.Media.EmbedProviders.OEmbedJson, umbraco">
|
||||
<urlShemeRegex><![CDATA[giphy\.com/]]></urlShemeRegex>
|
||||
<apiEndpoint><![CDATA[https://giphy.com/services/oembed?url=]]></apiEndpoint>
|
||||
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco">
|
||||
</requestParams>
|
||||
</provider>
|
||||
</embed>
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.7" targetFramework="net452" />
|
||||
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.7" targetFramework="net452" />
|
||||
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net452" />
|
||||
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="Microsoft.CodeAnalysis.Common" version="1.3.2" targetFramework="net452" />
|
||||
<package id="Microsoft.CodeAnalysis.CSharp" version="1.3.2" targetFramework="net452" />
|
||||
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.0.0" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="Microsoft.CodeAnalysis.Common" version="1.0.0" targetFramework="net452" />
|
||||
<package id="Microsoft.CodeAnalysis.CSharp" version="1.0.0" targetFramework="net452" />
|
||||
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net452" />
|
||||
<package id="Microsoft.IO.RecyclableMemoryStream" version="1.2.2" targetFramework="net45" />
|
||||
<package id="Microsoft.Net.Compilers" version="1.3.2" targetFramework="net452" developmentDependency="true" />
|
||||
@@ -32,11 +32,12 @@
|
||||
<package id="Microsoft.Owin.Security.OAuth" version="4.0.1" targetFramework="net452" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
|
||||
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
|
||||
<package id="MSBuild.Microsoft.VisualStudio.Web.targets" version="14.0.0.3" targetFramework="net452" />
|
||||
<package id="MySql.Data" version="6.9.9" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net452" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net452" />
|
||||
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net452" />
|
||||
<package id="System.Collections.Immutable" version="1.1.36" targetFramework="net452" />
|
||||
<package id="System.Reflection.Metadata" version="1.0.21" targetFramework="net452" />
|
||||
<package id="Umbraco.ModelsBuilder" version="3.0.10" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -438,34 +438,18 @@
|
||||
<assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845DCD8080CC91" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.3.0" newVersion="1.2.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.4.3.0" newVersion="1.4.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Threading.Tasks.Dataflow" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.6.3.0" newVersion="4.6.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.3.1.0" newVersion="1.3.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.3.1.0" newVersion="1.3.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.1.0" newVersion="2.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.AspNet.SignalR.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.4.1.0" newVersion="2.4.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Http.WebHost" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Umbraco.Web.Controllers
|
||||
{
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
[ValidateUmbracoFormRouteString]
|
||||
public ActionResult HandleLogin([Bind(Prefix = "loginModel")]LoginModel model)
|
||||
{
|
||||
if (ModelState.IsValid == false)
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Umbraco.Web.Controllers
|
||||
{
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
[ValidateUmbracoFormRouteString]
|
||||
public ActionResult HandleLogout([Bind(Prefix = "logoutModel")]PostRedirectModel model)
|
||||
{
|
||||
if (ModelState.IsValid == false)
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Umbraco.Web.Controllers
|
||||
{
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
[ValidateUmbracoFormRouteString]
|
||||
public ActionResult HandleUpdateProfile([Bind(Prefix = "profileModel")] ProfileModel model)
|
||||
{
|
||||
var provider = global::Umbraco.Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider();
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Umbraco.Web.Controllers
|
||||
{
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
[ValidateUmbracoFormRouteString]
|
||||
public ActionResult HandleRegisterMember([Bind(Prefix = "registerModel")]RegisterModel model)
|
||||
{
|
||||
if (ModelState.IsValid == false)
|
||||
|
||||
@@ -224,10 +224,6 @@ namespace Umbraco.Web.Editors
|
||||
"updateCheckApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<UpdateCheckController>(
|
||||
controller => controller.GetCheck())
|
||||
},
|
||||
{
|
||||
"tagApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<TagsController>(
|
||||
controller => controller.GetAllTags(null))
|
||||
},
|
||||
{
|
||||
"templateApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<TemplateController>(
|
||||
controller => controller.GetById(0))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1010
-1014
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,46 +1,50 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a content property to be saved
|
||||
/// </summary>
|
||||
[DataContract(Name = "property", Namespace = "")]
|
||||
public class ContentPropertyBasic
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the cmsPropertyData ID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is not really used for anything
|
||||
/// </remarks>
|
||||
[DataMember(Name = "id", IsRequired = true)]
|
||||
[Required]
|
||||
public int Id { get; set; }
|
||||
|
||||
[DataMember(Name = "value")]
|
||||
public object Value { get; set; }
|
||||
|
||||
[DataMember(Name = "alias", IsRequired = true)]
|
||||
[Required(AllowEmptyStrings = false)]
|
||||
public string Alias { get; set; }
|
||||
|
||||
[DataMember(Name = "editor", IsRequired = false)]
|
||||
public string Editor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flags the property to denote that it can contain sensitive data
|
||||
/// </summary>
|
||||
[DataMember(Name = "isSensitive", IsRequired = false)]
|
||||
public bool IsSensitive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used internally during model mapping
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
internal PropertyEditor PropertyEditor { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a content property to be saved
|
||||
/// </summary>
|
||||
[DataContract(Name = "property", Namespace = "")]
|
||||
public class ContentPropertyBasic
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the cmsPropertyData ID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is not really used for anything
|
||||
/// </remarks>
|
||||
[DataMember(Name = "id", IsRequired = true)]
|
||||
[Required]
|
||||
public int Id { get; set; }
|
||||
|
||||
[DataMember(Name = "dataTypeId", IsRequired = false)]
|
||||
public Guid? DataTypeId { get; set; }
|
||||
|
||||
[DataMember(Name = "value")]
|
||||
public object Value { get; set; }
|
||||
|
||||
[DataMember(Name = "alias", IsRequired = true)]
|
||||
[Required(AllowEmptyStrings = false)]
|
||||
public string Alias { get; set; }
|
||||
|
||||
[DataMember(Name = "editor", IsRequired = false)]
|
||||
public string Editor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flags the property to denote that it can contain sensitive data
|
||||
/// </summary>
|
||||
[DataMember(Name = "isSensitive", IsRequired = false)]
|
||||
public bool IsSensitive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used internally during model mapping
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
internal PropertyEditor PropertyEditor { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "urlAndAnchors", Namespace = "")]
|
||||
public class UrlAndAnchors
|
||||
{
|
||||
public UrlAndAnchors(string url, IEnumerable<string> anchorValues)
|
||||
{
|
||||
Url = url;
|
||||
AnchorValues = anchorValues;
|
||||
}
|
||||
|
||||
[DataMember(Name = "url")]
|
||||
public string Url { get; }
|
||||
|
||||
[DataMember(Name = "anchorValues")]
|
||||
public IEnumerable<string> AnchorValues { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,75 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a base generic ContentPropertyBasic from a Property
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
internal class ContentPropertyBasicConverter<T> : ITypeConverter<Property, T>
|
||||
where T : ContentPropertyBasic, new()
|
||||
{
|
||||
protected IDataTypeService DataTypeService { get; private set; }
|
||||
|
||||
private static readonly List<string> ComplexPropertyTypeAliases = new List<string> {"Umbraco.NestedContent"};
|
||||
|
||||
public ContentPropertyBasicConverter(IDataTypeService dataTypeService)
|
||||
{
|
||||
DataTypeService = dataTypeService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns the PropertyEditor, Id, Alias and Value to the property
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual T Convert(ResolutionContext context)
|
||||
{
|
||||
var property = context.SourceValue as Property;
|
||||
if (property == null)
|
||||
throw new InvalidOperationException("Source value is not a property.");
|
||||
|
||||
var editor = PropertyEditorResolver.Current.GetByAlias(property.PropertyType.PropertyEditorAlias);
|
||||
if (editor == null)
|
||||
{
|
||||
LogHelper.Error<ContentPropertyBasicConverter<T>>(
|
||||
"No property editor found, converting to a Label",
|
||||
new NullReferenceException("The property editor with alias " +
|
||||
property.PropertyType.PropertyEditorAlias + " does not exist"));
|
||||
|
||||
editor = PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias);
|
||||
}
|
||||
|
||||
var result = new T
|
||||
{
|
||||
Id = property.Id,
|
||||
Alias = property.Alias,
|
||||
PropertyEditor = editor,
|
||||
Editor = editor.Alias
|
||||
};
|
||||
|
||||
// if there's a set of property aliases specified, we will check if the current property's value should be mapped.
|
||||
// if it isn't one of the ones specified in 'includeProperties', we will just return the result without mapping the Value.
|
||||
if (context.Options.Items.ContainsKey("IncludeProperties"))
|
||||
{
|
||||
var includeProperties = context.Options.Items["IncludeProperties"] as IEnumerable<string>;
|
||||
if (includeProperties != null && includeProperties.Contains(property.Alias) == false)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// if no 'IncludeProperties' were specified or this property is set to be included - we will map the value and return.
|
||||
result.Value = editor.ValueEditor.ConvertDbToEditor(property, property.PropertyType, DataTypeService);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a base generic ContentPropertyBasic from a Property
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
internal class ContentPropertyBasicConverter<T> : ITypeConverter<Property, T>
|
||||
where T : ContentPropertyBasic, new()
|
||||
{
|
||||
protected IDataTypeService DataTypeService { get; }
|
||||
protected IEntityService EntityService { get; }
|
||||
|
||||
private static readonly List<string> ComplexPropertyTypeAliases = new List<string> {"Umbraco.NestedContent"};
|
||||
|
||||
public ContentPropertyBasicConverter(IDataTypeService dataTypeService, IEntityService entityService)
|
||||
{
|
||||
DataTypeService = dataTypeService;
|
||||
EntityService = entityService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns the PropertyEditor, Id, Alias and Value to the property
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual T Convert(ResolutionContext context)
|
||||
{
|
||||
var property = context.SourceValue as Property;
|
||||
if (property == null)
|
||||
throw new InvalidOperationException("Source value is not a property.");
|
||||
|
||||
var editor = PropertyEditorResolver.Current.GetByAlias(property.PropertyType.PropertyEditorAlias);
|
||||
if (editor == null)
|
||||
{
|
||||
LogHelper.Error<ContentPropertyBasicConverter<T>>(
|
||||
"No property editor found, converting to a Label",
|
||||
new NullReferenceException("The property editor with alias " +
|
||||
property.PropertyType.PropertyEditorAlias + " does not exist"));
|
||||
|
||||
editor = PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias);
|
||||
}
|
||||
|
||||
var dataTypeDefinitionKey = EntityService.GetKeyForId(property.PropertyType.DataTypeDefinitionId, UmbracoObjectTypes.DataType);
|
||||
|
||||
if (dataTypeDefinitionKey.Success == false)
|
||||
{
|
||||
throw new InvalidOperationException("Can't get the unique key from the id: " + property.PropertyType.DataTypeDefinitionId);
|
||||
}
|
||||
|
||||
|
||||
var result = new T
|
||||
{
|
||||
Id = property.Id,
|
||||
DataTypeId = dataTypeDefinitionKey.Result,
|
||||
Alias = property.Alias,
|
||||
PropertyEditor = editor,
|
||||
Editor = editor.Alias
|
||||
};
|
||||
|
||||
// if there's a set of property aliases specified, we will check if the current property's value should be mapped.
|
||||
// if it isn't one of the ones specified in 'includeProperties', we will just return the result without mapping the Value.
|
||||
if (context.Options.Items.ContainsKey("IncludeProperties"))
|
||||
{
|
||||
var includeProperties = context.Options.Items["IncludeProperties"] as IEnumerable<string>;
|
||||
if (includeProperties != null && includeProperties.Contains(property.Alias) == false)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// if no 'IncludeProperties' were specified or this property is set to be included - we will map the value and return.
|
||||
result.Value = editor.ValueEditor.ConvertDbToEditor(property, property.PropertyType, DataTypeService);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,67 +1,67 @@
|
||||
using System;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a ContentPropertyDisplay from a Property
|
||||
/// </summary>
|
||||
internal class ContentPropertyDisplayConverter : ContentPropertyBasicConverter<ContentPropertyDisplay>
|
||||
{
|
||||
private readonly ILocalizedTextService _textService;
|
||||
|
||||
public ContentPropertyDisplayConverter(IDataTypeService dataTypeService, ILocalizedTextService textService)
|
||||
: base(dataTypeService)
|
||||
{
|
||||
_textService = textService;
|
||||
}
|
||||
public override ContentPropertyDisplay Convert(ResolutionContext context)
|
||||
{
|
||||
var display = base.Convert(context);
|
||||
|
||||
var originalProperty = context.SourceValue as Property;
|
||||
if (originalProperty == null)
|
||||
throw new InvalidOperationException("Source value is not a property.");
|
||||
|
||||
var dataTypeService = DataTypeService;
|
||||
var preVals = dataTypeService.GetPreValuesCollectionByDataTypeId(originalProperty.PropertyType.DataTypeDefinitionId);
|
||||
|
||||
//configure the editor for display with the pre-values
|
||||
var valEditor = display.PropertyEditor.ValueEditor;
|
||||
valEditor.ConfigureForDisplay(preVals);
|
||||
|
||||
//set the display properties after mapping
|
||||
display.Alias = originalProperty.Alias;
|
||||
display.Description = originalProperty.PropertyType.Description;
|
||||
display.Label = originalProperty.PropertyType.Name;
|
||||
display.HideLabel = valEditor.HideLabel;
|
||||
|
||||
//add the validation information
|
||||
display.Validation.Mandatory = originalProperty.PropertyType.Mandatory;
|
||||
display.Validation.Pattern = originalProperty.PropertyType.ValidationRegExp;
|
||||
|
||||
if (display.PropertyEditor == null)
|
||||
{
|
||||
//display.Config = PreValueCollection.AsDictionary(preVals);
|
||||
//if there is no property editor it means that it is a legacy data type
|
||||
// we cannot support editing with that so we'll just render the readonly value view.
|
||||
display.View = "views/propertyeditors/readonlyvalue/readonlyvalue.html";
|
||||
}
|
||||
else
|
||||
{
|
||||
//let the property editor format the pre-values
|
||||
display.Config = display.PropertyEditor.PreValueEditor.ConvertDbToEditor(display.PropertyEditor.DefaultPreValues, preVals);
|
||||
display.View = valEditor.View;
|
||||
}
|
||||
|
||||
//Translate
|
||||
display.Label = _textService.UmbracoDictionaryTranslate(display.Label);
|
||||
display.Description = _textService.UmbracoDictionaryTranslate(display.Description);
|
||||
|
||||
return display;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a ContentPropertyDisplay from a Property
|
||||
/// </summary>
|
||||
internal class ContentPropertyDisplayConverter : ContentPropertyBasicConverter<ContentPropertyDisplay>
|
||||
{
|
||||
private readonly ILocalizedTextService _textService;
|
||||
|
||||
public ContentPropertyDisplayConverter(IDataTypeService dataTypeService, ILocalizedTextService textService, IEntityService entityService)
|
||||
: base(dataTypeService, entityService)
|
||||
{
|
||||
_textService = textService;
|
||||
}
|
||||
public override ContentPropertyDisplay Convert(ResolutionContext context)
|
||||
{
|
||||
var display = base.Convert(context);
|
||||
|
||||
var originalProperty = context.SourceValue as Property;
|
||||
if (originalProperty == null)
|
||||
throw new InvalidOperationException("Source value is not a property.");
|
||||
|
||||
var dataTypeService = DataTypeService;
|
||||
var preVals = dataTypeService.GetPreValuesCollectionByDataTypeId(originalProperty.PropertyType.DataTypeDefinitionId);
|
||||
|
||||
//configure the editor for display with the pre-values
|
||||
var valEditor = display.PropertyEditor.ValueEditor;
|
||||
valEditor.ConfigureForDisplay(preVals);
|
||||
|
||||
//set the display properties after mapping
|
||||
display.Alias = originalProperty.Alias;
|
||||
display.Description = originalProperty.PropertyType.Description;
|
||||
display.Label = originalProperty.PropertyType.Name;
|
||||
display.HideLabel = valEditor.HideLabel;
|
||||
|
||||
//add the validation information
|
||||
display.Validation.Mandatory = originalProperty.PropertyType.Mandatory;
|
||||
display.Validation.Pattern = originalProperty.PropertyType.ValidationRegExp;
|
||||
|
||||
if (display.PropertyEditor == null)
|
||||
{
|
||||
//display.Config = PreValueCollection.AsDictionary(preVals);
|
||||
//if there is no property editor it means that it is a legacy data type
|
||||
// we cannot support editing with that so we'll just render the readonly value view.
|
||||
display.View = "views/propertyeditors/readonlyvalue/readonlyvalue.html";
|
||||
}
|
||||
else
|
||||
{
|
||||
//let the property editor format the pre-values
|
||||
display.Config = display.PropertyEditor.PreValueEditor.ConvertDbToEditor(display.PropertyEditor.DefaultPreValues, preVals);
|
||||
display.View = valEditor.View;
|
||||
}
|
||||
|
||||
//Translate
|
||||
display.Label = _textService.UmbracoDictionaryTranslate(display.Label);
|
||||
display.Description = _textService.UmbracoDictionaryTranslate(display.Description);
|
||||
|
||||
return display;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
using System;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a ContentPropertyDto from a Property
|
||||
/// </summary>
|
||||
internal class ContentPropertyDtoConverter : ContentPropertyBasicConverter<ContentPropertyDto>
|
||||
{
|
||||
public ContentPropertyDtoConverter(IDataTypeService dataTypeService)
|
||||
: base(dataTypeService)
|
||||
{
|
||||
}
|
||||
|
||||
public override ContentPropertyDto Convert(ResolutionContext context)
|
||||
{
|
||||
var propertyDto = base.Convert(context);
|
||||
|
||||
var originalProperty = context.SourceValue as Property;
|
||||
if (originalProperty == null)
|
||||
throw new InvalidOperationException("Source value is not a property.");
|
||||
|
||||
var dataTypeService = DataTypeService;
|
||||
|
||||
propertyDto.IsRequired = originalProperty.PropertyType.Mandatory;
|
||||
propertyDto.ValidationRegExp = originalProperty.PropertyType.ValidationRegExp;
|
||||
propertyDto.Description = originalProperty.PropertyType.Description;
|
||||
propertyDto.Label = originalProperty.PropertyType.Name;
|
||||
|
||||
//TODO: We should be able to look both of these up at the same time!
|
||||
propertyDto.DataType = dataTypeService.GetDataTypeDefinitionById(originalProperty.PropertyType.DataTypeDefinitionId);
|
||||
propertyDto.PreValues = dataTypeService.GetPreValuesCollectionByDataTypeId(originalProperty.PropertyType.DataTypeDefinitionId);
|
||||
|
||||
return propertyDto;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a ContentPropertyDto from a Property
|
||||
/// </summary>
|
||||
internal class ContentPropertyDtoConverter : ContentPropertyBasicConverter<ContentPropertyDto>
|
||||
{
|
||||
public ContentPropertyDtoConverter(IDataTypeService dataTypeService, IEntityService entityService)
|
||||
: base(dataTypeService, entityService)
|
||||
{
|
||||
}
|
||||
|
||||
public override ContentPropertyDto Convert(ResolutionContext context)
|
||||
{
|
||||
var propertyDto = base.Convert(context);
|
||||
|
||||
var originalProperty = context.SourceValue as Property;
|
||||
if (originalProperty == null)
|
||||
throw new InvalidOperationException("Source value is not a property.");
|
||||
|
||||
var dataTypeService = DataTypeService;
|
||||
|
||||
propertyDto.IsRequired = originalProperty.PropertyType.Mandatory;
|
||||
propertyDto.ValidationRegExp = originalProperty.PropertyType.ValidationRegExp;
|
||||
propertyDto.Description = originalProperty.PropertyType.Description;
|
||||
propertyDto.Label = originalProperty.PropertyType.Name;
|
||||
|
||||
//TODO: We should be able to look both of these up at the same time!
|
||||
propertyDto.DataType = dataTypeService.GetDataTypeDefinitionById(originalProperty.PropertyType.DataTypeDefinitionId);
|
||||
propertyDto.PreValues = dataTypeService.GetPreValuesCollectionByDataTypeId(originalProperty.PropertyType.DataTypeDefinitionId);
|
||||
|
||||
return propertyDto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Mapping;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// A mapper which declares how to map content properties. These mappings are shared among media (and probably members) which is
|
||||
/// why they are in their own mapper
|
||||
/// </summary>
|
||||
internal class ContentPropertyModelMapper : MapperConfiguration
|
||||
{
|
||||
public override void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext)
|
||||
{
|
||||
//FROM Property TO ContentPropertyBasic
|
||||
config.CreateMap<PropertyGroup, Tab<ContentPropertyDisplay>>()
|
||||
.ForMember(tab => tab.Label, expression => expression.MapFrom(@group => @group.Name))
|
||||
.ForMember(tab => tab.IsActive, expression => expression.UseValue(true))
|
||||
.ForMember(tab => tab.Properties, expression => expression.Ignore())
|
||||
.ForMember(tab => tab.Alias, expression => expression.Ignore());
|
||||
|
||||
//FROM Property TO ContentPropertyBasic
|
||||
config.CreateMap<Property, ContentPropertyBasic>()
|
||||
.ConvertUsing(new ContentPropertyBasicConverter<ContentPropertyBasic>(applicationContext.Services.DataTypeService));
|
||||
|
||||
//FROM Property TO ContentPropertyDto
|
||||
config.CreateMap<Property, ContentPropertyDto>()
|
||||
.ConvertUsing(new ContentPropertyDtoConverter(applicationContext.Services.DataTypeService));
|
||||
|
||||
//FROM Property TO ContentPropertyDisplay
|
||||
config.CreateMap<Property, ContentPropertyDisplay>()
|
||||
.ConvertUsing(new ContentPropertyDisplayConverter(applicationContext.Services.DataTypeService, applicationContext.Services.TextService));
|
||||
}
|
||||
}
|
||||
}
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Mapping;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// A mapper which declares how to map content properties. These mappings are shared among media (and probably members) which is
|
||||
/// why they are in their own mapper
|
||||
/// </summary>
|
||||
internal class ContentPropertyModelMapper : MapperConfiguration
|
||||
{
|
||||
public override void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext)
|
||||
{
|
||||
//FROM Property TO ContentPropertyBasic
|
||||
config.CreateMap<PropertyGroup, Tab<ContentPropertyDisplay>>()
|
||||
.ForMember(tab => tab.Label, expression => expression.MapFrom(@group => @group.Name))
|
||||
.ForMember(tab => tab.IsActive, expression => expression.UseValue(true))
|
||||
.ForMember(tab => tab.Properties, expression => expression.Ignore())
|
||||
.ForMember(tab => tab.Alias, expression => expression.Ignore());
|
||||
|
||||
//FROM Property TO ContentPropertyBasic
|
||||
config.CreateMap<Property, ContentPropertyBasic>()
|
||||
.ConvertUsing(new ContentPropertyBasicConverter<ContentPropertyBasic>(applicationContext.Services.DataTypeService, applicationContext.Services.EntityService));
|
||||
|
||||
//FROM Property TO ContentPropertyDto
|
||||
config.CreateMap<Property, ContentPropertyDto>()
|
||||
.ConvertUsing(new ContentPropertyDtoConverter(applicationContext.Services.DataTypeService, applicationContext.Services.EntityService));
|
||||
|
||||
//FROM Property TO ContentPropertyDisplay
|
||||
config.CreateMap<Property, ContentPropertyDisplay>()
|
||||
.ConvertUsing(new ContentPropertyDisplayConverter(applicationContext.Services.DataTypeService, applicationContext.Services.TextService, applicationContext.Services.EntityService));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
internal class PreValueDisplayResolver : ValueResolver<IDataTypeDefinition, IEnumerable<PreValueFieldDisplay>>
|
||||
{
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
|
||||
public PreValueDisplayResolver(IDataTypeService dataTypeService)
|
||||
{
|
||||
_dataTypeService = dataTypeService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
internal class PreValueDisplayResolver : ValueResolver<IDataTypeDefinition, IEnumerable<PreValueFieldDisplay>>
|
||||
{
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
|
||||
public PreValueDisplayResolver(IDataTypeService dataTypeService)
|
||||
{
|
||||
_dataTypeService = dataTypeService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps pre-values in the dictionary to the values for the fields.
|
||||
/// </summary>
|
||||
/// <param name="fields">The fields.</param>
|
||||
/// <param name="preValues">The pre-values.</param>
|
||||
/// <param name="editorAlias">The editor alias.</param>
|
||||
internal static void MapPreValueValuesToPreValueFields(PreValueFieldDisplay[] fields, IDictionary<string, object> preValues, string editorAlias)
|
||||
{
|
||||
if (fields == null) throw new ArgumentNullException(nameof(fields));
|
||||
if (preValues == null) throw new ArgumentNullException(nameof(preValues));
|
||||
|
||||
// Now we need to wire up the pre-values values with the actual fields defined
|
||||
foreach (var field in fields)
|
||||
{
|
||||
// If the dictionary would be constructed with StringComparer.InvariantCultureIgnoreCase, we could just use TryGetValue
|
||||
var preValue = preValues.SingleOrDefault(x => x.Key.InvariantEquals(field.Key));
|
||||
if (preValue.Key == null)
|
||||
{
|
||||
LogHelper.Warn<PreValueDisplayResolver>("Could not find persisted pre-value for field {0} on property editor {1}", () => field.Key, () => editorAlias);
|
||||
continue;
|
||||
}
|
||||
|
||||
field.Value = preValue.Value;
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<PreValueFieldDisplay> Convert(IDataTypeDefinition source)
|
||||
{
|
||||
PropertyEditor propEd = null;
|
||||
if (source.PropertyEditorAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
propEd = PropertyEditorResolver.Current.GetByAlias(source.PropertyEditorAlias);
|
||||
if (propEd == null)
|
||||
{
|
||||
throw new InvalidOperationException("Could not find property editor with alias " + source.PropertyEditorAlias);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the defaults
|
||||
var dataTypeService = _dataTypeService;
|
||||
var preVals = dataTypeService.GetPreValuesCollectionByDataTypeId(source.Id);
|
||||
IDictionary<string, object> dictionaryVals = preVals.FormatAsDictionary().ToDictionary(x => x.Key, x => (object)x.Value);
|
||||
var result = Enumerable.Empty<PreValueFieldDisplay>().ToArray();
|
||||
|
||||
// If we have a prop editor, then format the pre-values based on it and create it's fields
|
||||
if (propEd != null)
|
||||
{
|
||||
result = propEd.PreValueEditor.Fields.Select(Mapper.Map<PreValueFieldDisplay>).ToArray();
|
||||
dictionaryVals = propEd.PreValueEditor.ConvertDbToEditor(propEd.DefaultPreValues, preVals);
|
||||
}
|
||||
|
||||
MapPreValueValuesToPreValueFields(result, dictionaryVals, source.PropertyEditorAlias);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override IEnumerable<PreValueFieldDisplay> ResolveCore(IDataTypeDefinition source)
|
||||
{
|
||||
return Convert(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Maps pre-values in the dictionary to the values for the fields.
|
||||
/// </summary>
|
||||
/// <param name="fields">The fields.</param>
|
||||
/// <param name="preValues">The pre-values.</param>
|
||||
/// <param name="editorAlias">The editor alias.</param>
|
||||
internal static void MapPreValueValuesToPreValueFields(IEnumerable<PreValueFieldDisplay> fields, IDictionary<string, object> preValues, string editorAlias)
|
||||
{
|
||||
if (fields == null) throw new ArgumentNullException(nameof(fields));
|
||||
if (preValues == null) throw new ArgumentNullException(nameof(preValues));
|
||||
|
||||
// Now we need to wire up the pre-values values with the actual fields defined
|
||||
foreach (var field in fields)
|
||||
{
|
||||
// If the dictionary would be constructed with StringComparer.InvariantCultureIgnoreCase, we could just use TryGetValue
|
||||
var preValue = preValues.SingleOrDefault(x => x.Key.InvariantEquals(field.Key));
|
||||
if (preValue.Key == null)
|
||||
{
|
||||
LogHelper.Warn<PreValueDisplayResolver>("Could not find persisted pre-value for field {0} on property editor {1}", () => field.Key, () => editorAlias);
|
||||
continue;
|
||||
}
|
||||
|
||||
field.Value = preValue.Value;
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<PreValueFieldDisplay> Convert(IDataTypeDefinition source)
|
||||
{
|
||||
PropertyEditor propEd = null;
|
||||
if (source.PropertyEditorAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
propEd = PropertyEditorResolver.Current.GetByAlias(source.PropertyEditorAlias);
|
||||
if (propEd == null)
|
||||
{
|
||||
throw new InvalidOperationException("Could not find property editor with alias " + source.PropertyEditorAlias);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the defaults
|
||||
var dataTypeService = _dataTypeService;
|
||||
var preVals = dataTypeService.GetPreValuesCollectionByDataTypeId(source.Id);
|
||||
IDictionary<string, object> dictionaryVals = preVals.FormatAsDictionary().ToDictionary(x => x.Key, x => (object)x.Value);
|
||||
var result = Enumerable.Empty<PreValueFieldDisplay>();
|
||||
|
||||
// If we have a prop editor, then format the pre-values based on it and create it's fields
|
||||
if (propEd != null)
|
||||
{
|
||||
result = propEd.PreValueEditor.Fields.Select(Mapper.Map<PreValueFieldDisplay>);
|
||||
if (source.IsBuildInDataType())
|
||||
{
|
||||
result = RemovePreValuesNotSupportedOnBuildInTypes(result);
|
||||
}
|
||||
dictionaryVals = propEd.PreValueEditor.ConvertDbToEditor(propEd.DefaultPreValues, preVals);
|
||||
}
|
||||
|
||||
result = result.ToArray();
|
||||
MapPreValueValuesToPreValueFields(result, dictionaryVals, source.PropertyEditorAlias);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private IEnumerable<PreValueFieldDisplay> RemovePreValuesNotSupportedOnBuildInTypes(IEnumerable<PreValueFieldDisplay> preValues)
|
||||
{
|
||||
return preValues.Where(preValue => string.Equals(preValue.Key, Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes) == false);
|
||||
}
|
||||
|
||||
protected override IEnumerable<PreValueFieldDisplay> ResolveCore(IDataTypeDefinition source)
|
||||
{
|
||||
return Convert(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception that occurs when an Umbraco form route string is invalid
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Web.HttpException" />
|
||||
[Serializable]
|
||||
public sealed class HttpUmbracoFormRouteStringException : HttpException
|
||||
{
|
||||
/// Initializes a new instance of the <see cref="HttpUmbracoFormRouteStringException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that holds the contextual information about the source or destination.</param>
|
||||
private HttpUmbracoFormRouteStringException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HttpUmbracoFormRouteStringException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message displayed to the client when the exception is thrown.</param>
|
||||
public HttpUmbracoFormRouteStringException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HttpUmbracoFormRouteStringException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message displayed to the client when the exception is thrown.</param>
|
||||
/// <param name="innerException">The <see cref="P:System.Exception.InnerException" />, if any, that threw the current exception.</param>
|
||||
public HttpUmbracoFormRouteStringException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace Umbraco.Web.Mvc
|
||||
public class RenderRouteHandler : IRouteHandler
|
||||
{
|
||||
// Define reserved dictionary keys for controller, action and area specified in route additional values data
|
||||
private static class ReservedAdditionalKeys
|
||||
internal static class ReservedAdditionalKeys
|
||||
{
|
||||
internal const string Controller = "c";
|
||||
internal const string Action = "a";
|
||||
@@ -142,36 +142,7 @@ namespace Umbraco.Web.Mvc
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
string decryptedString;
|
||||
try
|
||||
{
|
||||
decryptedString = encodedVal.DecryptWithMachineKey();
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
LogHelper.Warn<RenderRouteHandler>("A value was detected in the ufprt parameter but Umbraco could not decrypt the string");
|
||||
return null;
|
||||
}
|
||||
|
||||
var parsedQueryString = HttpUtility.ParseQueryString(decryptedString);
|
||||
var decodedParts = new Dictionary<string, string>();
|
||||
|
||||
foreach (var key in parsedQueryString.AllKeys)
|
||||
{
|
||||
decodedParts[key] = parsedQueryString[key];
|
||||
}
|
||||
|
||||
//validate all required keys exist
|
||||
|
||||
//the controller
|
||||
if (decodedParts.All(x => x.Key != ReservedAdditionalKeys.Controller))
|
||||
return null;
|
||||
//the action
|
||||
if (decodedParts.All(x => x.Key != ReservedAdditionalKeys.Action))
|
||||
return null;
|
||||
//the area
|
||||
if (decodedParts.All(x => x.Key != ReservedAdditionalKeys.Area))
|
||||
if (!UmbracoHelper.DecryptAndValidateEncryptedRouteString(encodedVal, out var decodedParts))
|
||||
return null;
|
||||
|
||||
foreach (var item in decodedParts.Where(x => new[] {
|
||||
@@ -192,6 +163,8 @@ namespace Umbraco.Web.Mvc
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles a posted form to an Umbraco Url and ensures the correct controller is routed to and that
|
||||
/// the right DataTokens are set.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Mvc;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute used to check that the request contains a valid Umbraco form request string.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Web.Mvc.FilterAttribute" />
|
||||
/// <seealso cref="System.Web.Mvc.IAuthorizationFilter" />
|
||||
/// <remarks>
|
||||
/// Applying this attribute/filter to a <see cref="SurfaceController"/> or SurfaceController Action will ensure that the Action can only be executed
|
||||
/// when it is routed to from within Umbraco, typically when rendering a form with BegingUmbracoForm. It will mean that the natural MVC route for this Action
|
||||
/// will fail with a <see cref="HttpUmbracoFormRouteStringException"/>.
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class ValidateUmbracoFormRouteStringAttribute : FilterAttribute, IAuthorizationFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when authorization is required.
|
||||
/// </summary>
|
||||
/// <param name="filterContext">The filter context.</param>
|
||||
/// <exception cref="ArgumentNullException">filterContext</exception>
|
||||
/// <exception cref="Umbraco.Web.Mvc.HttpUmbracoFormRouteStringException">The required request field \"ufprt\" is not present.
|
||||
/// or
|
||||
/// The Umbraco form request route string could not be decrypted.
|
||||
/// or
|
||||
/// The provided Umbraco form request route string was meant for a different controller and action.</exception>
|
||||
public void OnAuthorization(AuthorizationContext filterContext)
|
||||
{
|
||||
if (filterContext == null)
|
||||
throw new ArgumentNullException(nameof(filterContext));
|
||||
|
||||
var ufprt = filterContext.HttpContext.Request["ufprt"];
|
||||
ValidateRouteString(ufprt, filterContext.ActionDescriptor?.ControllerDescriptor.ControllerName, filterContext.ActionDescriptor?.ActionName, filterContext.RouteData?.DataTokens["area"]?.ToString());
|
||||
}
|
||||
|
||||
public void ValidateRouteString(string ufprt, string currentController, string currentAction, string currentArea)
|
||||
{
|
||||
if (ufprt.IsNullOrWhiteSpace())
|
||||
{
|
||||
throw new HttpUmbracoFormRouteStringException("The required request field \"ufprt\" is not present.");
|
||||
}
|
||||
|
||||
if (!UmbracoHelper.DecryptAndValidateEncryptedRouteString(ufprt, out var additionalDataParts))
|
||||
{
|
||||
throw new HttpUmbracoFormRouteStringException("The Umbraco form request route string could not be decrypted.");
|
||||
}
|
||||
|
||||
if (!additionalDataParts[RenderRouteHandler.ReservedAdditionalKeys.Controller].InvariantEquals(currentController) ||
|
||||
!additionalDataParts[RenderRouteHandler.ReservedAdditionalKeys.Action].InvariantEquals(currentAction) ||
|
||||
(!additionalDataParts[RenderRouteHandler.ReservedAdditionalKeys.Area].IsNullOrWhiteSpace() && !additionalDataParts[RenderRouteHandler.ReservedAdditionalKeys.Area].InvariantEquals(currentArea)))
|
||||
{
|
||||
throw new HttpUmbracoFormRouteStringException("The provided Umbraco form request route string was meant for a different controller and action.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,5 @@
|
||||
<Setting Name="test" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">Somthing</Value>
|
||||
</Setting>
|
||||
<Setting Name="umbraco_org_umbraco_our_Repository" Type="(Web Service URL)" Scope="Application">
|
||||
<Value Profile="(Default)">https://our.umbraco.com/umbraco/webservices/api/repository.asmx</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
+1
-11
@@ -12,7 +12,7 @@ namespace Umbraco.Web.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.2.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
@@ -50,15 +50,5 @@ namespace Umbraco.Web.Properties {
|
||||
return ((string)(this["test"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.WebServiceUrl)]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("https://our.umbraco.com/umbraco/webservices/api/repository.asmx")]
|
||||
public string umbraco_org_umbraco_our_Repository {
|
||||
get {
|
||||
return ((string)(this["umbraco_org_umbraco_our_Repository"]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
InternalPreValues = new Dictionary<string, object>
|
||||
{
|
||||
{"startNodeId", "-1"},
|
||||
{"startNodeId", "-1"},
|
||||
{"showOpenButton", "0"},
|
||||
{"showEditButton", "0"},
|
||||
{"showPathOnHover", "0"},
|
||||
{"ignoreUserStartNodes", "0"},
|
||||
{Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes, "0"},
|
||||
{"idType", "udi"}
|
||||
};
|
||||
}
|
||||
@@ -40,9 +40,9 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
public ContentPickerPreValueEditor()
|
||||
{
|
||||
//create the fields
|
||||
//create the fields
|
||||
Fields.Add(new PreValueField()
|
||||
{
|
||||
{
|
||||
Key = "showOpenButton",
|
||||
View = "boolean",
|
||||
Name = "Show open button (this feature is in preview!)",
|
||||
@@ -50,7 +50,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
});
|
||||
Fields.Add(new PreValueField()
|
||||
{
|
||||
Key = "ignoreUserStartNodes",
|
||||
Key = Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes,
|
||||
View = "boolean",
|
||||
Name = "Ignore user start nodes",
|
||||
Description = "Selecting this option allows a user to choose nodes that they normally don't have access to."
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
[PropertyEditor(Core.Constants.PropertyEditors.GridAlias, "Grid layout", "grid", HideLabel = true, IsParameterEditor = false, ValueType = PropertyEditorValueTypes.Json, Group="rich content", Icon="icon-layout")]
|
||||
public class GridPropertyEditor : PropertyEditor, IApplicationEventHandler
|
||||
{
|
||||
{
|
||||
|
||||
private static void DocumentWriting(object sender, Examine.LuceneEngine.DocumentWritingEventArgs e)
|
||||
{
|
||||
@@ -49,7 +49,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
|
||||
foreach (var areaVal in areaVals)
|
||||
{
|
||||
//TODO: If it's not a string, then it's a json formatted value -
|
||||
//TODO: If it's not a string, then it's a json formatted value -
|
||||
// we cannot really index this in a smart way since it could be 'anything'
|
||||
if (areaVal.Type == JTokenType.String)
|
||||
{
|
||||
@@ -87,12 +87,12 @@ namespace Umbraco.Web.PropertyEditors
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
//swallow...on purpose, there's a chance that this isn't the json format we are looking for
|
||||
// and we don't want that to affect the website.
|
||||
// and we don't want that to affect the website.
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
//swallow...on purpose, there's a chance that this isn't json and we don't want that to affect
|
||||
// the website.
|
||||
//swallow...on purpose, there's a chance that this isn't json and we don't want that to affect
|
||||
// the website.
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
@@ -137,7 +137,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
[PreValueField("rte", "Rich text editor", "views/propertyeditors/rte/rte.prevalues.html", Description = "Rich text editor configuration")]
|
||||
public string Rte { get; set; }
|
||||
|
||||
[PreValueField("ignoreUserStartNodes", "Ignore user start nodes", "boolean", Description = "Selecting this option allows a user to choose nodes that they normally don't have access to.")]
|
||||
[PreValueField(Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes, "Ignore user start nodes", "boolean", Description = "Selecting this option allows a user to choose nodes that they normally don't have access to.")]
|
||||
public bool IgnoreUserStartNodes { get; set; }
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// We're going to bind to the Examine events so we can ensure grid data is index nicely.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
|
||||
{
|
||||
foreach (var i in ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>())
|
||||
@@ -175,7 +175,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
|
||||
{
|
||||
//wrap
|
||||
_applicationStartup.OnApplicationStarted(umbracoApplication, applicationContext);
|
||||
_applicationStartup.OnApplicationStarted(umbracoApplication, applicationContext);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
}
|
||||
|
||||
internal IDictionary<string, object> InternalPreValues;
|
||||
|
||||
|
||||
public override IDictionary<string, object> DefaultPreValues
|
||||
{
|
||||
get { return InternalPreValues; }
|
||||
@@ -58,7 +58,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
});
|
||||
Fields.Add(new PreValueField()
|
||||
{
|
||||
Key = "ignoreUserStartNodes",
|
||||
Key = Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes,
|
||||
View = "boolean",
|
||||
Name = "Ignore user start nodes",
|
||||
Description = "Selecting this option allows a user to choose nodes that they normally don't have access to."
|
||||
|
||||
@@ -16,11 +16,11 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{"showOpenButton", "0"},
|
||||
{"showEditButton", "0"},
|
||||
{"showPathOnHover", "0"},
|
||||
{"ignoreUserStartNodes", "0"},
|
||||
{Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes, "0"},
|
||||
{"idType", "udi"}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
protected override PreValueEditor CreatePreValueEditor()
|
||||
{
|
||||
return new MultiNodePickerPreValueEditor();
|
||||
@@ -40,7 +40,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
//create the fields
|
||||
Fields.Add(new PreValueField()
|
||||
{
|
||||
Key = "ignoreUserStartNodes",
|
||||
Key = Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes,
|
||||
View = "boolean",
|
||||
Name = "Ignore user start nodes",
|
||||
Description = "Selecting this option allows a user to choose nodes that they normally don't have access to."
|
||||
@@ -81,7 +81,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
Name = "Show open button (this feature is in preview!)",
|
||||
Description = "Opens the node in a dialog"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This ensures the multiPicker pre-val is set based on the maxNumber of nodes set
|
||||
@@ -117,9 +117,9 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
result["multiPicker"] = "1";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
Fields.Add(new PreValueField()
|
||||
{
|
||||
Key = "ignoreUserStartNodes",
|
||||
Key = Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes,
|
||||
View = "boolean",
|
||||
Name = "Ignore user start nodes",
|
||||
Description = "Selecting this option allows a user to choose nodes that they normally don't have access to."
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
InternalPreValues = new Dictionary<string, object>
|
||||
{
|
||||
{"ignoreUserStartNodes", "0"},
|
||||
{Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes, "0"},
|
||||
{"idType", "udi"}
|
||||
};
|
||||
}
|
||||
@@ -33,11 +33,11 @@ namespace Umbraco.Web.PropertyEditors
|
||||
|
||||
internal class RelatedLinksPreValueEditor : PreValueEditor
|
||||
{
|
||||
[PreValueField("ignoreUserStartNodes", "Ignore user start nodes", "boolean", Description = "Selecting this option allows a user to choose nodes that they normally don't have access to.")]
|
||||
[PreValueField(Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes, "Ignore user start nodes", "boolean", Description = "Selecting this option allows a user to choose nodes that they normally don't have access to.")]
|
||||
public bool IgnoreUserStartNodes { get; set; }
|
||||
|
||||
[PreValueField("max", "Maximum number of links", "number", Description = "Enter the maximum amount of links to be added, enter 0 for unlimited")]
|
||||
public int Maximum { get; set; }
|
||||
public int Maximum { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
//need to figure out how to use this...
|
||||
internal class RichTextPreValueEditor : PreValueEditor
|
||||
{
|
||||
public RichTextPreValueEditor()
|
||||
{
|
||||
//SD: You can add pre-val fields here like you are doing, or you can add fields using attributes (http://issues.umbraco.org/issue/U4-2692),
|
||||
// see below for examples.
|
||||
|
||||
//use a custom editor too
|
||||
Fields.Add(new PreValueField()
|
||||
{
|
||||
View = "views/propertyeditors/rte/rte.prevalues.html",
|
||||
HideLabel = true,
|
||||
Key = "editor"
|
||||
});
|
||||
|
||||
Fields.Add(new PreValueField()
|
||||
{
|
||||
Key = "ignoreUserStartNodes",
|
||||
View = "boolean",
|
||||
Name = "Ignore user start nodes",
|
||||
Description = "Selecting this option allows a user to choose nodes that they normally don't have access to."
|
||||
});
|
||||
|
||||
Fields.Add(new PreValueField()
|
||||
{
|
||||
Name = "Hide Label",
|
||||
View = "boolean",
|
||||
Key = "hideLabel"
|
||||
});
|
||||
}
|
||||
|
||||
//SD: You can declare a field like this if you want to instead of in the ctor, there's some options here:
|
||||
//#1 - the property name becomes the Key:
|
||||
//
|
||||
// [PreValueField("", "views/propertyeditors/rte/rte.prevalues.html", HideLabel = true)]
|
||||
// public string Editor { get; set; }
|
||||
|
||||
//#2 - You can specify a custom Key:
|
||||
//
|
||||
// [PreValueField("editor", "", "views/propertyeditors/rte/rte.prevalues.html", HideLabel = true)]
|
||||
// public string Editor { get; set; }
|
||||
|
||||
//#3 - If you require custom server side validation for your field then you have to specify a custom PreValueField type to use,
|
||||
// this is why in this case I find it easier to use the ctor logic but thats just an opinion
|
||||
// - Any value specified for this property attribute will override the values set in on the class instance of the field, this
|
||||
// allows you to re-use class instances of fields if you want.
|
||||
//
|
||||
// [PreValueField(typeof(EditorPreValueField))]
|
||||
// public string Editor { get; set; }
|
||||
|
||||
// [PreValueField("", "views/propertyeditors/rte/rte.prevalues.html", HideLabel = true)]
|
||||
// public class EditorPreValueField : PreValueField
|
||||
// {
|
||||
// public EditorPreValueField()
|
||||
// {
|
||||
// //add any required server validators for this field
|
||||
// Validators.Add(new RegexValidator("^\\d*$"));
|
||||
// //You could also set the field properties directly here if you wanted instead of the attribute
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
//need to figure out how to use this...
|
||||
internal class RichTextPreValueEditor : PreValueEditor
|
||||
{
|
||||
public RichTextPreValueEditor()
|
||||
{
|
||||
//SD: You can add pre-val fields here like you are doing, or you can add fields using attributes (http://issues.umbraco.org/issue/U4-2692),
|
||||
// see below for examples.
|
||||
|
||||
//use a custom editor too
|
||||
Fields.Add(new PreValueField()
|
||||
{
|
||||
View = "views/propertyeditors/rte/rte.prevalues.html",
|
||||
HideLabel = true,
|
||||
Key = "editor"
|
||||
});
|
||||
|
||||
Fields.Add(new PreValueField()
|
||||
{
|
||||
Key = Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes,
|
||||
View = "boolean",
|
||||
Name = "Ignore user start nodes",
|
||||
Description = "Selecting this option allows a user to choose nodes that they normally don't have access to."
|
||||
});
|
||||
|
||||
Fields.Add(new PreValueField()
|
||||
{
|
||||
Name = "Hide Label",
|
||||
View = "boolean",
|
||||
Key = "hideLabel"
|
||||
});
|
||||
}
|
||||
|
||||
//SD: You can declare a field like this if you want to instead of in the ctor, there's some options here:
|
||||
//#1 - the property name becomes the Key:
|
||||
//
|
||||
// [PreValueField("", "views/propertyeditors/rte/rte.prevalues.html", HideLabel = true)]
|
||||
// public string Editor { get; set; }
|
||||
|
||||
//#2 - You can specify a custom Key:
|
||||
//
|
||||
// [PreValueField("editor", "", "views/propertyeditors/rte/rte.prevalues.html", HideLabel = true)]
|
||||
// public string Editor { get; set; }
|
||||
|
||||
//#3 - If you require custom server side validation for your field then you have to specify a custom PreValueField type to use,
|
||||
// this is why in this case I find it easier to use the ctor logic but thats just an opinion
|
||||
// - Any value specified for this property attribute will override the values set in on the class instance of the field, this
|
||||
// allows you to re-use class instances of fields if you want.
|
||||
//
|
||||
// [PreValueField(typeof(EditorPreValueField))]
|
||||
// public string Editor { get; set; }
|
||||
|
||||
// [PreValueField("", "views/propertyeditors/rte/rte.prevalues.html", HideLabel = true)]
|
||||
// public class EditorPreValueField : PreValueField
|
||||
// {
|
||||
// public EditorPreValueField()
|
||||
// {
|
||||
// //add any required server validators for this field
|
||||
// Validators.Add(new RegexValidator("^\\d*$"));
|
||||
// //You could also set the field properties directly here if you wanted instead of the attribute
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,31 +15,6 @@ namespace Umbraco.Web.Search
|
||||
{
|
||||
internal class UmbracoTreeSearcher
|
||||
{
|
||||
/// <summary>
|
||||
/// This method is obsolete, use the overload with ignoreUserStartNodes instead
|
||||
/// Searches for results based on the entity type
|
||||
/// </summary>
|
||||
/// <param name="umbracoHelper"></param>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="entityType"></param>
|
||||
/// <param name="totalFound"></param>
|
||||
/// <param name="searchFrom">
|
||||
/// A starting point for the search, generally a node id, but for members this is a member type alias
|
||||
/// </param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("This method is obsolete, use the overload with ignoreUserStartNodes instead", false)]
|
||||
public IEnumerable<SearchResultItem> ExamineSearch(
|
||||
UmbracoHelper umbracoHelper,
|
||||
string query,
|
||||
UmbracoEntityTypes entityType,
|
||||
int pageSize,
|
||||
long pageIndex, out long totalFound, string searchFrom = null)
|
||||
{
|
||||
return ExamineSearch(umbracoHelper, query, entityType, pageSize, pageIndex, out totalFound, false, searchFrom);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for results based on the entity type
|
||||
/// </summary>
|
||||
@@ -59,7 +34,7 @@ namespace Umbraco.Web.Search
|
||||
string query,
|
||||
UmbracoEntityTypes entityType,
|
||||
int pageSize,
|
||||
long pageIndex, out long totalFound, bool ignoreUserStartNodes, string searchFrom = null)
|
||||
long pageIndex, out long totalFound, string searchFrom = null, bool ignoreUserStartNodes = false)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Core;
|
||||
using System.Web.Helpers;
|
||||
using System.Web;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Web.Security
|
||||
{
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public class UmbracoAntiForgeryAdditionalDataProvider : IAntiForgeryAdditionalDataProvider
|
||||
{
|
||||
private readonly IAntiForgeryAdditionalDataProvider _defaultProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor, allows wrapping a default provider
|
||||
/// </summary>
|
||||
/// <param name="defaultProvider"></param>
|
||||
public UmbracoAntiForgeryAdditionalDataProvider(IAntiForgeryAdditionalDataProvider defaultProvider)
|
||||
{
|
||||
_defaultProvider = defaultProvider;
|
||||
}
|
||||
|
||||
public string GetAdditionalData(HttpContextBase context)
|
||||
{
|
||||
return JsonConvert.SerializeObject(new AdditionalData
|
||||
{
|
||||
Stamp = DateTime.UtcNow.Ticks,
|
||||
//this value will be here if this is a BeginUmbracoForms form
|
||||
Ufprt = context.Items["ufprt"]?.ToString(),
|
||||
//if there was a wrapped provider, add it's value to the json, else just a static value
|
||||
WrappedValue = _defaultProvider?.GetAdditionalData(context) ?? "default"
|
||||
});
|
||||
}
|
||||
|
||||
public bool ValidateAdditionalData(HttpContextBase context, string additionalData)
|
||||
{
|
||||
if (!additionalData.DetectIsJson())
|
||||
return false; //must be json
|
||||
|
||||
AdditionalData json;
|
||||
try
|
||||
{
|
||||
json = JsonConvert.DeserializeObject<AdditionalData>(additionalData);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false; //couldn't parse
|
||||
}
|
||||
|
||||
if (json.Stamp == default) return false;
|
||||
|
||||
//if there was a wrapped provider, validate it, else validate the static value
|
||||
var validateWrapped = _defaultProvider?.ValidateAdditionalData(context, json.WrappedValue) ?? json.WrappedValue == "default";
|
||||
if (!validateWrapped)
|
||||
return false;
|
||||
|
||||
var ufprtRequest = context.Request["ufprt"]?.ToString();
|
||||
|
||||
//if the custom BeginUmbracoForms route value is not there, then it's nothing more to validate
|
||||
if (ufprtRequest.IsNullOrWhiteSpace() && json.Ufprt.IsNullOrWhiteSpace())
|
||||
return true;
|
||||
|
||||
//if one or the other is null then something is wrong
|
||||
if (!ufprtRequest.IsNullOrWhiteSpace() && json.Ufprt.IsNullOrWhiteSpace()) return false;
|
||||
if (ufprtRequest.IsNullOrWhiteSpace() && !json.Ufprt.IsNullOrWhiteSpace()) return false;
|
||||
|
||||
if (!UmbracoHelper.DecryptAndValidateEncryptedRouteString(json.Ufprt, out var additionalDataParts))
|
||||
return false;
|
||||
|
||||
if (!UmbracoHelper.DecryptAndValidateEncryptedRouteString(ufprtRequest, out var requestParts))
|
||||
return false;
|
||||
|
||||
//ensure they all match
|
||||
return additionalDataParts.Count == requestParts.Count
|
||||
&& additionalDataParts[RenderRouteHandler.ReservedAdditionalKeys.Controller] == requestParts[RenderRouteHandler.ReservedAdditionalKeys.Controller]
|
||||
&& additionalDataParts[RenderRouteHandler.ReservedAdditionalKeys.Action] == requestParts[RenderRouteHandler.ReservedAdditionalKeys.Action]
|
||||
&& additionalDataParts[RenderRouteHandler.ReservedAdditionalKeys.Area] == requestParts[RenderRouteHandler.ReservedAdditionalKeys.Area];
|
||||
}
|
||||
|
||||
internal class AdditionalData
|
||||
{
|
||||
public string Ufprt { get; set; }
|
||||
public long Stamp { get; set; }
|
||||
public string WrappedValue { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -207,9 +207,6 @@ namespace Umbraco.Web.Trees
|
||||
return HasPathAccess(entity, queryStrings);
|
||||
}
|
||||
|
||||
internal override IEnumerable<IUmbracoEntity> GetChildrenFromEntityService(int entityId)
|
||||
=> Services.EntityService.GetChildren(entityId, UmbracoObjectType).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a collection of all menu items that can be on a content node
|
||||
/// </summary>
|
||||
|
||||
@@ -87,11 +87,12 @@ namespace Umbraco.Web.Trees
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
internal TreeNode GetSingleTreeNodeWithAccessCheck(IUmbracoEntity e, string parentId, FormDataCollection queryStrings)
|
||||
internal TreeNode GetSingleTreeNodeWithAccessCheck(IUmbracoEntity e, string parentId, FormDataCollection queryStrings,
|
||||
int[] startNodeIds, string[] startNodePaths, bool ignoreUserStartNodes)
|
||||
{
|
||||
bool hasPathAccess;
|
||||
var entityIsAncestorOfStartNodes = Security.CurrentUser.IsInBranchOfStartNode(e, Services.EntityService, RecycleBinId, out hasPathAccess);
|
||||
if (IgnoreUserStartNodes(queryStrings) == false && entityIsAncestorOfStartNodes == false)
|
||||
var entityIsAncestorOfStartNodes = UserExtensions.IsInBranchOfStartNode(e.Path, startNodeIds, startNodePaths, out hasPathAccess);
|
||||
if (ignoreUserStartNodes == false && entityIsAncestorOfStartNodes == false)
|
||||
return null;
|
||||
|
||||
var treeNode = GetSingleTreeNode(e, parentId, queryStrings);
|
||||
@@ -101,13 +102,30 @@ namespace Umbraco.Web.Trees
|
||||
//the node so we need to return null;
|
||||
return null;
|
||||
}
|
||||
if (IgnoreUserStartNodes(queryStrings) == false && hasPathAccess == false)
|
||||
if (ignoreUserStartNodes == false && hasPathAccess == false)
|
||||
{
|
||||
treeNode.AdditionalData["noAccess"] = true;
|
||||
}
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
private void GetUserStartNodes(out int[] startNodeIds, out string[] startNodePaths)
|
||||
{
|
||||
switch (RecycleBinId)
|
||||
{
|
||||
case Constants.System.RecycleBinMedia:
|
||||
startNodeIds = Security.CurrentUser.CalculateMediaStartNodeIds(Services.EntityService);
|
||||
startNodePaths = Security.CurrentUser.GetMediaStartNodePaths(Services.EntityService);
|
||||
break;
|
||||
case Constants.System.RecycleBinContent:
|
||||
startNodeIds = Security.CurrentUser.CalculateContentStartNodeIds(Services.EntityService);
|
||||
startNodePaths = Security.CurrentUser.GetContentStartNodePaths(Services.EntityService);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Path access is only determined on content or media");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the
|
||||
/// </summary>
|
||||
@@ -134,6 +152,8 @@ namespace Umbraco.Web.Trees
|
||||
? queryStrings.GetValue<string>(TreeQueryStringParameters.StartNodeId)
|
||||
: string.Empty;
|
||||
|
||||
var ignoreUserStartNodes = IgnoreUserStartNodes(queryStrings);
|
||||
|
||||
if (string.IsNullOrEmpty(startNodeId) == false && startNodeId != "undefined" && startNodeId != rootIdString)
|
||||
{
|
||||
// request has been made to render from a specific, non-root, start node
|
||||
@@ -141,7 +161,7 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
// ensure that the user has access to that node, otherwise return the empty tree nodes collection
|
||||
// TODO: in the future we could return a validation statement so we can have some UI to notify the user they don't have access
|
||||
if (IgnoreUserStartNodes(queryStrings) == false && HasPathAccess(id, queryStrings) == false)
|
||||
if (ignoreUserStartNodes == false && HasPathAccess(id, queryStrings) == false)
|
||||
{
|
||||
LogHelper.Warn<ContentTreeControllerBase>("User " + Security.CurrentUser.Username + " does not have access to node with id " + id);
|
||||
return nodes;
|
||||
@@ -159,7 +179,11 @@ namespace Umbraco.Web.Trees
|
||||
// get child entities - if id is root, but user's start nodes do not contain the
|
||||
// root node, this returns the start nodes instead of root's children
|
||||
var entities = GetChildEntities(id, queryStrings).ToList();
|
||||
nodes.AddRange(entities.Select(x => GetSingleTreeNodeWithAccessCheck(x, id, queryStrings)).Where(x => x != null));
|
||||
|
||||
//get the current user start node/paths
|
||||
GetUserStartNodes(out var userStartNodes, out var userStartNodePaths);
|
||||
|
||||
nodes.AddRange(entities.Select(x => GetSingleTreeNodeWithAccessCheck(x, id, queryStrings, userStartNodes, userStartNodePaths, ignoreUserStartNodes)).Where(x => x != null));
|
||||
|
||||
// if the user does not have access to the root node, what we have is the start nodes,
|
||||
// but to provide some context we also need to add their topmost nodes when they are not
|
||||
@@ -170,7 +194,7 @@ namespace Umbraco.Web.Trees
|
||||
if (topNodeIds.Length > 0)
|
||||
{
|
||||
var topNodes = Services.EntityService.GetAll(UmbracoObjectType, topNodeIds.ToArray());
|
||||
nodes.AddRange(topNodes.Select(x => GetSingleTreeNodeWithAccessCheck(x, id, queryStrings)).Where(x => x != null));
|
||||
nodes.AddRange(topNodes.Select(x => GetSingleTreeNodeWithAccessCheck(x, id, queryStrings, userStartNodes, userStartNodePaths, ignoreUserStartNodes)).Where(x => x != null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,12 +229,8 @@ namespace Umbraco.Web.Trees
|
||||
return GetChildrenFromEntityService(entityId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract method to fetch the entities from the entity service
|
||||
/// </summary>
|
||||
/// <param name="entityId"></param>
|
||||
/// <returns></returns>
|
||||
internal abstract IEnumerable<IUmbracoEntity> GetChildrenFromEntityService(int entityId);
|
||||
private IEnumerable<IUmbracoEntity> GetChildrenFromEntityService(int entityId)
|
||||
=> Services.EntityService.GetChildren(entityId, UmbracoObjectType).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Returns true or false if the current user has access to the node based on the user's allowed start node (path) access
|
||||
@@ -486,5 +506,21 @@ namespace Umbraco.Web.Trees
|
||||
}
|
||||
|
||||
private readonly ConcurrentDictionary<string, IUmbracoEntity> _entityCache = new ConcurrentDictionary<string, IUmbracoEntity>();
|
||||
|
||||
/// <summary>
|
||||
/// If the request should allows a user to choose nodes that they normally don't have access to
|
||||
/// </summary>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
internal bool IgnoreUserStartNodes(FormDataCollection queryStrings)
|
||||
{
|
||||
var dataTypeId = queryStrings.GetValue<Guid?>(TreeQueryStringParameters.DataTypeId);
|
||||
if (dataTypeId.HasValue)
|
||||
{
|
||||
return Services.DataTypeService.IsDataTypeIgnoringUserStartNodes(dataTypeId.Value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,12 +177,6 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
return _treeSearcher.ExamineSearch(Umbraco, query, UmbracoEntityTypes.Media, pageSize, pageIndex, out totalFound, searchFrom);
|
||||
}
|
||||
|
||||
internal override IEnumerable<IUmbracoEntity> GetChildrenFromEntityService(int entityId)
|
||||
// Not pretty having to cast the service, but it is the only way to get to use an internal method that we
|
||||
// do not want to make public on the interface. Unfortunately also prevents this from being unit tested.
|
||||
// See this issue for details on why we need this:
|
||||
// https://github.com/umbraco/Umbraco-CMS/issues/3457
|
||||
=> ((EntityService)Services.EntityService).GetMediaChildrenWithoutPropertyData(entityId).ToList();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,401 +1,392 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Formatting;
|
||||
using System.Web.Http.ModelBinding;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Web.Models.Trees;
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Web.Search;
|
||||
|
||||
namespace Umbraco.Web.Trees
|
||||
{
|
||||
/// <summary>
|
||||
/// A base controller reference for non-attributed trees (un-registered). Developers should inherit from
|
||||
/// TreeController.
|
||||
/// </summary>
|
||||
[AngularJsonOnlyConfiguration]
|
||||
public abstract class TreeControllerBase : UmbracoAuthorizedApiController
|
||||
{
|
||||
protected TreeControllerBase()
|
||||
{
|
||||
}
|
||||
|
||||
protected TreeControllerBase(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
|
||||
protected TreeControllerBase(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) : base(umbracoContext, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The method called to render the contents of the tree structure
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="queryStrings">
|
||||
/// All of the query string parameters passed from jsTree
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// We are allowing an arbitrary number of query strings to be pased in so that developers are able to persist custom data from the front-end
|
||||
/// to the back end to be used in the query for model data.
|
||||
/// </remarks>
|
||||
protected abstract TreeNodeCollection GetTreeNodes(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the menu structure for the node
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
protected abstract MenuItemCollection GetMenuForNode(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings);
|
||||
|
||||
/// <summary>
|
||||
/// The name to display on the root node
|
||||
/// </summary>
|
||||
public abstract string RootNodeDisplayName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current tree alias from the attribute assigned to it.
|
||||
/// </summary>
|
||||
public abstract string TreeAlias { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the root node for the tree
|
||||
/// </summary>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode GetRootNode([ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings)
|
||||
{
|
||||
if (queryStrings == null) queryStrings = new FormDataCollection("");
|
||||
var node = CreateRootNode(queryStrings);
|
||||
|
||||
//add the tree alias to the root
|
||||
node.AdditionalData["treeAlias"] = TreeAlias;
|
||||
|
||||
AddQueryStringsToAdditionalData(node, queryStrings);
|
||||
|
||||
//check if the tree is searchable and add that to the meta data as well
|
||||
if (this is ISearchableTree)
|
||||
{
|
||||
node.AdditionalData.Add("searchable", "true");
|
||||
}
|
||||
|
||||
//now update all data based on some of the query strings, like if we are running in dialog mode
|
||||
if (IsDialog(queryStrings))
|
||||
{
|
||||
node.RoutePath = "#";
|
||||
}
|
||||
|
||||
OnRootNodeRendering(this, new TreeNodeRenderingEventArgs(node, queryStrings));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The action called to render the contents of the tree structure
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="queryStrings">
|
||||
/// All of the query string parameters passed from jsTree
|
||||
/// </param>
|
||||
/// <returns>JSON markup for jsTree</returns>
|
||||
/// <remarks>
|
||||
/// We are allowing an arbitrary number of query strings to be pased in so that developers are able to persist custom data from the front-end
|
||||
/// to the back end to be used in the query for model data.
|
||||
/// </remarks>
|
||||
public TreeNodeCollection GetNodes(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings)
|
||||
{
|
||||
if (queryStrings == null) queryStrings = new FormDataCollection("");
|
||||
var nodes = GetTreeNodes(id, queryStrings);
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
AddQueryStringsToAdditionalData(node, queryStrings);
|
||||
}
|
||||
|
||||
//now update all data based on some of the query strings, like if we are running in dialog mode
|
||||
if (IsDialog((queryStrings)))
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
node.RoutePath = "#";
|
||||
}
|
||||
}
|
||||
|
||||
//raise the event
|
||||
OnTreeNodesRendering(this, new TreeNodesRenderingEventArgs(nodes, queryStrings));
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The action called to render the menu for a tree node
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
public MenuItemCollection GetMenu(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings)
|
||||
{
|
||||
if (queryStrings == null) queryStrings = new FormDataCollection("");
|
||||
var menu = GetMenuForNode(id, queryStrings);
|
||||
//raise the event
|
||||
OnMenuRendering(this, new MenuRenderingEventArgs(id, menu, queryStrings));
|
||||
return menu;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a root model for a tree
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual TreeNode CreateRootNode(FormDataCollection queryStrings)
|
||||
{
|
||||
var rootNodeAsString = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
|
||||
var currApp = queryStrings.GetValue<string>(TreeQueryStringParameters.Application);
|
||||
|
||||
var node = new TreeNode(
|
||||
rootNodeAsString,
|
||||
null, //this is a root node, there is no parent
|
||||
Url.GetTreeUrl(GetType(), rootNodeAsString, queryStrings),
|
||||
Url.GetMenuUrl(GetType(), rootNodeAsString, queryStrings))
|
||||
{
|
||||
HasChildren = true,
|
||||
RoutePath = currApp,
|
||||
Name = RootNodeDisplayName
|
||||
};
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
#region Create TreeNode methods
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title)
|
||||
{
|
||||
var jsonUrl = Url.GetTreeUrl(GetType(), id, queryStrings);
|
||||
var menuUrl = Url.GetMenuUrl(GetType(), id, queryStrings);
|
||||
var node = new TreeNode(id, parentId, jsonUrl, menuUrl) { Name = title };
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title, string icon)
|
||||
{
|
||||
var jsonUrl = Url.GetTreeUrl(GetType(), id, queryStrings);
|
||||
var menuUrl = Url.GetMenuUrl(GetType(), id, queryStrings);
|
||||
var node = new TreeNode(id, parentId, jsonUrl, menuUrl)
|
||||
{
|
||||
Name = title,
|
||||
Icon = icon,
|
||||
NodeType = TreeAlias
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="routePath"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title, string icon, string routePath)
|
||||
{
|
||||
var jsonUrl = Url.GetTreeUrl(GetType(), id, queryStrings);
|
||||
var menuUrl = Url.GetMenuUrl(GetType(), id, queryStrings);
|
||||
var node = new TreeNode(id, parentId, jsonUrl, menuUrl) { Name = title, RoutePath = routePath, Icon = icon };
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes and automatically generate the json url + UDI
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="entityObjectType"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="hasChildren"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(UmbracoEntity entity, Guid entityObjectType, string parentId, FormDataCollection queryStrings, bool hasChildren)
|
||||
{
|
||||
var treeNode = CreateTreeNode(entity.Id.ToInvariantString(), parentId, queryStrings, entity.Name, entity.ContentTypeIcon);
|
||||
treeNode.Path = entity.Path;
|
||||
treeNode.Udi = Udi.Create(UmbracoObjectTypesExtensions.GetUdiType(entityObjectType), entity.Key);
|
||||
treeNode.HasChildren = hasChildren;
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes and automatically generate the json url + UDI
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="entityObjectType"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <param name="hasChildren"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(IUmbracoEntity entity, Guid entityObjectType, string parentId, FormDataCollection queryStrings, string icon, bool hasChildren)
|
||||
{
|
||||
var treeNode = CreateTreeNode(entity.Id.ToInvariantString(), parentId, queryStrings, entity.Name, icon);
|
||||
treeNode.Path = entity.Path;
|
||||
treeNode.Udi = Udi.Create(UmbracoObjectTypesExtensions.GetUdiType(entityObjectType), entity.Key);
|
||||
treeNode.HasChildren = hasChildren;
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes and automatically generate the json url
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <param name="hasChildren"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title, string icon, bool hasChildren)
|
||||
{
|
||||
var treeNode = CreateTreeNode(id, parentId, queryStrings, title, icon);
|
||||
treeNode.HasChildren = hasChildren;
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes and automatically generate the json url
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="routePath"></param>
|
||||
/// <param name="hasChildren"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title, string icon, bool hasChildren, string routePath)
|
||||
{
|
||||
var treeNode = CreateTreeNode(id, parentId, queryStrings, title, icon);
|
||||
treeNode.HasChildren = hasChildren;
|
||||
treeNode.RoutePath = routePath;
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes and automatically generate the json url + UDI
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="routePath"></param>
|
||||
/// <param name="hasChildren"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <param name="udi"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title, string icon, bool hasChildren, string routePath, Udi udi)
|
||||
{
|
||||
var treeNode = CreateTreeNode(id, parentId, queryStrings, title, icon);
|
||||
treeNode.HasChildren = hasChildren;
|
||||
treeNode.RoutePath = routePath;
|
||||
treeNode.Udi = udi;
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The AdditionalData of a node is always populated with the query string data, this method performs this
|
||||
/// operation and ensures that special values are not inserted or that duplicate keys are not added.
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
protected void AddQueryStringsToAdditionalData(TreeNode node, FormDataCollection queryStrings)
|
||||
{
|
||||
foreach (var q in queryStrings.Where(x => node.AdditionalData.ContainsKey(x.Key) == false))
|
||||
{
|
||||
node.AdditionalData.Add(q.Key, q.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the request is for a dialog mode tree
|
||||
/// </summary>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
protected bool IsDialog(FormDataCollection queryStrings)
|
||||
{
|
||||
return queryStrings.GetValue<bool>(TreeQueryStringParameters.IsDialog);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the request should allows a user to choose nodes that they normally don't have access to
|
||||
/// </summary>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
protected bool IgnoreUserStartNodes(FormDataCollection queryStrings)
|
||||
{
|
||||
return queryStrings.GetValue<bool>(TreeQueryStringParameters.IgnoreUserStartNodes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An event that allows developers to modify the tree node collection that is being rendered
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Developers can add/remove/replace/insert/update/etc... any of the tree items in the collection.
|
||||
/// </remarks>
|
||||
public static event TypedEventHandler<TreeControllerBase, TreeNodesRenderingEventArgs> TreeNodesRendering;
|
||||
|
||||
private static void OnTreeNodesRendering(TreeControllerBase instance, TreeNodesRenderingEventArgs e)
|
||||
{
|
||||
var handler = TreeNodesRendering;
|
||||
if (handler != null) handler(instance, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An event that allows developer to modify the root tree node that is being rendered
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<TreeControllerBase, TreeNodeRenderingEventArgs> RootNodeRendering;
|
||||
|
||||
private static void OnRootNodeRendering(TreeControllerBase instance, TreeNodeRenderingEventArgs e)
|
||||
{
|
||||
var handler = RootNodeRendering;
|
||||
if (handler != null) handler(instance, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An event that allows developers to modify the meun that is being rendered
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Developers can add/remove/replace/insert/update/etc... any of the tree items in the collection.
|
||||
/// </remarks>
|
||||
public static event TypedEventHandler<TreeControllerBase, MenuRenderingEventArgs> MenuRendering;
|
||||
|
||||
private static void OnMenuRendering(TreeControllerBase instance, MenuRenderingEventArgs e)
|
||||
{
|
||||
var handler = MenuRendering;
|
||||
if (handler != null) handler(instance, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Formatting;
|
||||
using System.Web.Http.ModelBinding;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Web.Models.Trees;
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Search;
|
||||
|
||||
namespace Umbraco.Web.Trees
|
||||
{
|
||||
/// <summary>
|
||||
/// A base controller reference for non-attributed trees (un-registered). Developers should inherit from
|
||||
/// TreeController.
|
||||
/// </summary>
|
||||
[AngularJsonOnlyConfiguration]
|
||||
public abstract class TreeControllerBase : UmbracoAuthorizedApiController
|
||||
{
|
||||
protected TreeControllerBase()
|
||||
{
|
||||
}
|
||||
|
||||
protected TreeControllerBase(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
|
||||
protected TreeControllerBase(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) : base(umbracoContext, umbracoHelper)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The method called to render the contents of the tree structure
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="queryStrings">
|
||||
/// All of the query string parameters passed from jsTree
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// We are allowing an arbitrary number of query strings to be pased in so that developers are able to persist custom data from the front-end
|
||||
/// to the back end to be used in the query for model data.
|
||||
/// </remarks>
|
||||
protected abstract TreeNodeCollection GetTreeNodes(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the menu structure for the node
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
protected abstract MenuItemCollection GetMenuForNode(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings);
|
||||
|
||||
/// <summary>
|
||||
/// The name to display on the root node
|
||||
/// </summary>
|
||||
public abstract string RootNodeDisplayName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current tree alias from the attribute assigned to it.
|
||||
/// </summary>
|
||||
public abstract string TreeAlias { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the root node for the tree
|
||||
/// </summary>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode GetRootNode([ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings)
|
||||
{
|
||||
if (queryStrings == null) queryStrings = new FormDataCollection("");
|
||||
var node = CreateRootNode(queryStrings);
|
||||
|
||||
//add the tree alias to the root
|
||||
node.AdditionalData["treeAlias"] = TreeAlias;
|
||||
|
||||
AddQueryStringsToAdditionalData(node, queryStrings);
|
||||
|
||||
//check if the tree is searchable and add that to the meta data as well
|
||||
if (this is ISearchableTree)
|
||||
{
|
||||
node.AdditionalData.Add("searchable", "true");
|
||||
}
|
||||
|
||||
//now update all data based on some of the query strings, like if we are running in dialog mode
|
||||
if (IsDialog(queryStrings))
|
||||
{
|
||||
node.RoutePath = "#";
|
||||
}
|
||||
|
||||
OnRootNodeRendering(this, new TreeNodeRenderingEventArgs(node, queryStrings));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The action called to render the contents of the tree structure
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="queryStrings">
|
||||
/// All of the query string parameters passed from jsTree
|
||||
/// </param>
|
||||
/// <returns>JSON markup for jsTree</returns>
|
||||
/// <remarks>
|
||||
/// We are allowing an arbitrary number of query strings to be pased in so that developers are able to persist custom data from the front-end
|
||||
/// to the back end to be used in the query for model data.
|
||||
/// </remarks>
|
||||
public TreeNodeCollection GetNodes(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings)
|
||||
{
|
||||
if (queryStrings == null) queryStrings = new FormDataCollection("");
|
||||
var nodes = GetTreeNodes(id, queryStrings);
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
AddQueryStringsToAdditionalData(node, queryStrings);
|
||||
}
|
||||
|
||||
//now update all data based on some of the query strings, like if we are running in dialog mode
|
||||
if (IsDialog((queryStrings)))
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
node.RoutePath = "#";
|
||||
}
|
||||
}
|
||||
|
||||
//raise the event
|
||||
OnTreeNodesRendering(this, new TreeNodesRenderingEventArgs(nodes, queryStrings));
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The action called to render the menu for a tree node
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
public MenuItemCollection GetMenu(string id, [ModelBinder(typeof(HttpQueryStringModelBinder))]FormDataCollection queryStrings)
|
||||
{
|
||||
if (queryStrings == null) queryStrings = new FormDataCollection("");
|
||||
var menu = GetMenuForNode(id, queryStrings);
|
||||
//raise the event
|
||||
OnMenuRendering(this, new MenuRenderingEventArgs(id, menu, queryStrings));
|
||||
return menu;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a root model for a tree
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual TreeNode CreateRootNode(FormDataCollection queryStrings)
|
||||
{
|
||||
var rootNodeAsString = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
|
||||
var currApp = queryStrings.GetValue<string>(TreeQueryStringParameters.Application);
|
||||
|
||||
var node = new TreeNode(
|
||||
rootNodeAsString,
|
||||
null, //this is a root node, there is no parent
|
||||
Url.GetTreeUrl(GetType(), rootNodeAsString, queryStrings),
|
||||
Url.GetMenuUrl(GetType(), rootNodeAsString, queryStrings))
|
||||
{
|
||||
HasChildren = true,
|
||||
RoutePath = currApp,
|
||||
Name = RootNodeDisplayName
|
||||
};
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
#region Create TreeNode methods
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title)
|
||||
{
|
||||
var jsonUrl = Url.GetTreeUrl(GetType(), id, queryStrings);
|
||||
var menuUrl = Url.GetMenuUrl(GetType(), id, queryStrings);
|
||||
var node = new TreeNode(id, parentId, jsonUrl, menuUrl) { Name = title };
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title, string icon)
|
||||
{
|
||||
var jsonUrl = Url.GetTreeUrl(GetType(), id, queryStrings);
|
||||
var menuUrl = Url.GetMenuUrl(GetType(), id, queryStrings);
|
||||
var node = new TreeNode(id, parentId, jsonUrl, menuUrl)
|
||||
{
|
||||
Name = title,
|
||||
Icon = icon,
|
||||
NodeType = TreeAlias
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="routePath"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title, string icon, string routePath)
|
||||
{
|
||||
var jsonUrl = Url.GetTreeUrl(GetType(), id, queryStrings);
|
||||
var menuUrl = Url.GetMenuUrl(GetType(), id, queryStrings);
|
||||
var node = new TreeNode(id, parentId, jsonUrl, menuUrl) { Name = title, RoutePath = routePath, Icon = icon };
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes and automatically generate the json url + UDI
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="entityObjectType"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="hasChildren"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(UmbracoEntity entity, Guid entityObjectType, string parentId, FormDataCollection queryStrings, bool hasChildren)
|
||||
{
|
||||
var treeNode = CreateTreeNode(entity.Id.ToInvariantString(), parentId, queryStrings, entity.Name, entity.ContentTypeIcon);
|
||||
treeNode.Path = entity.Path;
|
||||
treeNode.Udi = Udi.Create(UmbracoObjectTypesExtensions.GetUdiType(entityObjectType), entity.Key);
|
||||
treeNode.HasChildren = hasChildren;
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes and automatically generate the json url + UDI
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="entityObjectType"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <param name="hasChildren"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(IUmbracoEntity entity, Guid entityObjectType, string parentId, FormDataCollection queryStrings, string icon, bool hasChildren)
|
||||
{
|
||||
var treeNode = CreateTreeNode(entity.Id.ToInvariantString(), parentId, queryStrings, entity.Name, icon);
|
||||
treeNode.Path = entity.Path;
|
||||
treeNode.Udi = Udi.Create(UmbracoObjectTypesExtensions.GetUdiType(entityObjectType), entity.Key);
|
||||
treeNode.HasChildren = hasChildren;
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes and automatically generate the json url
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <param name="hasChildren"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title, string icon, bool hasChildren)
|
||||
{
|
||||
var treeNode = CreateTreeNode(id, parentId, queryStrings, title, icon);
|
||||
treeNode.HasChildren = hasChildren;
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes and automatically generate the json url
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="routePath"></param>
|
||||
/// <param name="hasChildren"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title, string icon, bool hasChildren, string routePath)
|
||||
{
|
||||
var treeNode = CreateTreeNode(id, parentId, queryStrings, title, icon);
|
||||
treeNode.HasChildren = hasChildren;
|
||||
treeNode.RoutePath = routePath;
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create tree nodes and automatically generate the json url + UDI
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="routePath"></param>
|
||||
/// <param name="hasChildren"></param>
|
||||
/// <param name="icon"></param>
|
||||
/// <param name="udi"></param>
|
||||
/// <returns></returns>
|
||||
public TreeNode CreateTreeNode(string id, string parentId, FormDataCollection queryStrings, string title, string icon, bool hasChildren, string routePath, Udi udi)
|
||||
{
|
||||
var treeNode = CreateTreeNode(id, parentId, queryStrings, title, icon);
|
||||
treeNode.HasChildren = hasChildren;
|
||||
treeNode.RoutePath = routePath;
|
||||
treeNode.Udi = udi;
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The AdditionalData of a node is always populated with the query string data, this method performs this
|
||||
/// operation and ensures that special values are not inserted or that duplicate keys are not added.
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
/// <param name="queryStrings"></param>
|
||||
protected void AddQueryStringsToAdditionalData(TreeNode node, FormDataCollection queryStrings)
|
||||
{
|
||||
foreach (var q in queryStrings.Where(x => node.AdditionalData.ContainsKey(x.Key) == false))
|
||||
{
|
||||
node.AdditionalData.Add(q.Key, q.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the request is for a dialog mode tree
|
||||
/// </summary>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <returns></returns>
|
||||
protected bool IsDialog(FormDataCollection queryStrings)
|
||||
{
|
||||
return queryStrings.GetValue<bool>(TreeQueryStringParameters.IsDialog);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An event that allows developers to modify the tree node collection that is being rendered
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Developers can add/remove/replace/insert/update/etc... any of the tree items in the collection.
|
||||
/// </remarks>
|
||||
public static event TypedEventHandler<TreeControllerBase, TreeNodesRenderingEventArgs> TreeNodesRendering;
|
||||
|
||||
private static void OnTreeNodesRendering(TreeControllerBase instance, TreeNodesRenderingEventArgs e)
|
||||
{
|
||||
var handler = TreeNodesRendering;
|
||||
if (handler != null) handler(instance, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An event that allows developer to modify the root tree node that is being rendered
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<TreeControllerBase, TreeNodeRenderingEventArgs> RootNodeRendering;
|
||||
|
||||
private static void OnRootNodeRendering(TreeControllerBase instance, TreeNodeRenderingEventArgs e)
|
||||
{
|
||||
var handler = RootNodeRendering;
|
||||
if (handler != null) handler(instance, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An event that allows developers to modify the meun that is being rendered
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Developers can add/remove/replace/insert/update/etc... any of the tree items in the collection.
|
||||
/// </remarks>
|
||||
public static event TypedEventHandler<TreeControllerBase, MenuRenderingEventArgs> MenuRendering;
|
||||
|
||||
private static void OnMenuRendering(TreeControllerBase instance, MenuRenderingEventArgs e)
|
||||
{
|
||||
var handler = MenuRendering;
|
||||
if (handler != null) handler(instance, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
namespace Umbraco.Web.Trees
|
||||
{
|
||||
/// <summary>
|
||||
/// Common query string parameters used for tree query strings
|
||||
/// </summary>
|
||||
internal struct TreeQueryStringParameters
|
||||
{
|
||||
public const string IsDialog = "isDialog";
|
||||
public const string Application = "application";
|
||||
public const string StartNodeId = "startNodeId";
|
||||
public const string IgnoreUserStartNodes = "ignoreUserStartNodes";
|
||||
//public const string OnNodeClick = "OnNodeClick";
|
||||
//public const string RenderParent = "RenderParent";
|
||||
}
|
||||
}
|
||||
namespace Umbraco.Web.Trees
|
||||
{
|
||||
/// <summary>
|
||||
/// Common query string parameters used for tree query strings
|
||||
/// </summary>
|
||||
internal struct TreeQueryStringParameters
|
||||
{
|
||||
public const string IsDialog = "isDialog";
|
||||
public const string Application = "application";
|
||||
public const string StartNodeId = "startNodeId";
|
||||
public const string DataTypeId = "dataTypeId";
|
||||
//public const string OnNodeClick = "OnNodeClick";
|
||||
//public const string RenderParent = "RenderParent";
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user