Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a8d7a1d01d | |||
| e62597521e | |||
| fa91321299 | |||
| 2d81691407 | |||
| 21f08ca491 | |||
| e202f21934 | |||
| 2936ff0bf9 | |||
| 8e4e575276 | |||
| 84752babc8 | |||
| 60a1116acd | |||
| a480d7bbe6 | |||
| 7316c5462a | |||
| 2a9960afb3 | |||
| ed899ec73d | |||
| 8f26f9385d | |||
| a446cc224d | |||
| 07f9a9700d | |||
| 7e7acd0049 | |||
| 57985c26a2 | |||
| 504c1f7254 | |||
| 52ad36a6c2 | |||
| 01670e0832 | |||
| 99c96bce86 | |||
| da2bc6764b | |||
| d11a377f0f | |||
| d445f7cb0d | |||
| 899d325ca1 | |||
| f1107b7a91 | |||
| a3f171e7b3 | |||
| 788a0241d8 | |||
| 25237995eb | |||
| ed75109829 | |||
| 6738a25bfa | |||
| aa9c753455 | |||
| 0e5f9b92e8 | |||
| 77fd4d383b | |||
| 98a03a0127 | |||
| 464130a102 | |||
| dfb324b003 | |||
| 966b8565ba | |||
| 2b774dbdf2 | |||
| cae600ac2f | |||
| 5e4702a4ab | |||
| 8442b2e8e7 | |||
| 64efd0abbc | |||
| b8f3f93d83 | |||
| ce9e851087 | |||
| 53d9a34996 | |||
| 2f79d4a71d | |||
| 98d72da622 | |||
| c563629756 | |||
| acb3ecbbf7 | |||
| 2cbe6f5543 | |||
| 9beaaa825e | |||
| bf90edb5be | |||
| 94a506f8e8 | |||
| 4f68941f98 | |||
| 25de56a98b | |||
| b11135a096 | |||
| d4db32c0f2 | |||
| d54f35f5f7 | |||
| f163381399 | |||
| 86cb3e8695 | |||
| dcc50c3b53 | |||
| 0209b71182 | |||
| 6b92e47631 | |||
| 36ffebbb49 | |||
| d0bafc6184 | |||
| 801828df70 | |||
| 953c371580 | |||
| 83d3882b9a | |||
| c37777b289 | |||
| ef6a4139de | |||
| 98ceabaf7e | |||
| 85bcb7ad2b |
@@ -128,3 +128,4 @@ src/*.boltdata/
|
||||
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.config.js
|
||||
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.front.js
|
||||
src/umbraco.sln.ide/*
|
||||
build/UmbracoCms.*/
|
||||
|
||||
+2
-2
@@ -156,8 +156,8 @@
|
||||
<Target Name="ZipWebApp" DependsOnTargets="ZipUmbracoExaminePDF" >
|
||||
<Message Text="Starting to zip to $(buildDate)-$(BuildZipFileName)" Importance="high" />
|
||||
|
||||
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameBin)%22 %22$(SolutionBinFolderAbsolutePath)*%22" />
|
||||
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileName)%22 %22$(WebAppFolderAbsolutePath)*%22" />
|
||||
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameBin)%22 %22$(SolutionBinFolderAbsolutePath)*%22 -x!dotLess.Core.dll" />
|
||||
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileName)%22 %22$(WebAppFolderAbsolutePath)*%22 -x!dotLess.Core.dll" />
|
||||
|
||||
<Message Text="Finished zipping to build\$(BuildFolder)\$(buildDate)-$(BuildZipFileName)" Importance="high" />
|
||||
</Target>
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
<dependency id="Examine" version="[0.1.57, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[1.9.5, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[3.3.1, 5.0.0)" />
|
||||
<dependency id="dotless" version="[1.4.1, 2.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -26,11 +26,15 @@
|
||||
views/dashboard/developer/developerdashboardvideos.html
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
|
||||
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
</section>
|
||||
|
||||
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)">
|
||||
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
|
||||
<control>
|
||||
views/dashboard/developer/examinemanagement.html
|
||||
</control>
|
||||
</tab>
|
||||
</tab>
|
||||
</section>
|
||||
|
||||
<section alias="StartupMediaDashboardSection" xdt:Locator="Match(alias)">
|
||||
|
||||
@@ -2,24 +2,22 @@ A note about running Umbraco from Visual Studio.
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
BETA Notice: We've done our best to transform your config files, we are testing this in 7.2 beta and would love to
|
||||
hear back if it didn't work so we can improve this feature. We'd love to see your before and after config files
|
||||
(make sure to delete sensitive data like passwords and API keys) in the issue tracker at http://issues.umbraco.org/
|
||||
Remember, we backed up your files in App_Data\NuGetBackup so you can find the original file before it was transformed.
|
||||
|
||||
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
|
||||
file (and config files in the config folder).
|
||||
|
||||
We've overwritten all the files in the Umbraco and Umbraco_Client folder, these have been backed up in
|
||||
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or a package
|
||||
might have added. Only the existing files were overwritten. If you customized anything then make sure to do a compare
|
||||
and merge with the NuGetBackup folder.
|
||||
We've done our best to transform your configuration files but in case something is not quite right: remember we
|
||||
backed up your files in App_Data\NuGetBackup so you can find the original files before they were transformed.
|
||||
|
||||
This nuget package includes build targets that extends the creation of a deploy package, which is generated by
|
||||
We've overwritten all the files in the Umbraco and Umbraco_Client folder, these have been backed up in
|
||||
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or
|
||||
a package might have added. Only the existing files were overwritten. If you customized anything then make
|
||||
sure to do a compare and merge with the NuGetBackup folder.
|
||||
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
|
||||
Publish this won't affect you.
|
||||
These things will now be automatically included when creating a deploy package or publishing to the file system:
|
||||
umbraco, umbraco_client, config\splashes and global.asax.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, umbraco_client, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.org:
|
||||
http://our.umbraco.org/contribute/releases
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.1" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.2.0
|
||||
RC
|
||||
7.2.1
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.2.0");
|
||||
private static readonly Version Version = new Version("7.2.1");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// Gets the version comment (like beta or RC).
|
||||
/// </summary>
|
||||
/// <value>The version comment.</value>
|
||||
public static string CurrentComment { get { return "RC"; } }
|
||||
public static string CurrentComment { get { return ""; } }
|
||||
|
||||
// Get the version of the umbraco.dll by looking at a class in that dll
|
||||
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Helper class for mandating values, for example on method parameters.
|
||||
/// </summary>
|
||||
internal static class Mandate
|
||||
public static class Mandate
|
||||
{
|
||||
/// <summary>
|
||||
/// Mandates that the specified parameter is not null.
|
||||
|
||||
@@ -15,11 +15,11 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
private int _defaultTemplate;
|
||||
private IEnumerable<ITemplate> _allowedTemplates;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constuctor for creating a ContentType with the parent's id.
|
||||
/// </summary>
|
||||
/// <remarks>You usually only want to use this for creating ContentTypes at the root.</remarks>
|
||||
/// <remarks>Only use this for creating ContentTypes at the root (with ParentId -1).</remarks>
|
||||
/// <param name="parentId"></param>
|
||||
public ContentType(int parentId) : base(parentId)
|
||||
{
|
||||
@@ -31,14 +31,26 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
/// <remarks>Use this to ensure inheritance from parent.</remarks>
|
||||
/// <param name="parent"></param>
|
||||
public ContentType(IContentType parent) : base(parent)
|
||||
{
|
||||
_allowedTemplates = new List<ITemplate>();
|
||||
}
|
||||
[Obsolete("This method is obsolete, use ContentType(IContentType parent, string alias) instead.", false)]
|
||||
public ContentType(IContentType parent) : this(parent, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constuctor for creating a ContentType with the parent as an inherited type.
|
||||
/// </summary>
|
||||
/// <remarks>Use this to ensure inheritance from parent.</remarks>
|
||||
/// <param name="parent"></param>
|
||||
/// <param name="alias"></param>
|
||||
public ContentType(IContentType parent, string alias)
|
||||
: base(parent, alias)
|
||||
{
|
||||
_allowedTemplates = new List<ITemplate>();
|
||||
}
|
||||
|
||||
private static readonly PropertyInfo DefaultTemplateSelector = ExpressionHelper.GetPropertyInfo<ContentType, int>(x => x.DefaultTemplateId);
|
||||
private static readonly PropertyInfo AllowedTemplatesSelector = ExpressionHelper.GetPropertyInfo<ContentType, IEnumerable<ITemplate>>(x => x.AllowedTemplates);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the alias of the default Template.
|
||||
/// </summary>
|
||||
@@ -95,7 +107,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
DefaultTemplateId = template.Id;
|
||||
if(_allowedTemplates.Any(x => x != null && x.Id == template.Id) == false)
|
||||
if (_allowedTemplates.Any(x => x != null && x.Id == template.Id) == false)
|
||||
{
|
||||
var templates = AllowedTemplates.ToList();
|
||||
templates.Add(template);
|
||||
@@ -129,7 +141,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
base.AddingEntity();
|
||||
|
||||
if(Key == Guid.Empty)
|
||||
if (Key == Guid.Empty)
|
||||
Key = Guid.NewGuid();
|
||||
}
|
||||
|
||||
@@ -140,7 +152,7 @@ namespace Umbraco.Core.Models
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use DeepCloneWithResetIdentities instead")]
|
||||
public IContentType Clone(string alias)
|
||||
{
|
||||
{
|
||||
return DeepCloneWithResetIdentities(alias);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
@@ -15,6 +16,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
|
||||
public abstract class ContentTypeBase : Entity, IContentTypeBase
|
||||
{
|
||||
private Lazy<int> _parentId;
|
||||
@@ -48,17 +50,22 @@ namespace Umbraco.Core.Models
|
||||
_additionalData = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
protected ContentTypeBase(IContentTypeBase parent)
|
||||
protected ContentTypeBase(IContentTypeBase parent) : this(parent, null)
|
||||
{
|
||||
Mandate.ParameterNotNull(parent, "parent");
|
||||
}
|
||||
|
||||
_parentId = new Lazy<int>(() => parent.Id);
|
||||
_allowedContentTypes = new List<ContentTypeSort>();
|
||||
_propertyGroups = new PropertyGroupCollection();
|
||||
protected ContentTypeBase(IContentTypeBase parent, string alias)
|
||||
{
|
||||
Mandate.ParameterNotNull(parent, "parent");
|
||||
|
||||
_alias = alias;
|
||||
_parentId = new Lazy<int>(() => parent.Id);
|
||||
_allowedContentTypes = new List<ContentTypeSort>();
|
||||
_propertyGroups = new PropertyGroupCollection();
|
||||
_propertyTypes = new PropertyTypeCollection();
|
||||
_propertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
_additionalData = new Dictionary<string, object>();
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Name);
|
||||
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.ParentId);
|
||||
@@ -492,7 +499,6 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="propertyTypeAlias">Alias of the <see cref="PropertyType"/> to remove</param>
|
||||
public void RemovePropertyType(string propertyTypeAlias)
|
||||
{
|
||||
|
||||
//check if the property exist in one of our collections
|
||||
if (PropertyGroups.Any(group => group.PropertyTypes.Any(pt => pt.Alias == propertyTypeAlias))
|
||||
|| _propertyTypes.Any(x => x.Alias == propertyTypeAlias))
|
||||
@@ -519,6 +525,7 @@ namespace Umbraco.Core.Models
|
||||
public void RemovePropertyGroup(string propertyGroupName)
|
||||
{
|
||||
PropertyGroups.RemoveItem(propertyGroupName);
|
||||
OnPropertyChanged(PropertyGroupCollectionSelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -22,11 +22,16 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
protected ContentTypeCompositionBase(IContentTypeComposition parent)
|
||||
: base(parent)
|
||||
: this(parent, null)
|
||||
{
|
||||
AddContentType(parent);
|
||||
}
|
||||
|
||||
protected ContentTypeCompositionBase(IContentTypeComposition parent, string alias)
|
||||
: base(parent, alias)
|
||||
{
|
||||
AddContentType(parent);
|
||||
}
|
||||
|
||||
private static readonly PropertyInfo ContentTypeCompositionSelector =
|
||||
ExpressionHelper.GetPropertyInfo<ContentTypeCompositionBase, IEnumerable<IContentTypeComposition>>(
|
||||
x => x.ContentTypeComposition);
|
||||
@@ -76,6 +81,9 @@ namespace Umbraco.Core.Models
|
||||
if (contentType.ContentTypeComposition.Any(x => x.CompositionAliases().Any(ContentTypeCompositionExists)))
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrEmpty(Alias) == false && Alias.Equals(contentType.Alias))
|
||||
return false;
|
||||
|
||||
if (ContentTypeCompositionExists(contentType.Alias) == false)
|
||||
{
|
||||
//Before we actually go ahead and add the ContentType as a Composition we ensure that we don't
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Constuctor for creating a MediaType with the parent's id.
|
||||
/// </summary>
|
||||
/// <remarks>You usually only want to use this for creating MediaTypes at the root.</remarks>
|
||||
/// <remarks>Only use this for creating MediaTypes at the root (with ParentId -1).</remarks>
|
||||
/// <param name="parentId"></param>
|
||||
public MediaType(int parentId) : base(parentId)
|
||||
{
|
||||
@@ -24,10 +24,21 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
/// <remarks>Use this to ensure inheritance from parent.</remarks>
|
||||
/// <param name="parent"></param>
|
||||
public MediaType(IMediaType parent) : base(parent)
|
||||
public MediaType(IMediaType parent) : this(parent, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constuctor for creating a MediaType with the parent as an inherited type.
|
||||
/// </summary>
|
||||
/// <remarks>Use this to ensure inheritance from parent.</remarks>
|
||||
/// <param name="parent"></param>
|
||||
/// <param name="alias"></param>
|
||||
public MediaType(IMediaType parent, string alias)
|
||||
: base(parent, alias)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method to call when Entity is being saved
|
||||
/// </summary>
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace Umbraco.Core.Models
|
||||
private string _email;
|
||||
private string _rawPasswordValue;
|
||||
private object _providerUserKey;
|
||||
private Type _userTypeKey;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for creating an empty Member object
|
||||
@@ -114,7 +113,6 @@ namespace Umbraco.Core.Models
|
||||
private static readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Email);
|
||||
private static readonly PropertyInfo PasswordSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.RawPasswordValue);
|
||||
private static readonly PropertyInfo ProviderUserKeySelector = ExpressionHelper.GetPropertyInfo<Member, object>(x => x.ProviderUserKey);
|
||||
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<Member, Type>(x => x.ProviderUserKeyType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Username
|
||||
@@ -502,38 +500,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of the provider user key.
|
||||
/// </value>
|
||||
[IgnoreDataMember]
|
||||
internal Type ProviderUserKeyType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _userTypeKey;
|
||||
}
|
||||
private set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_userTypeKey = value;
|
||||
return _userTypeKey;
|
||||
}, _userTypeKey, UserTypeKeySelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
internal void SetProviderUserKeyType(Type type)
|
||||
{
|
||||
ProviderUserKeyType = type;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Method to call when Entity is being saved
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
@@ -21,7 +20,12 @@ namespace Umbraco.Core.Models
|
||||
MemberTypePropertyTypes = new Dictionary<string, MemberTypePropertyProfileAccess>();
|
||||
}
|
||||
|
||||
public MemberType(IContentTypeComposition parent) : base(parent)
|
||||
public MemberType(IContentTypeComposition parent) : this(parent, null)
|
||||
{
|
||||
}
|
||||
|
||||
public MemberType(IContentTypeComposition parent, string alias)
|
||||
: base(parent, alias)
|
||||
{
|
||||
MemberTypePropertyTypes = new Dictionary<string, MemberTypePropertyProfileAccess>();
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
internal static class MembershipUserExtensions
|
||||
{
|
||||
internal static UmbracoMembershipMember AsConcreteMembershipUser(this IMembershipUser member, string providerName)
|
||||
internal static UmbracoMembershipMember AsConcreteMembershipUser(this IMembershipUser member, string providerName, bool providerKeyAsGuid = false)
|
||||
{
|
||||
var membershipMember = new UmbracoMembershipMember(member, providerName);
|
||||
var membershipMember = new UmbracoMembershipMember(member, providerName, providerKeyAsGuid);
|
||||
return membershipMember;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Web.Security;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
@@ -25,7 +26,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
//NOTE: We are not calling the base constructor which will validate that a provider with the specified name exists which causes issues with unit tests. The ctor
|
||||
// validation for that doesn't need to be there anyways (have checked the source).
|
||||
public UmbracoMembershipMember(IMembershipUser member, string providerName)
|
||||
public UmbracoMembershipMember(IMembershipUser member, string providerName, bool providerKeyAsGuid = false)
|
||||
{
|
||||
_member = member;
|
||||
//NOTE: We are copying the values here so that everything is consistent with how the underlying built-in ASP.Net membership user
|
||||
@@ -37,7 +38,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
if (member.PasswordQuestion != null)
|
||||
_passwordQuestion = member.PasswordQuestion.Trim();
|
||||
_providerName = providerName;
|
||||
_providerUserKey = member.ProviderUserKey;
|
||||
_providerUserKey = providerKeyAsGuid ? member.ProviderUserKey : member.Id;
|
||||
_comment = member.Comments;
|
||||
_isApproved = member.IsApproved;
|
||||
_isLockedOut = member.IsLockedOut;
|
||||
|
||||
@@ -58,7 +58,6 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
private IUserType _userType;
|
||||
private string _name;
|
||||
private Type _userTypeKey;
|
||||
private List<string> _addedSections;
|
||||
private List<string> _removedSections;
|
||||
private ObservableCollection<string> _sectionCollection;
|
||||
@@ -80,7 +79,6 @@ namespace Umbraco.Core.Models.Membership
|
||||
private static readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartMediaId);
|
||||
private static readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<string>>(x => x.AllowedSections);
|
||||
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Name);
|
||||
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<User, Type>(x => x.ProviderUserKeyType);
|
||||
|
||||
private static readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Username);
|
||||
private static readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Email);
|
||||
@@ -101,37 +99,6 @@ namespace Umbraco.Core.Models.Membership
|
||||
set { throw new NotSupportedException("Cannot set the provider user key for a user"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of the provider user key.
|
||||
/// </value>
|
||||
[IgnoreDataMember]
|
||||
internal Type ProviderUserKeyType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _userTypeKey;
|
||||
}
|
||||
private set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_userTypeKey = value;
|
||||
return _userTypeKey;
|
||||
}, _userTypeKey, UserTypeKeySelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
internal void SetProviderUserKeyType(Type type)
|
||||
{
|
||||
ProviderUserKeyType = type;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public string Username
|
||||
|
||||
@@ -71,16 +71,34 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
using (new WriteLock(_addLocker))
|
||||
{
|
||||
var key = GetKeyForItem(item);
|
||||
if (key != null)
|
||||
//Note this is done to ensure existig groups can be renamed
|
||||
if (item.HasIdentity && item.Id > 0)
|
||||
{
|
||||
var exists = this.Contains(key);
|
||||
var exists = this.Contains(item.Id);
|
||||
if (exists)
|
||||
{
|
||||
SetItem(IndexOfKey(key), item);
|
||||
var keyExists = this.Contains(item.Name);
|
||||
if(keyExists)
|
||||
throw new Exception(string.Format("Naming conflict: Changing the name of PropertyGroup '{0}' would result in duplicates", item.Name));
|
||||
|
||||
SetItem(IndexOfKey(item.Id), item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var key = GetKeyForItem(item);
|
||||
if (key != null)
|
||||
{
|
||||
var exists = this.Contains(key);
|
||||
if (exists)
|
||||
{
|
||||
SetItem(IndexOfKey(key), item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.Add(item);
|
||||
OnAdd.IfNotNull(x => x.Invoke());//Could this not be replaced by a Mandate/Contract for ensuring item is not null
|
||||
|
||||
@@ -99,6 +117,11 @@ namespace Umbraco.Core.Models
|
||||
return this.Any(x => x.Name == groupName);
|
||||
}
|
||||
|
||||
public bool Contains(int id)
|
||||
{
|
||||
return this.Any(x => x.Id == id);
|
||||
}
|
||||
|
||||
public void RemoveItem(string propertyGroupName)
|
||||
{
|
||||
var key = IndexOfKey(propertyGroupName);
|
||||
@@ -119,6 +142,18 @@ namespace Umbraco.Core.Models
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int IndexOfKey(int id)
|
||||
{
|
||||
for (var i = 0; i < this.Count; i++)
|
||||
{
|
||||
if (this[i].Id == id)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected override string GetKeyForItem(PropertyGroup item)
|
||||
{
|
||||
return item.Name;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
[DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")]
|
||||
public class PropertyType : Entity, IEquatable<PropertyType>
|
||||
{
|
||||
private readonly bool _isExplicitDbType;
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero
|
||||
//make sure it doesn't already exist
|
||||
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID")) == false)
|
||||
{
|
||||
Create.Index("IX_umbracoNodeUniqueID").OnTable("umbracoNode").OnColumn("uniqueID").Unique();
|
||||
Create.Index("IX_umbracoNodeUniqueID").OnTable("umbracoNode").OnColumn("uniqueID").Ascending().WithOptions().NonClustered();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-3
@@ -1,3 +1,5 @@
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
@@ -11,9 +13,20 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero
|
||||
{
|
||||
public override void Up()
|
||||
{
|
||||
//To text
|
||||
var textType = SqlSyntaxContext.SqlSyntaxProvider.GetSpecialDbType(SpecialDbTypes.NTEXT);
|
||||
Alter.Table("cmsDataTypePreValues").AlterColumn("value").AsCustom(textType).Nullable();
|
||||
var columns = SqlSyntaxContext.SqlSyntaxProvider.GetColumnsInSchema(Context.Database).Distinct().ToArray();
|
||||
|
||||
//Check if it's already text
|
||||
if (columns.Any(x => x.ColumnName.InvariantEquals("value") && x.TableName.InvariantEquals("cmsDataTypePreValues")
|
||||
//mysql check
|
||||
&& (x.DataType.InvariantEquals("longtext") == false
|
||||
//sql server check
|
||||
&& x.DataType.InvariantEquals("ntext") == false)))
|
||||
{
|
||||
//To text
|
||||
var textType = SqlSyntaxContext.SqlSyntaxProvider.GetSpecialDbType(SpecialDbTypes.NTEXT);
|
||||
Alter.Table("cmsDataTypePreValues").AlterColumn("value").AsCustom(textType).Nullable();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
|
||||
@@ -850,7 +850,7 @@ namespace Umbraco.Core.Persistence
|
||||
public IEnumerable<T1> Query<T1, T2, T3, T4>(Sql sql) { return Query<T1>(new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, null, sql.SQL, sql.Arguments); }
|
||||
|
||||
// Automagically guess the property relationships between various POCOs and create a delegate that will set them up
|
||||
object GetAutoMapper(Type[] types)
|
||||
Delegate GetAutoMapper(Type[] types)
|
||||
{
|
||||
// Build a key
|
||||
var kb = new StringBuilder();
|
||||
@@ -865,7 +865,7 @@ namespace Umbraco.Core.Persistence
|
||||
RWLock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
object mapper;
|
||||
Delegate mapper;
|
||||
if (AutoMappers.TryGetValue(key, out mapper))
|
||||
return mapper;
|
||||
}
|
||||
@@ -879,7 +879,7 @@ namespace Umbraco.Core.Persistence
|
||||
try
|
||||
{
|
||||
// Try again
|
||||
object mapper;
|
||||
Delegate mapper;
|
||||
if (AutoMappers.TryGetValue(key, out mapper))
|
||||
return mapper;
|
||||
|
||||
@@ -952,22 +952,53 @@ namespace Umbraco.Core.Persistence
|
||||
throw new InvalidOperationException(string.Format("Couldn't find split point between {0} and {1}", typeThis, typeNext));
|
||||
}
|
||||
|
||||
|
||||
// Instance data used by the Multipoco factory delegate - essentially a list of the nested poco factories to call
|
||||
public class MultiPocoFactory
|
||||
{
|
||||
public List<Delegate> m_Delegates;
|
||||
public Delegate GetItem(int index) { return m_Delegates[index]; }
|
||||
|
||||
public MultiPocoFactory(IEnumerable<Delegate> dels)
|
||||
{
|
||||
Delegates = new List<Delegate>(dels);
|
||||
}
|
||||
private List<Delegate> Delegates { get; set; }
|
||||
private Delegate GetItem(int index) { return Delegates[index]; }
|
||||
|
||||
/// <summary>
|
||||
/// Calls the delegate at the specified index and returns its values
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="reader"></param>
|
||||
/// <returns></returns>
|
||||
private object CallDelegate(int index, IDataReader reader)
|
||||
{
|
||||
var d = GetItem(index);
|
||||
var output = d.DynamicInvoke(reader);
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls the callback delegate and passes in the output of all delegates as the parameters
|
||||
/// </summary>
|
||||
/// <typeparam name="TRet"></typeparam>
|
||||
/// <param name="callback"></param>
|
||||
/// <param name="dr"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
public TRet CallCallback<TRet>(Delegate callback, IDataReader dr, int count)
|
||||
{
|
||||
var args = new List<object>();
|
||||
for(var i = 0;i<count;i++)
|
||||
{
|
||||
args.Add(CallDelegate(i, dr));
|
||||
}
|
||||
return (TRet)callback.DynamicInvoke(args.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
// Create a multi-poco factory
|
||||
Func<IDataReader, object, TRet> CreateMultiPocoFactory<TRet>(Type[] types, string sql, IDataReader r)
|
||||
{
|
||||
var m = new DynamicMethod("petapoco_multipoco_factory", typeof(TRet), new Type[] { typeof(MultiPocoFactory), typeof(IDataReader), typeof(object) }, typeof(MultiPocoFactory));
|
||||
var il = m.GetILGenerator();
|
||||
|
||||
// Load the callback
|
||||
il.Emit(OpCodes.Ldarg_2);
|
||||
|
||||
Func<IDataReader, Delegate, TRet> CreateMultiPocoFactory<TRet>(Type[] types, string sql, IDataReader r)
|
||||
{
|
||||
// Call each delegate
|
||||
var dels = new List<Delegate>();
|
||||
int pos = 0;
|
||||
@@ -976,33 +1007,19 @@ namespace Umbraco.Core.Persistence
|
||||
// Add to list of delegates to call
|
||||
var del = FindSplitPoint(types[i], i + 1 < types.Length ? types[i + 1] : null, sql, r, ref pos);
|
||||
dels.Add(del);
|
||||
|
||||
// Get the delegate
|
||||
il.Emit(OpCodes.Ldarg_0); // callback,this
|
||||
il.Emit(OpCodes.Ldc_I4, i); // callback,this,Index
|
||||
il.Emit(OpCodes.Callvirt, typeof(MultiPocoFactory).GetMethod("GetItem")); // callback,Delegate
|
||||
il.Emit(OpCodes.Ldarg_1); // callback,delegate, datareader
|
||||
|
||||
// Call Invoke
|
||||
var tDelInvoke = del.GetType().GetMethod("Invoke");
|
||||
il.Emit(OpCodes.Callvirt, tDelInvoke); // Poco left on stack
|
||||
}
|
||||
|
||||
// By now we should have the callback and the N pocos all on the stack. Call the callback and we're done
|
||||
il.Emit(OpCodes.Callvirt, Expression.GetFuncType(types.Concat(new Type[] { typeof(TRet) }).ToArray()).GetMethod("Invoke"));
|
||||
il.Emit(OpCodes.Ret);
|
||||
|
||||
// Finish up
|
||||
return (Func<IDataReader, object, TRet>)m.CreateDelegate(typeof(Func<IDataReader, object, TRet>), new MultiPocoFactory() { m_Delegates = dels });
|
||||
var mpFactory = new MultiPocoFactory(dels);
|
||||
return (reader, arg3) => mpFactory.CallCallback<TRet>(arg3, reader, types.Length);
|
||||
}
|
||||
|
||||
// Various cached stuff
|
||||
static Dictionary<string, object> MultiPocoFactories = new Dictionary<string, object>();
|
||||
static Dictionary<string, object> AutoMappers = new Dictionary<string, object>();
|
||||
static Dictionary<string, Delegate> AutoMappers = new Dictionary<string, Delegate>();
|
||||
static System.Threading.ReaderWriterLockSlim RWLock = new System.Threading.ReaderWriterLockSlim();
|
||||
|
||||
// Get (or create) the multi-poco factory for a query
|
||||
Func<IDataReader, object, TRet> GetMultiPocoFactory<TRet>(Type[] types, string sql, IDataReader r)
|
||||
// Get (or create) the multi-poco factory for a query
|
||||
Func<IDataReader, Delegate, TRet> GetMultiPocoFactory<TRet>(Type[] types, string sql, IDataReader r)
|
||||
{
|
||||
// Build a key string (this is crap, should address this at some point)
|
||||
var kb = new StringBuilder();
|
||||
@@ -1024,7 +1041,10 @@ namespace Umbraco.Core.Persistence
|
||||
{
|
||||
object oFactory;
|
||||
if (MultiPocoFactories.TryGetValue(key, out oFactory))
|
||||
return (Func<IDataReader, object, TRet>)oFactory;
|
||||
{
|
||||
//mpFactory = oFactory;
|
||||
return (Func<IDataReader, Delegate, TRet>)oFactory;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -1036,15 +1056,17 @@ namespace Umbraco.Core.Persistence
|
||||
try
|
||||
{
|
||||
// Check again
|
||||
object oFactory;
|
||||
object oFactory; ;
|
||||
if (MultiPocoFactories.TryGetValue(key, out oFactory))
|
||||
return (Func<IDataReader, object, TRet>)oFactory;
|
||||
{
|
||||
return (Func<IDataReader, Delegate, TRet>)oFactory;
|
||||
}
|
||||
|
||||
// Create the factory
|
||||
var factory = CreateMultiPocoFactory<TRet>(types, sql, r);
|
||||
|
||||
// Create the factory
|
||||
var Factory = CreateMultiPocoFactory<TRet>(types, sql, r);
|
||||
|
||||
MultiPocoFactories.Add(key, Factory);
|
||||
return Factory;
|
||||
MultiPocoFactories.Add(key, factory);
|
||||
return factory;
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -1054,7 +1076,7 @@ namespace Umbraco.Core.Persistence
|
||||
}
|
||||
|
||||
// Actual implementation of the multi-poco query
|
||||
public IEnumerable<TRet> Query<TRet>(Type[] types, object cb, string sql, params object[] args)
|
||||
public IEnumerable<TRet> Query<TRet>(Type[] types, Delegate cb, string sql, params object[] args)
|
||||
{
|
||||
OpenSharedConnection();
|
||||
try
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -297,9 +298,38 @@ AND umbracoNode.id <> @id",
|
||||
//Delete Tabs/Groups by excepting entries from db with entries from collections
|
||||
var dbPropertyGroups =
|
||||
Database.Fetch<PropertyTypeGroupDto>("WHERE contenttypeNodeId = @Id", new {Id = entity.Id})
|
||||
.Select(x => new Tuple<int, string>(x.Id, x.Text));
|
||||
var entityPropertyGroups = entity.PropertyGroups.Select(x => new Tuple<int, string>(x.Id, x.Name));
|
||||
var tabs = dbPropertyGroups.Except(entityPropertyGroups);
|
||||
.Select(x => new Tuple<int, string>(x.Id, x.Text))
|
||||
.ToList();
|
||||
var entityPropertyGroups = entity.PropertyGroups.Select(x => new Tuple<int, string>(x.Id, x.Name)).ToList();
|
||||
var tabsToDelete = dbPropertyGroups.Select(x => x.Item1).Except(entityPropertyGroups.Select(x => x.Item1));
|
||||
var tabs = dbPropertyGroups.Where(x => tabsToDelete.Any(y => y == x.Item1));
|
||||
//Update Tab name downstream to ensure renaming is done properly
|
||||
foreach (var propertyGroup in entityPropertyGroups)
|
||||
{
|
||||
Database.Update<PropertyTypeGroupDto>("SET Text = @TabName WHERE parentGroupId = @TabId",
|
||||
new { TabName = propertyGroup.Item2, TabId = propertyGroup.Item1 });
|
||||
|
||||
var childGroups = Database.Fetch<PropertyTypeGroupDto>("WHERE parentGroupId = @TabId", new { TabId = propertyGroup.Item1 });
|
||||
foreach (var childGroup in childGroups)
|
||||
{
|
||||
var sibling = Database.Fetch<PropertyTypeGroupDto>("WHERE contenttypeNodeId = @Id AND text = @Name",
|
||||
new { Id = childGroup.ContentTypeNodeId, Name = propertyGroup.Item2 })
|
||||
.FirstOrDefault(x => x.ParentGroupId.HasValue == false || x.ParentGroupId.Value.Equals(propertyGroup.Item1) == false);
|
||||
//If the child group doesn't have a sibling there is no chance of duplicates and we continue
|
||||
if (sibling == null || (sibling.ParentGroupId.HasValue && sibling.ParentGroupId.Value.Equals(propertyGroup.Item1))) continue;
|
||||
|
||||
//Since the child group has a sibling with the same name we need to point any PropertyTypes to the sibling
|
||||
//as this child group is about to leave the party.
|
||||
Database.Update<PropertyTypeDto>(
|
||||
"SET propertyTypeGroupId = @PropertyTypeGroupId WHERE propertyTypeGroupId = @PropertyGroupId AND ContentTypeId = @ContentTypeId",
|
||||
new { PropertyTypeGroupId = sibling.Id, PropertyGroupId = childGroup.Id, ContentTypeId = childGroup.ContentTypeNodeId });
|
||||
|
||||
//Since the parent group has been renamed and we have duplicates we remove this group
|
||||
//and leave our sibling in charge of the part.
|
||||
Database.Delete(childGroup);
|
||||
}
|
||||
}
|
||||
//Do Tab updates
|
||||
foreach (var tab in tabs)
|
||||
{
|
||||
Database.Update<PropertyTypeDto>("SET propertyTypeGroupId = NULL WHERE propertyTypeGroupId = @PropertyGroupId",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
@@ -8,11 +9,13 @@ using System.Threading;
|
||||
using Umbraco.Core.Auditing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -273,6 +276,74 @@ namespace Umbraco.Core.Services
|
||||
|
||||
}
|
||||
|
||||
public void Validate(IContentTypeComposition compo)
|
||||
{
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
ValidateLocked(compo);
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateLocked(IContentTypeComposition compositionContentType)
|
||||
{
|
||||
// performs business-level validation of the composition
|
||||
// should ensure that it is absolutely safe to save the composition
|
||||
|
||||
// eg maybe a property has been added, with an alias that's OK (no conflict with ancestors)
|
||||
// but that cannot be used (conflict with descendants)
|
||||
|
||||
var contentType = compositionContentType as IContentType;
|
||||
var mediaType = compositionContentType as IMediaType;
|
||||
|
||||
IContentTypeComposition[] allContentTypes;
|
||||
if (contentType != null)
|
||||
allContentTypes = GetAllContentTypes().Cast<IContentTypeComposition>().ToArray();
|
||||
else if (mediaType != null)
|
||||
allContentTypes = GetAllMediaTypes().Cast<IContentTypeComposition>().ToArray();
|
||||
else
|
||||
throw new Exception("Composition is neither IContentType nor IMediaType?");
|
||||
|
||||
var compositionAliases = compositionContentType.CompositionAliases();
|
||||
var compositions = allContentTypes.Where(x => compositionAliases.Any(y => x.Alias.Equals(y)));
|
||||
var propertyTypeAliases = compositionContentType.PropertyTypes.Select(x => x.Alias.ToLowerInvariant()).ToArray();
|
||||
var indirectReferences = allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == compositionContentType.Id));
|
||||
var comparer = new DelegateEqualityComparer<IContentTypeComposition>((x, y) => x.Id == y.Id, x => x.Id);
|
||||
var dependencies = new HashSet<IContentTypeComposition>(compositions, comparer);
|
||||
var stack = new Stack<IContentTypeComposition>();
|
||||
indirectReferences.ForEach(stack.Push);//Push indirect references to a stack, so we can add recursively
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var indirectReference = stack.Pop();
|
||||
dependencies.Add(indirectReference);
|
||||
//Get all compositions for the current indirect reference
|
||||
var directReferences = indirectReference.ContentTypeComposition;
|
||||
|
||||
foreach (var directReference in directReferences)
|
||||
{
|
||||
if (directReference.Id == compositionContentType.Id || directReference.Alias.Equals(compositionContentType.Alias)) continue;
|
||||
dependencies.Add(directReference);
|
||||
//A direct reference has compositions of its own - these also need to be taken into account
|
||||
var directReferenceGraph = directReference.CompositionAliases();
|
||||
allContentTypes.Where(x => directReferenceGraph.Any(y => x.Alias.Equals(y, StringComparison.InvariantCultureIgnoreCase))).ForEach(c => dependencies.Add(c));
|
||||
}
|
||||
//Recursive lookup of indirect references
|
||||
allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == indirectReference.Id)).ForEach(stack.Push);
|
||||
}
|
||||
|
||||
foreach (var dependency in dependencies)
|
||||
{
|
||||
if (dependency.Id == compositionContentType.Id) continue;
|
||||
var contentTypeDependency = allContentTypes.FirstOrDefault(x => x.Alias.Equals(dependency.Alias, StringComparison.InvariantCultureIgnoreCase));
|
||||
if (contentTypeDependency == null) continue;
|
||||
var intersect = contentTypeDependency.PropertyTypes.Select(x => x.Alias.ToLowerInvariant()).Intersect(propertyTypeAliases).ToArray();
|
||||
if (intersect.Length == 0) continue;
|
||||
|
||||
var message = string.Format("The following PropertyType aliases from the current ContentType conflict with existing PropertyType aliases: {0}.",
|
||||
string.Join(", ", intersect));
|
||||
throw new Exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a single <see cref="IContentType"/> object
|
||||
/// </summary>
|
||||
@@ -288,6 +359,7 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
|
||||
{
|
||||
ValidateLocked(contentType); // throws if invalid
|
||||
contentType.CreatorId = userId;
|
||||
repository.AddOrUpdate(contentType);
|
||||
|
||||
@@ -317,6 +389,11 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
|
||||
{
|
||||
// all-or-nothing, validate them all first
|
||||
foreach (var contentType in asArray)
|
||||
{
|
||||
ValidateLocked(contentType); // throws if invalid
|
||||
}
|
||||
foreach (var contentType in asArray)
|
||||
{
|
||||
contentType.CreatorId = userId;
|
||||
@@ -487,6 +564,7 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
ValidateLocked(mediaType); // throws if invalid
|
||||
mediaType.CreatorId = userId;
|
||||
repository.AddOrUpdate(mediaType);
|
||||
uow.Commit();
|
||||
@@ -517,7 +595,11 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
|
||||
// all-or-nothing, validate them all first
|
||||
foreach (var mediaType in asArray)
|
||||
{
|
||||
ValidateLocked(mediaType); // throws if invalid
|
||||
}
|
||||
foreach (var mediaType in asArray)
|
||||
{
|
||||
mediaType.CreatorId = userId;
|
||||
|
||||
@@ -200,8 +200,22 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="userId">Id of the user issueing the save</param>
|
||||
public void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId = 0)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions), this))
|
||||
return;
|
||||
Save(dataTypeDefinitions, userId, true);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public void Save(IEnumerable<IDataTypeDefinition> dataTypeDefinitions, int userId, bool raiseEvents)
|
||||
{
|
||||
if (raiseEvents)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions), this))
|
||||
return;
|
||||
}
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow))
|
||||
@@ -213,7 +227,8 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
uow.Commit();
|
||||
|
||||
Saved.RaiseEvent(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions, false), this);
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinitions, false), this);
|
||||
}
|
||||
|
||||
Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId, -1);
|
||||
|
||||
@@ -52,6 +52,14 @@ namespace Umbraco.Core.Services
|
||||
/// <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>
|
||||
|
||||
@@ -336,48 +336,56 @@ namespace Umbraco.Core.Services
|
||||
? (from doc in element.Elements("DocumentType") select doc).ToList()
|
||||
: new List<XElement> { element };
|
||||
|
||||
//NOTE Here we sort the doctype XElements based on dependencies
|
||||
//before creating the doc types - this should also allow for a better structure/inheritance support.
|
||||
//When you are importing a single doc type we have to assume that the depedencies are already there.
|
||||
//Otherwise something like uSync won't work.
|
||||
var fields = new List<TopologicalSorter.DependencyField<XElement>>();
|
||||
foreach (var documentType in unsortedDocumentTypes)
|
||||
var isSingleDocTypeImport = unsortedDocumentTypes.Count == 1;
|
||||
if (isSingleDocTypeImport == false)
|
||||
{
|
||||
var elementCopy = documentType;
|
||||
var infoElement = elementCopy.Element("Info");
|
||||
var dependencies = new List<string>();
|
||||
|
||||
//Add the Master as a dependency
|
||||
if (elementCopy.Element("Master") != null &&
|
||||
string.IsNullOrEmpty(elementCopy.Element("Master").Value) == false)
|
||||
//NOTE Here we sort the doctype XElements based on dependencies
|
||||
//before creating the doc types - this should also allow for a better structure/inheritance support.
|
||||
foreach (var documentType in unsortedDocumentTypes)
|
||||
{
|
||||
dependencies.Add(elementCopy.Element("Master").Value);
|
||||
}
|
||||
var elementCopy = documentType;
|
||||
var infoElement = elementCopy.Element("Info");
|
||||
var dependencies = new List<string>();
|
||||
|
||||
//Add compositions as dependencies
|
||||
var compositionsElement = infoElement.Element("Compositions");
|
||||
if (compositionsElement != null && compositionsElement.HasElements)
|
||||
{
|
||||
var compositions = compositionsElement.Elements("Composition");
|
||||
if (compositions.Any())
|
||||
//Add the Master as a dependency
|
||||
if (elementCopy.Element("Master") != null &&
|
||||
string.IsNullOrEmpty(elementCopy.Element("Master").Value) == false)
|
||||
{
|
||||
foreach (var composition in compositions)
|
||||
dependencies.Add(elementCopy.Element("Master").Value);
|
||||
}
|
||||
|
||||
//Add compositions as dependencies
|
||||
var compositionsElement = infoElement.Element("Compositions");
|
||||
if (compositionsElement != null && compositionsElement.HasElements)
|
||||
{
|
||||
var compositions = compositionsElement.Elements("Composition");
|
||||
if (compositions.Any())
|
||||
{
|
||||
dependencies.Add(composition.Value);
|
||||
foreach (var composition in compositions)
|
||||
{
|
||||
dependencies.Add(composition.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var field = new TopologicalSorter.DependencyField<XElement>
|
||||
{
|
||||
Alias = infoElement.Element("Alias").Value,
|
||||
Item = new Lazy<XElement>(() => elementCopy),
|
||||
DependsOn = dependencies.ToArray()
|
||||
};
|
||||
|
||||
fields.Add(field);
|
||||
var field = new TopologicalSorter.DependencyField<XElement>
|
||||
{
|
||||
Alias = infoElement.Element("Alias").Value,
|
||||
Item = new Lazy<XElement>(() => elementCopy),
|
||||
DependsOn = dependencies.ToArray()
|
||||
};
|
||||
|
||||
fields.Add(field);
|
||||
}
|
||||
}
|
||||
|
||||
//Sorting the Document Types based on dependencies
|
||||
var documentTypes = TopologicalSorter.GetSortedItems(fields).ToList();
|
||||
//Sorting the Document Types based on dependencies - if its not a single doc type import ref. #U4-5921
|
||||
var documentTypes = isSingleDocTypeImport
|
||||
? unsortedDocumentTypes.ToList()
|
||||
: TopologicalSorter.GetSortedItems(fields).ToList();
|
||||
|
||||
//Iterate the sorted document types and create them as IContentType objects
|
||||
foreach (var documentType in documentTypes)
|
||||
@@ -438,15 +446,10 @@ namespace Umbraco.Core.Services
|
||||
: _contentTypeService.GetContentType(masterAlias);
|
||||
}
|
||||
|
||||
var alias = infoElement.Element("Alias").Value;
|
||||
var contentType = parent == null
|
||||
? new ContentType(-1)
|
||||
{
|
||||
Alias = infoElement.Element("Alias").Value
|
||||
}
|
||||
: new ContentType(parent)
|
||||
{
|
||||
Alias = infoElement.Element("Alias").Value
|
||||
};
|
||||
? new ContentType(-1) { Alias = alias }
|
||||
: new ContentType(parent, alias);
|
||||
|
||||
if (parent != null)
|
||||
contentType.AddContentType(parent);
|
||||
@@ -843,9 +846,15 @@ namespace Umbraco.Core.Services
|
||||
var list = dataTypes.Select(x => x.Value).ToList();
|
||||
if (list.Any())
|
||||
{
|
||||
_dataTypeService.Save(list, userId);
|
||||
//NOTE: As long as we have to deal with the two types of PreValue lists (with/without Keys)
|
||||
//this is a bit of a pain to handle while ensuring that the imported DataTypes has PreValues
|
||||
//place when triggering the save event.
|
||||
|
||||
SavePrevaluesFromXml(list, dataTypeElements);
|
||||
_dataTypeService.Save(list, userId, false);//Save without raising events
|
||||
|
||||
SavePrevaluesFromXml(list, dataTypeElements);//Save the PreValues for the current list of DataTypes
|
||||
|
||||
_dataTypeService.Save(list, userId, true);//Re-save and raise events
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
|
||||
@@ -74,7 +74,8 @@ namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
var contentTypeService = ctx.Application.Services.ContentTypeService;
|
||||
var baseType = new ContentType(-1) {Alias = "base", Name = "Base"};
|
||||
var inheritedType = new ContentType(baseType) {Alias = "inherited", Name = "Inherited"};
|
||||
const string contentTypeAlias = "inherited";
|
||||
var inheritedType = new ContentType(baseType, contentTypeAlias) {Alias = contentTypeAlias, Name = "Inherited"};
|
||||
contentTypeService.Save(baseType);
|
||||
contentTypeService.Save(inheritedType);
|
||||
createContentTypes = false;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Runtime.Remoting;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -5,6 +6,8 @@ using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Tests.CodeFirst.TestModels.Composition;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
@@ -178,10 +181,11 @@ namespace Umbraco.Tests.Services
|
||||
/*,"Navigation"*/);
|
||||
cts.Save(ctBase);
|
||||
|
||||
var ctHomePage = new ContentType(ctBase)
|
||||
const string contentTypeAlias = "HomePage";
|
||||
var ctHomePage = new ContentType(ctBase, contentTypeAlias)
|
||||
{
|
||||
Name = "Home Page",
|
||||
Alias = "HomePage",
|
||||
Alias = contentTypeAlias,
|
||||
Icon = "settingDomain.gif",
|
||||
Thumbnail = "folder.png",
|
||||
AllowedAsRoot = true
|
||||
@@ -191,7 +195,7 @@ namespace Umbraco.Tests.Services
|
||||
cts.Save(ctHomePage);
|
||||
|
||||
// Act
|
||||
var homeDoc = cs.CreateContent("Home Page", -1, "HomePage");
|
||||
var homeDoc = cs.CreateContent("Home Page", -1, contentTypeAlias);
|
||||
cs.SaveAndPublishWithStatus(homeDoc);
|
||||
|
||||
// Assert
|
||||
@@ -243,13 +247,13 @@ namespace Umbraco.Tests.Services
|
||||
var global = MockedContentTypes.CreateSimpleContentType("global", "Global");
|
||||
service.Save(global);
|
||||
|
||||
var components = MockedContentTypes.CreateSimpleContentType("components", "Components", global);
|
||||
var components = MockedContentTypes.CreateSimpleContentType("components", "Components", global, true);
|
||||
service.Save(components);
|
||||
|
||||
var component = MockedContentTypes.CreateSimpleContentType("component", "Component", components);
|
||||
var component = MockedContentTypes.CreateSimpleContentType("component", "Component", components, true);
|
||||
service.Save(component);
|
||||
|
||||
var category = MockedContentTypes.CreateSimpleContentType("category", "Category", global);
|
||||
var category = MockedContentTypes.CreateSimpleContentType("category", "Category", global, true);
|
||||
service.Save(category);
|
||||
|
||||
var success = category.AddContentType(component);
|
||||
@@ -464,6 +468,766 @@ namespace Umbraco.Tests.Services
|
||||
Assert.AreNotEqual(clonedContentType.PropertyGroups.First(x => x.Name.StartsWith("Content")).Id, originalContentType.PropertyGroups.First(x => x.Name.StartsWith("Content")).Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Add_Duplicate_PropertyType_Alias_To_Referenced_Composition()
|
||||
{
|
||||
//Related the second issue in screencast from this post http://issues.umbraco.org/issue/U4-5986
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
|
||||
var parent = MockedContentTypes.CreateSimpleContentType();
|
||||
service.Save(parent);
|
||||
var child = MockedContentTypes.CreateSimpleContentType("simpleChildPage", "Simple Child Page", parent, true);
|
||||
service.Save(child);
|
||||
var composition = MockedContentTypes.CreateMetaContentType();
|
||||
service.Save(composition);
|
||||
|
||||
//Adding Meta-composition to child doc type
|
||||
child.AddContentType(composition);
|
||||
service.Save(child);
|
||||
|
||||
// Act
|
||||
var duplicatePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var added = composition.AddPropertyType(duplicatePropertyType, "Meta");
|
||||
|
||||
// Assert
|
||||
Assert.That(added, Is.True);
|
||||
Assert.Throws<Exception>(() => service.Save(composition));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("simpleChildPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Add_Duplicate_PropertyType_Alias_In_Composition_Graph()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
|
||||
var basePage = MockedContentTypes.CreateSimpleContentType("basePage", "Base Page", null, true);
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true);
|
||||
service.Save(advancedPage);
|
||||
|
||||
var metaComposition = MockedContentTypes.CreateMetaContentType();
|
||||
service.Save(metaComposition);
|
||||
var seoComposition = MockedContentTypes.CreateSeoContentType();
|
||||
service.Save(seoComposition);
|
||||
|
||||
var metaAdded = contentPage.AddContentType(metaComposition);
|
||||
service.Save(contentPage);
|
||||
var seoAdded = advancedPage.AddContentType(seoComposition);
|
||||
service.Save(advancedPage);
|
||||
|
||||
// Act
|
||||
var duplicatePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var addedToBasePage = basePage.AddPropertyType(duplicatePropertyType, "Content");
|
||||
var addedToAdvancedPage = advancedPage.AddPropertyType(duplicatePropertyType, "Content");
|
||||
var addedToMeta = metaComposition.AddPropertyType(duplicatePropertyType, "Meta");
|
||||
var addedToSeo = seoComposition.AddPropertyType(duplicatePropertyType, "Seo");
|
||||
|
||||
// Assert
|
||||
Assert.That(metaAdded, Is.True);
|
||||
Assert.That(seoAdded, Is.True);
|
||||
|
||||
Assert.That(addedToBasePage, Is.True);
|
||||
Assert.That(addedToAdvancedPage, Is.False);
|
||||
Assert.That(addedToMeta, Is.True);
|
||||
Assert.That(addedToSeo, Is.True);
|
||||
|
||||
Assert.Throws<Exception>(() => service.Save(basePage));
|
||||
Assert.Throws<Exception>(() => service.Save(metaComposition));
|
||||
Assert.Throws<Exception>(() => service.Save(seoComposition));
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("meta"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("seo"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Add_Duplicate_PropertyType_Alias_At_Root_Which_Conflicts_With_Third_Levels_Composition()
|
||||
{
|
||||
/*
|
||||
* BasePage, gets 'Title' added but should not be allowed
|
||||
* -- Content Page
|
||||
* ---- Advanced Page -> Content Meta
|
||||
* Content Meta :: Composition, has 'Title'
|
||||
*
|
||||
* Content Meta has 'Title' PropertyType
|
||||
* Adding 'Title' to BasePage should fail
|
||||
*/
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var compositionAdded = advancedPage.AddContentType(contentMetaComposition);
|
||||
service.Save(advancedPage);
|
||||
|
||||
//NOTE: It should not be possible to Save 'BasePage' with the Title PropertyType added
|
||||
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var titleAdded = basePage.AddPropertyType(titlePropertyType, "Content");
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(titleAdded, Is.True);
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
|
||||
Assert.Throws<Exception>(() => service.Save(basePage));
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Rename_PropertyType_Alias_On_Composition_Which_Would_Cause_Conflict_In_Other_Composition()
|
||||
{
|
||||
/*
|
||||
* Meta renames alias to 'title'
|
||||
* Seo has 'Title'
|
||||
* BasePage
|
||||
* -- ContentPage
|
||||
* ---- AdvancedPage -> Seo
|
||||
* ------ MoreAdvanedPage -> Meta
|
||||
*/
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
var moreAdvancedPage = MockedContentTypes.CreateBasicContentType("moreAdvancedPage", "More Advanced Page", advancedPage);
|
||||
service.Save(moreAdvancedPage);
|
||||
|
||||
var seoComposition = MockedContentTypes.CreateSeoContentType();
|
||||
service.Save(seoComposition);
|
||||
var metaComposition = MockedContentTypes.CreateMetaContentType();
|
||||
service.Save(metaComposition);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitleAdded = advancedPage.AddPropertyType(subtitlePropertyType, "Content");
|
||||
service.Save(advancedPage);
|
||||
|
||||
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var titleAdded = seoComposition.AddPropertyType(titlePropertyType, "Content");
|
||||
service.Save(seoComposition);
|
||||
|
||||
var seoCompositionAdded = advancedPage.AddContentType(seoComposition);
|
||||
var metaCompositionAdded = moreAdvancedPage.AddContentType(metaComposition);
|
||||
service.Save(advancedPage);
|
||||
service.Save(moreAdvancedPage);
|
||||
|
||||
var keywordsPropertyType = metaComposition.PropertyTypes.First(x => x.Alias.Equals("metakeywords"));
|
||||
keywordsPropertyType.Alias = "title";
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(titleAdded, Is.True);
|
||||
Assert.That(seoCompositionAdded, Is.True);
|
||||
Assert.That(metaCompositionAdded, Is.True);
|
||||
|
||||
Assert.Throws<Exception>(() => service.Save(metaComposition));
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("moreAdvancedPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Add_Additional_Properties_On_Composition_Once_Composition_Has_Been_Saved()
|
||||
{
|
||||
/*
|
||||
* Meta renames alias to 'title'
|
||||
* Seo has 'Title'
|
||||
* BasePage
|
||||
* -- ContentPage
|
||||
* ---- AdvancedPage -> Seo
|
||||
* ------ MoreAdvancedPage -> Meta
|
||||
*/
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
var moreAdvancedPage = MockedContentTypes.CreateBasicContentType("moreAdvancedPage", "More Advanced Page", advancedPage);
|
||||
service.Save(moreAdvancedPage);
|
||||
|
||||
var seoComposition = MockedContentTypes.CreateSeoContentType();
|
||||
service.Save(seoComposition);
|
||||
var metaComposition = MockedContentTypes.CreateMetaContentType();
|
||||
service.Save(metaComposition);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitleAdded = advancedPage.AddPropertyType(subtitlePropertyType, "Content");
|
||||
service.Save(advancedPage);
|
||||
|
||||
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var titleAdded = seoComposition.AddPropertyType(titlePropertyType, "Content");
|
||||
service.Save(seoComposition);
|
||||
|
||||
var seoCompositionAdded = advancedPage.AddContentType(seoComposition);
|
||||
var metaCompositionAdded = moreAdvancedPage.AddContentType(metaComposition);
|
||||
service.Save(advancedPage);
|
||||
service.Save(moreAdvancedPage);
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(titleAdded, Is.True);
|
||||
Assert.That(seoCompositionAdded, Is.True);
|
||||
Assert.That(metaCompositionAdded, Is.True);
|
||||
|
||||
var testPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "test", Name = "Test", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var testAdded = seoComposition.AddPropertyType(testPropertyType, "Content");
|
||||
service.Save(seoComposition);
|
||||
|
||||
Assert.That(testAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("moreAdvancedPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Rename_PropertyGroup_On_Child_Avoiding_Conflict_With_Parent_PropertyGroup()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, true, "Content");
|
||||
service.Save(page);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true, "Content_");
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true, "Details");
|
||||
service.Save(advancedPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
//Change the name of the tab on the "root" content type 'page'.
|
||||
var propertyGroup = contentPage.PropertyGroups["Content_"];
|
||||
Assert.Throws<Exception>(() => contentPage.PropertyGroups.Add(new PropertyGroup
|
||||
{
|
||||
Id = propertyGroup.Id,
|
||||
Name = "Content",
|
||||
SortOrder = 0
|
||||
}));
|
||||
|
||||
// Assert
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cannot_Rename_PropertyType_Alias_Causing_Conflicts_With_Parents()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
|
||||
// Act
|
||||
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var titleAdded = basePage.AddPropertyType(titlePropertyType, "Content");
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = contentPage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = advancedPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
service.Save(contentPage);
|
||||
service.Save(advancedPage);
|
||||
|
||||
//Rename the PropertyType to something that already exists in the Composition - NOTE this should not be allowed and Saving should throw an exception
|
||||
var authorPropertyTypeToRename = advancedPage.PropertyTypes.First(x => x.Alias.Equals("author"));
|
||||
authorPropertyTypeToRename.Alias = "title";
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(titleAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
|
||||
Assert.Throws<Exception>(() => service.Save(advancedPage));
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Add_PropertyType_Alias_Which_Exists_In_Composition_Outside_Graph()
|
||||
{
|
||||
/*
|
||||
* Meta (Composition)
|
||||
* Content Meta (Composition) has 'Title' -> Meta
|
||||
* BasePage
|
||||
* -- ContentPage gets 'Title' added -> Meta
|
||||
* ---- Advanced Page
|
||||
*/
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
|
||||
var basePage = MockedContentTypes.CreateSimpleContentType("basePage", "Base Page", null, true);
|
||||
service.Save(basePage);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", basePage, true);
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true);
|
||||
service.Save(advancedPage);
|
||||
|
||||
var metaComposition = MockedContentTypes.CreateMetaContentType();
|
||||
service.Save(metaComposition);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
var metaAdded = contentPage.AddContentType(metaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
var metaAddedToComposition = contentMetaComposition.AddContentType(metaComposition);
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var propertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var addedToContentPage = contentPage.AddPropertyType(propertyType, "Content");
|
||||
|
||||
// Assert
|
||||
Assert.That(metaAdded, Is.True);
|
||||
Assert.That(metaAddedToComposition, Is.True);
|
||||
|
||||
Assert.That(addedToContentPage, Is.True);
|
||||
Assert.DoesNotThrow(() => service.Save(contentPage));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Rename_PropertyGroup_With_Inherited_PropertyGroups()
|
||||
{
|
||||
//Related the first issue in screencast from this post http://issues.umbraco.org/issue/U4-5986
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
|
||||
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, false, "Content_");
|
||||
service.Save(page);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true);
|
||||
service.Save(contentPage);
|
||||
var composition = MockedContentTypes.CreateMetaContentType();
|
||||
composition.AddPropertyGroup("Content");
|
||||
service.Save(composition);
|
||||
//Adding Meta-composition to child doc type
|
||||
contentPage.AddContentType(composition);
|
||||
service.Save(contentPage);
|
||||
|
||||
// Act
|
||||
var propertyTypeOne = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "testTextbox", Name = "Test Textbox", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var firstOneAdded = contentPage.AddPropertyType(propertyTypeOne, "Content_");
|
||||
var propertyTypeTwo = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "anotherTextbox", Name = "Another Test Textbox", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var secondOneAdded = contentPage.AddPropertyType(propertyTypeTwo, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
Assert.That(page.PropertyGroups.Contains("Content_"), Is.True);
|
||||
var propertyGroup = page.PropertyGroups["Content_"];
|
||||
page.PropertyGroups.Add(new PropertyGroup{ Id = propertyGroup.Id, Name = "ContentTab", SortOrder = 0});
|
||||
service.Save(page);
|
||||
|
||||
// Assert
|
||||
Assert.That(firstOneAdded, Is.True);
|
||||
Assert.That(secondOneAdded, Is.True);
|
||||
|
||||
var contentType = service.GetContentType("contentPage");
|
||||
Assert.That(contentType, Is.Not.Null);
|
||||
|
||||
var compositionPropertyGroups = contentType.CompositionPropertyGroups;
|
||||
Assert.That(compositionPropertyGroups.Count(x => x.Name.Equals("Content_")), Is.EqualTo(0));
|
||||
|
||||
var propertyTypeCount = contentType.PropertyTypes.Count();
|
||||
var compPropertyTypeCount = contentType.CompositionPropertyTypes.Count();
|
||||
Assert.That(propertyTypeCount, Is.EqualTo(5));
|
||||
Assert.That(compPropertyTypeCount, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Rename_PropertyGroup_On_Parent_Without_Causing_Duplicate_PropertyGroups()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, true, "Content_");
|
||||
service.Save(page);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true, "Contentx");
|
||||
service.Save(contentPage);
|
||||
var advancedPage = MockedContentTypes.CreateSimpleContentType("advancedPage", "Advanced Page", contentPage, true, "Contenty");
|
||||
service.Save(advancedPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = contentPage.AddPropertyType(bodyTextPropertyType, "Content_");//Will be added to the parent tab
|
||||
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");//Will be added to the "Content Meta" composition
|
||||
service.Save(contentPage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var descriptionPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "description", Name = "Description", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var keywordsPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "keywords", Name = "Keywords", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = advancedPage.AddPropertyType(authorPropertyType, "Content_");//Will be added to an ancestor tab
|
||||
var descriptionAdded = advancedPage.AddPropertyType(descriptionPropertyType, "Contentx");//Will be added to a parent tab
|
||||
var keywordsAdded = advancedPage.AddPropertyType(keywordsPropertyType, "Content");//Will be added to the "Content Meta" composition
|
||||
service.Save(advancedPage);
|
||||
|
||||
//Change the name of the tab on the "root" content type 'page'.
|
||||
var propertyGroup = page.PropertyGroups["Content_"];
|
||||
page.PropertyGroups.Add(new PropertyGroup { Id = propertyGroup.Id, Name = "Content", SortOrder = 0 });
|
||||
service.Save(page);
|
||||
|
||||
// Assert
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(descriptionAdded, Is.True);
|
||||
Assert.That(keywordsAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
|
||||
var advancedPageReloaded = service.GetContentType("advancedPage");
|
||||
var contentUnderscoreTabExists = advancedPageReloaded.CompositionPropertyGroups.Any(x => x.Name.Equals("Content_"));
|
||||
Assert.That(contentUnderscoreTabExists, Is.False);
|
||||
|
||||
var numberOfContentTabs = advancedPageReloaded.CompositionPropertyGroups.Count(x => x.Name.Equals("Content"));
|
||||
Assert.That(numberOfContentTabs, Is.EqualTo(4));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Rename_PropertyGroup_On_Parent_Without_Causing_Duplicate_PropertyGroups_v2()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, true, "Content_");
|
||||
service.Save(page);
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var subtitlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "subtitle", Name = "Subtitle", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = page.AddPropertyType(bodyTextPropertyType, "Content_");
|
||||
var subtitleAdded = contentPage.AddPropertyType(subtitlePropertyType, "Content");
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content_");
|
||||
service.Save(page);
|
||||
service.Save(contentPage);
|
||||
|
||||
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
//Change the name of the tab on the "root" content type 'page'.
|
||||
var propertyGroup = page.PropertyGroups["Content_"];
|
||||
page.PropertyGroups.Add(new PropertyGroup { Id = propertyGroup.Id, Name = "Content", SortOrder = 0 });
|
||||
service.Save(page);
|
||||
|
||||
// Assert
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(subtitleAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Remove_PropertyGroup_On_Parent_Without_Causing_Duplicate_PropertyGroups()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
basePage.RemovePropertyGroup("Content");
|
||||
service.Save(basePage);
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
|
||||
var contentType = service.GetContentType("contentPage");
|
||||
var propertyGroup = contentType.PropertyGroups["Content"];
|
||||
Assert.That(propertyGroup.ParentId.HasValue, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Add_PropertyGroup_With_Same_Name_On_Parent_and_Child()
|
||||
{
|
||||
/*
|
||||
* BasePage
|
||||
* - Content Page
|
||||
* -- Advanced Page
|
||||
* Content Meta :: Composition
|
||||
*/
|
||||
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = MockedContentTypes.CreateBasicContentType();
|
||||
service.Save(basePage);
|
||||
|
||||
var contentPage = MockedContentTypes.CreateBasicContentType("contentPage", "Content Page", basePage);
|
||||
service.Save(contentPage);
|
||||
|
||||
var advancedPage = MockedContentTypes.CreateBasicContentType("advancedPage", "Advanced Page", contentPage);
|
||||
service.Save(advancedPage);
|
||||
|
||||
var contentMetaComposition = MockedContentTypes.CreateContentMetaContentType();
|
||||
service.Save(contentMetaComposition);
|
||||
|
||||
// Act
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "author", Name = "Author", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = contentPage.AddPropertyType(authorPropertyType, "Content");
|
||||
service.Save(contentPage);
|
||||
|
||||
var bodyTextPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88
|
||||
};
|
||||
var bodyTextAdded = basePage.AddPropertyType(bodyTextPropertyType, "Content");
|
||||
service.Save(basePage);
|
||||
|
||||
var compositionAdded = contentPage.AddContentType(contentMetaComposition);
|
||||
service.Save(contentPage);
|
||||
|
||||
// Assert
|
||||
Assert.That(bodyTextAdded, Is.True);
|
||||
Assert.That(authorAdded, Is.True);
|
||||
Assert.That(compositionAdded, Is.True);
|
||||
|
||||
Assert.DoesNotThrow(() => service.GetContentType("contentPage"));
|
||||
Assert.DoesNotThrow(() => service.GetContentType("advancedPage"));
|
||||
|
||||
var contentType = service.GetContentType("contentPage");
|
||||
var propertyGroup = contentType.PropertyGroups["Content"];
|
||||
Assert.That(propertyGroup.ParentId.HasValue, Is.False);
|
||||
|
||||
var numberOfContentTabs = contentType.CompositionPropertyGroups.Count(x => x.Name.Equals("Content"));
|
||||
Assert.That(numberOfContentTabs, Is.EqualTo(3));
|
||||
|
||||
//Ensure that adding a new PropertyType to the "Content"-tab also adds it to the right group
|
||||
|
||||
var descriptionPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "description", Name = "Description", Description = "", HelpText = "", Mandatory = false, SortOrder = 1,DataTypeDefinitionId = -88
|
||||
};
|
||||
var descriptionAdded = contentType.AddPropertyType(descriptionPropertyType, "Content");
|
||||
service.Save(contentType);
|
||||
Assert.That(descriptionAdded, Is.True);
|
||||
|
||||
var contentPageReloaded = service.GetContentType("contentPage");
|
||||
var propertyGroupReloaded = contentPageReloaded.PropertyGroups["Content"];
|
||||
var hasDescriptionPropertyType = propertyGroupReloaded.PropertyTypes.Contains("description");
|
||||
Assert.That(hasDescriptionPropertyType, Is.True);
|
||||
Assert.That(propertyGroupReloaded.ParentId.HasValue, Is.False);
|
||||
|
||||
var descriptionPropertyTypeReloaded = propertyGroupReloaded.PropertyTypes["description"];
|
||||
Assert.That(descriptionPropertyTypeReloaded.PropertyGroupId.IsValueCreated, Is.False);
|
||||
}
|
||||
|
||||
private ContentType CreateComponent()
|
||||
{
|
||||
var component = new ContentType(-1)
|
||||
@@ -487,9 +1251,10 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
private ContentType CreateBannerComponent(ContentType parent)
|
||||
{
|
||||
var banner = new ContentType(parent)
|
||||
const string contentTypeAlias = "banner";
|
||||
var banner = new ContentType(parent, contentTypeAlias)
|
||||
{
|
||||
Alias = "banner",
|
||||
Alias = contentTypeAlias,
|
||||
Name = "Banner Component",
|
||||
Description = "ContentType used for Banner Component",
|
||||
Icon = ".sprTreeDoc3",
|
||||
@@ -535,9 +1300,10 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
private ContentType CreateHomepage(ContentType parent)
|
||||
{
|
||||
var contentType = new ContentType(parent)
|
||||
const string contentTypeAlias = "homepage";
|
||||
var contentType = new ContentType(parent, contentTypeAlias)
|
||||
{
|
||||
Alias = "homepage",
|
||||
Alias = contentTypeAlias,
|
||||
Name = "Homepage",
|
||||
Description = "ContentType used for the Homepage",
|
||||
Icon = ".sprTreeDoc3",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -196,6 +196,34 @@ namespace Umbraco.Tests.Services.Importing {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
///<umbPackage>
|
||||
/// <files>
|
||||
/// <file>
|
||||
/// <guid>bootstrap.min.js</guid>
|
||||
/// <orgPath>/js</orgPath>
|
||||
/// <orgName>bootstrap.min.js</orgName>
|
||||
/// </file>
|
||||
/// <file>
|
||||
/// <guid>jquery.min.js</guid>
|
||||
/// <orgPath>/js</orgPath>
|
||||
/// <orgName>jquery.min.js</orgName>
|
||||
/// </file>
|
||||
/// <file>
|
||||
/// <guid>top-image.jpg</guid>
|
||||
/// <orgPath>/Media/1001</orgPath>
|
||||
/// <orgName>top-image.jpg</orgName>
|
||||
/// </file>
|
||||
/// <file>
|
||||
/// <guid>top-im [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string Fanoe_Package {
|
||||
get {
|
||||
return ResourceManager.GetString("Fanoe_Package", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
///<umbPackage>
|
||||
|
||||
@@ -154,4 +154,7 @@
|
||||
<data name="CompositionsTestPackage_Random" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>compositionstestpackage-random.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="Fanoe_Package" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>fanoe-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -211,6 +211,30 @@ namespace Umbraco.Tests.Services.Importing
|
||||
Assert.That(templates.Any(), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PackagingService_Can_Import_Fanoe_Starterkit_ContentTypes_And_Templates_Xml()
|
||||
{
|
||||
// Arrange
|
||||
string strXml = ImportResources.Fanoe_Package;
|
||||
var xml = XElement.Parse(strXml);
|
||||
var dataTypeElement = xml.Descendants("DataTypes").First();
|
||||
var templateElement = xml.Descendants("Templates").First();
|
||||
var docTypeElement = xml.Descendants("DocumentTypes").First();
|
||||
|
||||
// Act
|
||||
var dataTypeDefinitions = ServiceContext.PackagingService.ImportDataTypeDefinitions(dataTypeElement);
|
||||
var templates = ServiceContext.PackagingService.ImportTemplates(templateElement);
|
||||
var contentTypes = ServiceContext.PackagingService.ImportContentTypes(docTypeElement);
|
||||
var numberOfDocTypes = (from doc in docTypeElement.Elements("DocumentType") select doc).Count();
|
||||
|
||||
//Assert - Re-Import contenttypes doesn't throw
|
||||
Assert.DoesNotThrow(() => ServiceContext.PackagingService.ImportContentTypes(docTypeElement));
|
||||
Assert.That(contentTypes.Count(), Is.EqualTo(numberOfDocTypes));
|
||||
Assert.That(dataTypeDefinitions, Is.Not.Null);
|
||||
Assert.That(dataTypeDefinitions.Any(), Is.True);
|
||||
Assert.That(templates.Any(), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PackagingService_Can_Import_Content_Package_Xml()
|
||||
{
|
||||
|
||||
@@ -6,7 +6,25 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
{
|
||||
public class MockedContentTypes
|
||||
{
|
||||
|
||||
public static ContentType CreateBasicContentType(string alias = "basePage", string name = "Base Page",
|
||||
ContentType parent = null)
|
||||
{
|
||||
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent, alias);
|
||||
|
||||
contentType.Alias = alias;
|
||||
contentType.Name = name;
|
||||
contentType.Description = "ContentType used for basic pages";
|
||||
contentType.Icon = ".sprTreeDoc3";
|
||||
contentType.Thumbnail = "doc2.png";
|
||||
contentType.SortOrder = 1;
|
||||
contentType.CreatorId = 0;
|
||||
contentType.Trashed = false;
|
||||
|
||||
//ensure that nothing is marked as dirty
|
||||
contentType.ResetDirtyProperties(false);
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateTextpageContentType(string alias = "textPage", string name = "Text Page")
|
||||
{
|
||||
@@ -65,6 +83,57 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateContentMetaContentType()
|
||||
{
|
||||
var contentType = new ContentType(-1)
|
||||
{
|
||||
Alias = "contentMeta",
|
||||
Name = "Content Meta",
|
||||
Description = "ContentType used for Content Meta",
|
||||
Icon = ".sprTreeDoc3",
|
||||
Thumbnail = "doc.png",
|
||||
SortOrder = 1,
|
||||
CreatorId = 0,
|
||||
Trashed = false
|
||||
};
|
||||
|
||||
var metaCollection = new PropertyTypeCollection();
|
||||
metaCollection.Add(new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(metaCollection) { Name = "Content", SortOrder = 2 });
|
||||
|
||||
//ensure that nothing is marked as dirty
|
||||
contentType.ResetDirtyProperties(false);
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSeoContentType()
|
||||
{
|
||||
var contentType = new ContentType(-1)
|
||||
{
|
||||
Alias = "seo",
|
||||
Name = "Seo",
|
||||
Description = "ContentType used for Seo",
|
||||
Icon = ".sprTreeDoc3",
|
||||
Thumbnail = "doc.png",
|
||||
SortOrder = 1,
|
||||
CreatorId = 0,
|
||||
Trashed = false
|
||||
};
|
||||
|
||||
var metaCollection = new PropertyTypeCollection();
|
||||
metaCollection.Add(new PropertyType("seotest", DataTypeDatabaseType.Ntext) { Alias = "seokeywords", Name = "Seo Keywords", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
|
||||
metaCollection.Add(new PropertyType("seotest", DataTypeDatabaseType.Ntext) { Alias = "seodescription", Name = "Seo Description", Description = "", HelpText = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -89 });
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(metaCollection) { Name = "Seo", SortOrder = 5 });
|
||||
|
||||
//ensure that nothing is marked as dirty
|
||||
contentType.ResetDirtyProperties(false);
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSimpleContentType()
|
||||
{
|
||||
var contentType = new ContentType(-1)
|
||||
@@ -92,9 +161,9 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSimpleContentType(string alias, string name, IContentType parent = null, bool randomizeAliases = false)
|
||||
public static ContentType CreateSimpleContentType(string alias, string name, IContentType parent = null, bool randomizeAliases = false, string propertyGroupName = "Content")
|
||||
{
|
||||
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent);
|
||||
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent, alias);
|
||||
|
||||
contentType.Alias = alias;
|
||||
contentType.Name = name;
|
||||
@@ -110,7 +179,7 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TinyMCEAlias, DataTypeDatabaseType.Ntext) { Alias = RandomAlias("bodyText", randomizeAliases), Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -87 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = RandomAlias("author", randomizeAliases) , Name = "Author", Description = "Name of the author", HelpText = "", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -88 });
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = propertyGroupName, SortOrder = 1 });
|
||||
|
||||
//ensure that nothing is marked as dirty
|
||||
contentType.ResetDirtyProperties(false);
|
||||
@@ -167,6 +236,27 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSimpleContentType(string alias, string name, PropertyTypeCollection collection, string propertyGroupName, IContentType parent = null)
|
||||
{
|
||||
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent, alias);
|
||||
|
||||
contentType.Alias = alias;
|
||||
contentType.Name = name;
|
||||
contentType.Description = "ContentType used for simple text pages";
|
||||
contentType.Icon = ".sprTreeDoc3";
|
||||
contentType.Thumbnail = "doc2.png";
|
||||
contentType.SortOrder = 1;
|
||||
contentType.CreatorId = 0;
|
||||
contentType.Trashed = false;
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(collection) { Name = propertyGroupName, SortOrder = 1 });
|
||||
|
||||
//ensure that nothing is marked as dirty
|
||||
contentType.ResetDirtyProperties(false);
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSimpleContentType(string alias, string name, PropertyTypeCollection groupedCollection, PropertyTypeCollection nonGroupedCollection)
|
||||
{
|
||||
var contentType = CreateSimpleContentType(alias, name, groupedCollection);
|
||||
|
||||
@@ -697,6 +697,7 @@
|
||||
<Content Include="Services\Importing\CompositionsTestPackage-Random.xml" />
|
||||
<Content Include="Services\Importing\CompositionsTestPackage.xml" />
|
||||
<Content Include="Services\Importing\Dictionary-Package.xml" />
|
||||
<Content Include="Services\Importing\Fanoe-Package.xml" />
|
||||
<Content Include="UmbracoExamine\TestFiles\media.xml" />
|
||||
<Content Include="Services\Importing\InheritedDocTypes-Package.xml" />
|
||||
<Content Include="Services\Importing\SingleDocType.xml" />
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
abbr,address,article,aside,audio,b,blockquote,body,canvas,caption,cite,code,dd,del,details,dfn,div,dl,dt,em,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,p,pre,q,samp,section,small,span,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,ul,var,video{margin:0;padding:0;outline:0;border:0;background:0 0;vertical-align:baseline;font-size:100%}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}nav ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:'';content:none}a{margin:0;padding:0;background:0 0;vertical-align:baseline;font-size:100%}ins{background-color:#ff9;color:#000;text-decoration:none}mark{background-color:#ff9;color:#000;font-weight:700;font-style:italic}del{text-decoration:line-through}abbr[title],dfn[title]{border-bottom:1px dotted;cursor:help}table{border-spacing:0;border-collapse:collapse}hr{display:block;margin:1em 0;padding:0;height:1px;border:0;border-top:1px solid #ccc}input,select{vertical-align:middle}html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{box-sizing:border-box}body,html{height:100%;width:100%;color:#fff;font-family:'Open Sans',sans-serif;font-weight:400;font-size:.9375em;line-height:1.5}h1{font-size:1.7em;margin:40px auto 10px;font-weight:700}h2{font-size:1.35em;margin:0 auto .4em;font-weight:700}h3{font-size:1em;font-weight:400;font-style:italic}p{font-size:1em;line-height:1.6}p+a{margin-top:1rem;display:inline-block}a,a:active,a:visited{text-decoration:none}.cta{margin:4.5em auto 1.5em;padding-bottom:4.5em}.button,.button:visited{padding:.9375em 1.875em;border-radius:.1em;font-weight:600;font-size:1.2em;background:#2e99f4;color:#fff;display:inline-block;border:none;transition:all 200ms ease-in-out}.button:hover,.button:visited:hover{border-bottom:none;background:#0c80e3}section{background:url(../img/nonodesbg.jpg) center center/cover;height:100%;width:100%;display:table;padding:3em 1.75em}section a,section a:focus,section a:visited{color:#46a5f5;font-size:1.1625em;border-bottom:1px solid transparent;transition:border-bottom 100ms ease-in-out}section a:focus:hover,section a:hover,section a:visited:hover{border-bottom:1px solid}section:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.17);background:linear-gradient(45deg,rgba(85,98,112,.1) 10%,rgba(255,107,107,.1) 95%);z-index:0}section article{display:table-cell;vertical-align:middle;margin:0 auto;text-align:center;position:relative;z-index:100}section article>div{max-width:60em;margin:0 auto}section .logo{background:url(../img/logo.png) no-repeat;width:91px;height:91px;margin:0 auto}section .row{overflow:hidden}section .row .col{text-align:left;width:100%}section .row .col:nth-child(2){margin-top:3em}@media screen and (min-width:48em){body,html{font-size:1em}h1{font-size:2.5em;margin:70px auto 0;letter-spacing:.5px}h2{font-size:1.4375em;margin:0 auto 1em}h3{font-size:1.2em}a{font-size:1.1rem;font-weight:600}p+a{margin-top:3rem}.cta{margin:7.5em auto 2.5em;border-bottom:1px solid rgba(255,255,255,.5);padding-bottom:7.5em}section{padding:0 15px}section .row .col{float:left;width:50%;padding-right:5%;display:inline-block}section .row .col:nth-child(2){padding-right:0;padding-left:5%;margin-top:0}.button{font-size:1.1625em}}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 685 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 309 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 232 KiB |
@@ -18,8 +18,8 @@ angular.module("umbraco.directives")
|
||||
element.bind('blur', function(){ update(true); });
|
||||
|
||||
$timeout(function() {
|
||||
update();
|
||||
}, 100);
|
||||
update(true);
|
||||
}, 200);
|
||||
|
||||
|
||||
//I hate bootstrap tabs
|
||||
|
||||
@@ -33,6 +33,14 @@ angular.module("umbraco.directives.html")
|
||||
else {
|
||||
scope.labelstring = scope.label;
|
||||
}
|
||||
|
||||
if (scope.description && scope.description[0] === "@") {
|
||||
scope.descriptionstring = localizationService.localize(scope.description.substring(1));
|
||||
}
|
||||
else {
|
||||
scope.descriptionstring = scope.description;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:preventEnterSubmit
|
||||
* @description prevents a form from submitting when the enter key is pressed on an input field
|
||||
**/
|
||||
angular.module("umbraco.directives")
|
||||
.directive('preventEnterSubmit', function() {
|
||||
return function(scope, element, attrs) {
|
||||
|
||||
var enabled = true;
|
||||
//check if there's a value for the attribute, if there is and it's false then we conditionally don't
|
||||
//prevent default.
|
||||
if (attrs.preventEnterSubmit) {
|
||||
attrs.$observe("preventEnterSubmit", function (newVal) {
|
||||
enabled = (newVal === "false" || newVal === 0 || newVal === false) ? false : true;
|
||||
});
|
||||
}
|
||||
|
||||
$(element).keypress(function (event) {
|
||||
if (event.which === 13) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -31,7 +31,10 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
|
||||
var deferred = $q.defer();
|
||||
|
||||
if (formHelper.submitForm({ scope: args.scope, statusMessage: args.statusMessage })) {
|
||||
if (!args.scope.busy && formHelper.submitForm({ scope: args.scope, statusMessage: args.statusMessage })) {
|
||||
|
||||
args.scope.busy = true;
|
||||
|
||||
args.saveMethod(args.content, $routeParams.create, fileManager.getFiles())
|
||||
.then(function (data) {
|
||||
|
||||
@@ -42,6 +45,8 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
savedContent: data,
|
||||
rebindCallback: self.reBindChangedProperties(args.content, data)
|
||||
});
|
||||
|
||||
args.scope.busy = false;
|
||||
deferred.resolve(data);
|
||||
|
||||
}, function (err) {
|
||||
@@ -50,6 +55,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
err: err,
|
||||
rebindCallback: self.reBindChangedProperties(args.content, err.data)
|
||||
});
|
||||
args.scope.busy = false;
|
||||
deferred.reject(err);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
ng-pattern="passwordPattern"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"
|
||||
autocomplete="off"
|
||||
required
|
||||
ng-model="installer.current.model.password" id="password" />
|
||||
<small class="inline-help">At least {{installer.current.model.minCharLength}} characters long</small>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
overflow-y:hidden!important;
|
||||
}
|
||||
|
||||
IFRAME {overflow:hidden;}
|
||||
IFRAME {overflow:hidden;}
|
||||
|
||||
|
||||
// Sortabel
|
||||
@@ -500,7 +500,7 @@
|
||||
.usky-grid .usky-templates-columns{
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
|
||||
.usky-grid .usky-row-inner{
|
||||
margin-right: 45px;
|
||||
border: 1px dashed transparent;
|
||||
@@ -598,7 +598,7 @@
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
width: 125px;
|
||||
margin: 35px 40px 15px 0;
|
||||
margin: 35px 40px 15px 0;
|
||||
border: 2px solid @grayLight; /* @grayLight */
|
||||
transition: border 200ms linear;
|
||||
|
||||
@@ -618,7 +618,7 @@
|
||||
border-color: @blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.preview-row {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
@@ -627,7 +627,6 @@
|
||||
}
|
||||
|
||||
.preview-rows.layout {
|
||||
height: 180px;
|
||||
padding: 2px;
|
||||
|
||||
.preview-row {
|
||||
@@ -635,7 +634,7 @@
|
||||
}
|
||||
|
||||
.preview-col {
|
||||
height: 100%;
|
||||
height: 180px;
|
||||
border: dashed 1px @grayLight;
|
||||
}
|
||||
|
||||
@@ -806,7 +805,7 @@
|
||||
}
|
||||
|
||||
.usky-grid-configuration .uSky-templates-column.last{
|
||||
margin-right: -1px;
|
||||
margin-right: -1px;
|
||||
}
|
||||
|
||||
.usky-grid-configuration .uSky-templates-column.add{
|
||||
|
||||
@@ -12,16 +12,13 @@ function ContentEditDialogController($scope, editorState, $routeParams, $q, $tim
|
||||
scope: $scope,
|
||||
content: $scope.content
|
||||
}).then(function (content) {
|
||||
//success
|
||||
$scope.busy = false;
|
||||
|
||||
//success
|
||||
if (dialogOptions.closeOnSave) {
|
||||
$scope.submit(content);
|
||||
}
|
||||
|
||||
}, function(err) {
|
||||
//error
|
||||
$scope.busy = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -73,13 +73,11 @@ function ContentEditController($scope, $rootScope, $routeParams, $q, $timeout, $
|
||||
scope: $scope,
|
||||
content: $scope.content
|
||||
}).then(function (data) {
|
||||
//success
|
||||
$scope.busy = false;
|
||||
//success
|
||||
init($scope.content);
|
||||
syncTreeNode($scope.content, data.path);
|
||||
}, function (err) {
|
||||
//error
|
||||
$scope.busy = false;
|
||||
if (err) {
|
||||
editorState.set($scope.content);
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@ function startUpVideosDashboardController($scope, xmlhelper, $log, $http) {
|
||||
angular.module("umbraco").controller("Umbraco.Dashboard.StartupVideosController", startUpVideosDashboardController);
|
||||
|
||||
|
||||
|
||||
function FormsController($scope, $route, packageResource) {
|
||||
function FormsController($scope, $route, $cookieStore, packageResource) {
|
||||
$scope.installForms = function(){
|
||||
$scope.state = "Installng package";
|
||||
packageResource
|
||||
@@ -44,9 +43,8 @@ function FormsController($scope, $route, packageResource) {
|
||||
|
||||
$scope.complete = function(result){
|
||||
var url = window.location.href + "?init=true";
|
||||
window.location.href = url;
|
||||
|
||||
//window.location.reload();
|
||||
$cookieStore.put("umbPackageInstallId", result.packageGuid);
|
||||
window.location.reload(true);
|
||||
};
|
||||
|
||||
$scope.error = function(err){
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
<p style="font-size: 16px; line-height: 1.5; color: #4c4c4c;">Create forms using an intuitive drag and drop interface. From simple contact forms that sends e-mails to advanced questionaires that integrate with CRM systems. Your clients will love it!</p>
|
||||
|
||||
<button class="btn publish btn-install" ng-click="installForms()">Install</button>
|
||||
<small>Preview version should not be used in production</small>
|
||||
</div>
|
||||
|
||||
<div class="step-two" ng-if="state"> <!-- STEP two -->
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="umb-el-wrap">
|
||||
<label ng-if="hideLabel!=='true'" class="control-label" for="{{alias}}">
|
||||
{{labelstring}}
|
||||
<small>{{description}}</small>
|
||||
<small>{{descriptionstring}}</small>
|
||||
</label>
|
||||
|
||||
<div class="controls controls-row" ng-transclude>
|
||||
|
||||
+2
-5
@@ -11,14 +11,12 @@ angular.module("umbraco")
|
||||
macroData: $scope.control.value
|
||||
},
|
||||
callback: function (data) {
|
||||
|
||||
$scope.control.value = {
|
||||
syntax: data.syntax,
|
||||
macroAlias: data.macroAlias,
|
||||
macroParamsDictionary: data.macroParamsDictionary
|
||||
};
|
||||
|
||||
$scope.setPreview(data);
|
||||
$scope.setPreview($scope.control.value );
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -40,8 +38,7 @@ angular.module("umbraco")
|
||||
if($scope.control.$initializing){
|
||||
$scope.setMacro();
|
||||
}else if($scope.control.value){
|
||||
var parsed = macroService.parseMacroSyntax($scope.control.value.syntax);
|
||||
$scope.setPreview(parsed);
|
||||
$scope.setPreview($scope.control.value);
|
||||
}
|
||||
}, 200);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div ng-controller="Umbraco.PropertyEditors.Grid.TextStringController">
|
||||
<div>
|
||||
<textarea
|
||||
rows="1"
|
||||
umb-auto-resize
|
||||
|
||||
@@ -149,6 +149,9 @@ angular.module("umbraco")
|
||||
return ((spans / $scope.model.value.columns) * 100).toFixed(1);
|
||||
};
|
||||
|
||||
$scope.zeroWidthFilter = function (cell) {
|
||||
return cell.grid > 0;
|
||||
};
|
||||
|
||||
/****************
|
||||
Config
|
||||
|
||||
@@ -12,17 +12,17 @@
|
||||
<li ng-repeat="template in model.value.templates">
|
||||
|
||||
<div ng-click="configureTemplate(template)"
|
||||
class="preview-rows layout" style="height: 60px; margin-top: 5px; margin-bottom: 20px; float:left">
|
||||
class="preview-rows layout" style="margin-top: 5px; margin-bottom: 20px; float:left">
|
||||
|
||||
<div class="preview-row">
|
||||
<div class="preview-col"
|
||||
ng-class="{last:$last}"
|
||||
ng-repeat="section in template.sections"
|
||||
ng-style="{width: percentage(section.grid) + '%'}">
|
||||
ng-repeat="section in template.sections | filter:zeroWidthFilter"
|
||||
ng-style="{width: percentage(section.grid) + '%', height: '60px'}">
|
||||
<div class="preview-cell"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{{template.name}} <br/>
|
||||
@@ -57,25 +57,25 @@
|
||||
|
||||
<li ng-repeat="layout in model.value.layouts">
|
||||
|
||||
<div ng-click="configureLayout(layout)"
|
||||
<div ng-click="configureLayout(layout)"
|
||||
class="preview-rows columns" style="margin-top: 5px; margin-bottom: 25px; float:left">
|
||||
|
||||
<div class="preview-row">
|
||||
<div class="preview-col"
|
||||
ng-class="{last:$last}"
|
||||
ng-repeat="area in layout.areas"
|
||||
ng-repeat="area in layout.areas | filter:zeroWidthFilter"
|
||||
ng-style="{width: percentage(area.grid) + '%'}">
|
||||
|
||||
|
||||
<div class="preview-cell"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{{layout.name}}<br />
|
||||
<i class="icon-delete red"></i>
|
||||
<a class="btn btn-small btn-link" href ng-click="deleteLayout($index)">
|
||||
<localize key="general_delete" />
|
||||
<localize key="general_delete" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -95,13 +95,13 @@
|
||||
|
||||
<div style="max-width: 600px">
|
||||
|
||||
<umb-control-group
|
||||
label="@grid_columns"
|
||||
<umb-control-group
|
||||
label="@grid_columns"
|
||||
description="@grid_columnsDetails">
|
||||
<input type="text" class="" ng-model="model.value.columns" />
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group
|
||||
<umb-control-group
|
||||
label="@grid_settings"
|
||||
description="@grid_settingsDetails">
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<td>
|
||||
<form class="pull-right" novalidate>
|
||||
<i class="icon-search" ng-click="enterSearch($event)"></i>
|
||||
<input type="text" ng-model="options.filter" on-keyup="search()" no-dirty-check>
|
||||
<input type="text" ng-model="options.filter" on-keyup="search()" prevent-enter-submit no-dirty-check>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -2542,9 +2542,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7200</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7210</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7200</IISUrl>
|
||||
<IISUrl>http://localhost:7210</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -2,148 +2,67 @@
|
||||
<%@ Import Namespace="Umbraco.Core.Configuration" %>
|
||||
<%@ Import Namespace="Umbraco.Core.IO" %>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head runat="server">
|
||||
<!doctype html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
|
||||
<title></title>
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
|
||||
<meta charset="utf-8">
|
||||
<link href='//fonts.googleapis.com/css?family=Open+Sans:300,400,700,600' rel='stylesheet' type='text/css'>
|
||||
<link href='//fonts.googleapis.com/css?family=Asap:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
|
||||
|
||||
<title>Umbraco - no pages found</title>
|
||||
<link rel="icon" type="image/png" href="<%=umbraco.GlobalSettings.Path + "/Images/PinnedIcons/umb.ico" %>" />
|
||||
<link rel="stylesheet" href="../../Umbraco/assets/css/nonodes.style.min.css" />
|
||||
|
||||
<link media="all" rel="stylesheet" href="../../umbraco_client/installer/css/jquery-ui-1.8.6.custom.css" />
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.7.1/modernizr.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link media="all" type="text/css" rel="stylesheet" href="../../umbraco_client/installer/css/reset.css" />
|
||||
|
||||
<link media="all" rel="stylesheet" href="../../umbraco_client/installer/css/all.css" />
|
||||
|
||||
<link media="all" type="text/css" rel="stylesheet" href="../../umbraco_client/installer/css/form.css" />
|
||||
|
||||
<script src="../../umbraco_client/installer/js/jquery.1.4.4.js" type="text/javascript"></script>
|
||||
<script src="../../umbraco_client/installer/js/jquery.ui.selectmenu.js" type="text/javascript"></script>
|
||||
<script src="../../umbraco_client/installer/js/jquery.main.js" type="text/javascript"></script>
|
||||
|
||||
<script src="../../umbraco_client/passwordStrength/passwordstrength.js" type="text/javascript"></script>
|
||||
|
||||
<!--[if lt IE 9]>
|
||||
<link media="all" rel="stylesheet" href="../../umbraco_client/installer/css/lt7.css" />
|
||||
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<!--[if lt IE 7]><script type="text/javascript" src="../../umbraco_client/installer/js/ie-png.js"></script><![endif]-->
|
||||
|
||||
</head>
|
||||
<body class="theend">
|
||||
<form id="Form1" method="post" runat="server">
|
||||
<body>
|
||||
|
||||
<!-- all page -->
|
||||
<section>
|
||||
<article>
|
||||
<div>
|
||||
<div class="logo"></div>
|
||||
|
||||
<section id="wrapper">
|
||||
<h1>Welcome to your Umbraco installation</h1>
|
||||
<h3>You're seeing the wonderful page because your website doesn't contain any published content yet.</h3>
|
||||
|
||||
<div class="wholder">
|
||||
<div class="cta">
|
||||
<a href="<%= IOHelper.ResolveUrl(SystemDirectories.Umbraco) %>" class="button">Open Umbraco</a>
|
||||
</div>
|
||||
|
||||
<!-- header -->
|
||||
|
||||
<header id="header">
|
||||
<div class="holder">
|
||||
<strong class="logo"><a href="#">Umbraco</a></strong>
|
||||
</div>
|
||||
</header>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h2>Easy start with Umbraco.tv</h2>
|
||||
<p>We have created a bunch of 'how-to' videos, to get you easily started with Umbraco. Learn how to build projects in just a couple of minutes. Easiest CMS in the world.</p>
|
||||
|
||||
<a href="http://umbraco.tv?ref=tvFromInstaller" target="_blank">Umbraco.tv →</a>
|
||||
</div>
|
||||
|
||||
<!-- all content -->
|
||||
<div class="col">
|
||||
<h2>Be a part of the community</h2>
|
||||
<p>The Umbraco community is the best of its kind, be sure to visit, and if you have any questions, we’re sure that you can get your answers from the community.</p>
|
||||
|
||||
<a href="http://our.umbraco.org?ref=ourFromInstaller" target="_blank">our.Umbraco →</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section id="main">
|
||||
|
||||
<!-- content -->
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<section class="content">
|
||||
</section>
|
||||
|
||||
<script type="text/javascript">
|
||||
jQuery(document).ready(function () {
|
||||
$.post("../../install/InstallerRestService.aspx?feed=sitebuildervids",
|
||||
function(data) {
|
||||
jQuery("#ajax-sitebuildervids").html(data);
|
||||
});
|
||||
<script src="//code.jquery.com/jquery-latest.min.js"></script>
|
||||
|
||||
$.post("../../install/InstallerRestService.aspx?feed=developervids",
|
||||
function(data) {
|
||||
jQuery("#ajax-developervids").html(data);
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<!-- done box -->
|
||||
|
||||
<div class="tab main-tabinfo">
|
||||
<div class="container">
|
||||
<h1>Looks like there's still work to do</h1>
|
||||
<p>
|
||||
You're seeing the wonderful page because your website doesn't contain any <strong>published</strong> content yet.
|
||||
</p>
|
||||
<p>
|
||||
So get rid of this page by starting umbraco and publishing some content. You can do this by clicking the "set up your new website" button below.
|
||||
</p>
|
||||
<ul class="btn-web">
|
||||
<li class="btn-set"><a href="<%= IOHelper.ResolveUrl(SystemDirectories.Umbraco) %>"><span>Launch umbraco</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="threcol">
|
||||
<div class="t">
|
||||
|
||||
</div>
|
||||
<div class="hold">
|
||||
<aside class="col1">
|
||||
<h2>Useful links</h2>
|
||||
<p>We’ve put together some useful links to help you get started with Umbraco.</p>
|
||||
<nav class="links">
|
||||
<ul>
|
||||
<li><a href="http://our.umbraco.org?ref=ourFromInstaller">our.umbraco.org</a></li>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li><a href="http://our.umbraco.org/wiki?ref=LatestDocsFromInstaller">New documentation</a></li>
|
||||
<li><a href="http://our.umbraco.org/projects?ref=LatestProjectsFromInstaller">New Projects</a></li>
|
||||
<li><a href="http://our.umbraco.org/forum?ref=LatesTalkFromInstaller">Forum Talk</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
<aside class="col2">
|
||||
<h2>Sitebuilder introduction</h2>
|
||||
<div id="ajax-sitebuildervids"><small>Loading...</small></div>
|
||||
</aside>
|
||||
<aside class="col3">
|
||||
<h2>Developer introduction</h2>
|
||||
<div id="ajax-developervids"><small>Loading...</small></div>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- bg page -->
|
||||
<div class="bg-main">
|
||||
<div class="color2">
|
||||
<div class="bg-c"></div>
|
||||
</div>
|
||||
<div class="color3">
|
||||
<div class="bg-c"></div>
|
||||
</div>
|
||||
<div class="color1">
|
||||
<div class="bg-c"></div>
|
||||
</div>
|
||||
<div class="color4">
|
||||
<div class="bg-c"></div>
|
||||
</div>
|
||||
<div class="color5">
|
||||
<div class="bg-c"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -45,7 +45,7 @@
|
||||
<MacroErrors>inline</MacroErrors>
|
||||
|
||||
<!-- These file types will not be allowed to be uploaded via the upload control for media and content -->
|
||||
<disallowedUploadFiles>ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,swf,xml,html.htm,svg,php,htaccess</disallowedUploadFiles>
|
||||
<disallowedUploadFiles>ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,swf,xml,html,htm,svg,php,htaccess</disallowedUploadFiles>
|
||||
|
||||
<!-- Defines the default document type property used when adding properties in the back-office (if missing or empty, defaults to Textstring -->
|
||||
<defaultDocumentTypeProperty>Textstring</defaultDocumentTypeProperty>
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
<MacroErrors>throw</MacroErrors>
|
||||
|
||||
<!-- These file types will not be allowed to be uploaded via the upload control for media and content -->
|
||||
<disallowedUploadFiles>ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,swf,xml,html.htm,svg,php,htaccess</disallowedUploadFiles>
|
||||
<disallowedUploadFiles>ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,swf,xml,html,htm,svg,php,htaccess</disallowedUploadFiles>
|
||||
|
||||
<!-- Defines the default document type property used when adding properties in the back-office (if missing or empty, defaults to Textstring -->
|
||||
<defaultDocumentTypeProperty>Textstring</defaultDocumentTypeProperty>
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
<create assembly="umbraco" type="MediaTypeTasks" />
|
||||
<delete assembly="umbraco" type="MediaTypeTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
</nodeType>
|
||||
<nodeType alias="initmember">
|
||||
<header>member</header>
|
||||
<usercontrol>/create/member.ascx</usercontrol>
|
||||
@@ -324,7 +324,7 @@
|
||||
</nodeType>
|
||||
<nodeType alias="partialViews">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialView.ascx</usercontrol>
|
||||
<usercontrol>/Create/PartialView.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="PartialViewTasks" />
|
||||
<delete assembly="umbraco" type="PartialViewTasks" />
|
||||
@@ -338,4 +338,20 @@
|
||||
<delete assembly="umbraco" type="PartialViewMacroTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewsFolder">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialView.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="PartialViewTasks" />
|
||||
<delete assembly="umbraco" type="PartialViewTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewMacrosFolder">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialViewMacro.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="PartialViewMacroTasks" />
|
||||
<delete assembly="umbraco" type="PartialViewMacroTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
</createUI>
|
||||
|
||||
@@ -330,14 +330,6 @@
|
||||
<delete assembly="umbraco" type="PartialViewTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewsFolder">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialView.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="PartialViewTasks" />
|
||||
<delete assembly="umbraco" type="PartialViewTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewMacros">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialViewMacro.ascx</usercontrol>
|
||||
@@ -346,6 +338,14 @@
|
||||
<delete assembly="umbraco" type="PartialViewMacroTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewsFolder">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialView.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="PartialViewTasks" />
|
||||
<delete assembly="umbraco" type="PartialViewTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
<nodeType alias="partialViewMacrosFolder">
|
||||
<header>Macro</header>
|
||||
<usercontrol>/Create/PartialViewMacro.ascx</usercontrol>
|
||||
|
||||
@@ -410,9 +410,9 @@
|
||||
<key alias="searchResults">Search results</key>
|
||||
</area>
|
||||
<area alias="graphicheadline">
|
||||
<key alias="backgroundcolor">Background color</key>
|
||||
<key alias="backgroundcolor">Background colour</key>
|
||||
<key alias="bold">Bold</key>
|
||||
<key alias="color">Text color</key>
|
||||
<key alias="color">Text colour</key>
|
||||
<key alias="font">Font</key>
|
||||
<key alias="text">Text</key>
|
||||
</area>
|
||||
@@ -702,7 +702,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
]]></key>
|
||||
</area>
|
||||
<area alias="colorpicker">
|
||||
<key alias="noColors">You have not configured any approved colors</key>
|
||||
<key alias="noColors">You have not configured any approved colours</key>
|
||||
</area>
|
||||
<area alias="relatedlinks">
|
||||
<key alias="addExternal">Add external link</key>
|
||||
|
||||
@@ -854,6 +854,36 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="quickGuide">Quick Guide to Umbraco template tags</key>
|
||||
<key alias="template">Template</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="insertControl">Insert control</key>
|
||||
<key alias="addRows">Add rows to your layout</key>
|
||||
<key alias="addElement"><![CDATA[To start, click the <i class="icon icon-add blue"></i> below and add your first element]]></key>
|
||||
|
||||
<key alias="gridLayouts">Grid layouts</key>
|
||||
<key alias="gridLayoutsDetail">Layouts are the overall work area for the grid editor, usually you only need one or two differnt layouts</key>
|
||||
<key alias="addGridLayout">Add grid layout</key>
|
||||
<key alias="addGridLayoutDetail">Adjust the layout by setting column widths and adding additional sections</key>
|
||||
|
||||
<key alias="rowConfigurations">Row configurations</key>
|
||||
<key alias="rowConfigurationsDetail">Rows are predefined cells arranged horizontally</key>
|
||||
<key alias="addRowConfiguration">Add row configuration</key>
|
||||
<key alias="addRowConfigurationDetail">Adjust the row by setting cell widths and adding additional cells</key>
|
||||
|
||||
<key alias="columns">Columns</key>
|
||||
<key alias="columnsDetails">Total combined number of columns in the grid layout</key>
|
||||
|
||||
<key alias="settings">Settings</key>
|
||||
<key alias="settingsDetails">Configure what settings editors can change</key>
|
||||
|
||||
|
||||
<key alias="styles">Styles</key>
|
||||
<key alias="stylesDetails">Configure what styling editors can change</key>
|
||||
|
||||
<key alias="settingDialogDetails">Settings will only save if the entered json configuration is valid</key>
|
||||
|
||||
<key alias="allowAllEditors">Allow all editors</key>
|
||||
<key alias="allowAllRowConfigurations">Allow all row configurations</key>
|
||||
</area>
|
||||
<area alias="templateEditor">
|
||||
<key alias="alternativeField">Alternative field</key>
|
||||
<key alias="alternativeText">Alternative Text</key>
|
||||
|
||||
@@ -35,15 +35,15 @@
|
||||
<key alias="toPublish">Enviar a publicación</key>
|
||||
<key alias="translate">Traducir</key>
|
||||
<key alias="update">Actualizar</key>
|
||||
<key alias="defaultValue">Default value</key>
|
||||
<key alias="defaultValue">Valor por defecto</key>
|
||||
</area>
|
||||
<area alias="assignDomain">
|
||||
<key alias="permissionDenied">Permission denied.</key>
|
||||
<key alias="permissionDenied">Permiso denegado.</key>
|
||||
<key alias="addNew">Añadir nuevo dominio</key>
|
||||
<key alias="remove">remove</key>
|
||||
<key alias="invalidNode">Invalid node.</key>
|
||||
<key alias="invalidDomain">Invalid domain format.</key>
|
||||
<key alias="duplicateDomain">Domain has already been assigned.</key>
|
||||
<key alias="remove">quitar</key>
|
||||
<key alias="invalidNode">Nodo no válido.</key>
|
||||
<key alias="invalidDomain">Formato de dominio no válido.</key>
|
||||
<key alias="duplicateDomain">Este dominio ya ha sido asignado.</key>
|
||||
<key alias="language">Language</key>
|
||||
<key alias="domain">Dominio</key>
|
||||
<key alias="domainCreated">El nuevo dominio %0% ha sido creado</key>
|
||||
@@ -52,15 +52,14 @@
|
||||
<key alias="domainUpdated">El dominio %0% ha sido actualizado</key>
|
||||
<key alias="orEdit">Editar dominios actuales</key>
|
||||
<key alias="domainHelp">
|
||||
<![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
|
||||
"https://www.example.com/".<br /><br />One-level paths in domains are supported, eg. "example.com/en". However, they
|
||||
should be avoided. Better use the culture setting above.]]>
|
||||
<![CDATA[p.ej.: "tudominio.com", "www.tudominio.com", "tudominio.com:8080" o
|
||||
"https://www.tudominio.com/".<br /><br />Los dominios de un nivel están soportados, por ej. "example.com/en". De todas formas deberían de evitarse. Mejor usar la configuración cultural especificada arriba.]]>
|
||||
</key>
|
||||
<key alias="inherit">Inherit</key>
|
||||
<key alias="setLanguage">Culture</key>
|
||||
<key alias="inherit">Heredar</key>
|
||||
<key alias="setLanguage">Cultura</key>
|
||||
<key alias="setLanguageHelp">
|
||||
<![CDATA[Set the culture for nodes below the current node,<br /> or inherit culture from parent nodes. Will also apply<br />
|
||||
to the current node, unless a domain below applies too.]]>
|
||||
<![CDATA[Configura la cultura para los nodos por debajo del nodo actual,<br /> o hereda la cultura de los nodos padres. También se aplicará<br />
|
||||
para el nodo actual, a menos que un dominio por debajo lo aplique también.]]>
|
||||
</key>
|
||||
<key alias="setDomains">Domains</key>
|
||||
</area>
|
||||
@@ -68,9 +67,9 @@
|
||||
<key alias="atViewingFor">Visualización de</key>
|
||||
</area>
|
||||
<area alias="buttons">
|
||||
<key alias="select">Select</key>
|
||||
<key alias="selectCurrentFolder">Select current folder</key>
|
||||
<key alias="somethingElse">Do something else</key>
|
||||
<key alias="select">Seleccionar</key>
|
||||
<key alias="selectCurrentFolder">Selecciona la carpeta actual</key>
|
||||
<key alias="somethingElse">Hacer otra cosa</key>
|
||||
<key alias="bold">Negrita</key>
|
||||
<key alias="deindent">Cancelar Sangría del Párrafo </key>
|
||||
<key alias="formFieldInsert">Insertar campo de formulario</key>
|
||||
@@ -92,30 +91,30 @@
|
||||
<key alias="saveAndPublish">Guardar y publicar</key>
|
||||
<key alias="saveToPublish">Guardar y enviar para aprobación</key>
|
||||
<key alias="showPage">Previsualizar</key>
|
||||
<key alias="showPageDisabled">Preview is disabled because there's no template assigned</key>
|
||||
<key alias="showPageDisabled">La previsualización está deshabilitada porque no hay ninguna plantilla asignada</key>
|
||||
<key alias="styleChoose">Elegir estilo</key>
|
||||
<key alias="styleShow">Mostrar estilos</key>
|
||||
<key alias="tableInsert">Insertar tabla</key>
|
||||
</area>
|
||||
<area alias="changeDocType">
|
||||
<key alias="changeDocTypeInstruction">To change the document type for the selected content, first select from the list of valid types for this location.</key>
|
||||
<key alias="changeDocTypeInstruction2">Then confirm and/or amend the mapping of properties from the current type to the new, and click Save.</key>
|
||||
<key alias="contentRepublished">The content has been re-published.</key>
|
||||
<key alias="currentProperty">Current Property</key>
|
||||
<key alias="currentType">Current type</key>
|
||||
<key alias="docTypeCannotBeChanged">The document type cannot be changed, as there are no alternatives valid for this location.</key>
|
||||
<key alias="docTypeChanged">Document Type Changed</key>
|
||||
<key alias="mapProperties">Map Properties</key>
|
||||
<key alias="mapToProperty">Map to Property</key>
|
||||
<key alias="newTemplate">New Template</key>
|
||||
<key alias="newType">New Type</key>
|
||||
<key alias="none">none</key>
|
||||
<key alias="selectedContent">Content</key>
|
||||
<key alias="selectNewDocType">Select New Document Type</key>
|
||||
<key alias="successMessage">The document type of the selected content has been successfully changed to [new type] and the following properties mapped:</key>
|
||||
<key alias="to">to</key>
|
||||
<key alias="validationErrorPropertyWithMoreThanOneMapping">Could not complete property mapping as one or more properties have more than one mapping defined.</key>
|
||||
<key alias="validDocTypesNote">Only alternate types valid for the current location are displayed.</key>
|
||||
<key alias="changeDocTypeInstruction">Para cambiar el tipo de documento al contenido seleccionado, primero selecciona uno de la lista de tipos válidos.</key>
|
||||
<key alias="changeDocTypeInstruction2">Entonces confirma el mapeo de propiedades del tipo actual al nuevo y haz click en Guardar.</key>
|
||||
<key alias="contentRepublished">El contenido se ha vuelto a publicar.</key>
|
||||
<key alias="currentProperty">Propiedad actual</key>
|
||||
<key alias="currentType">Tipo actual</key>
|
||||
<key alias="docTypeCannotBeChanged">El tipo de contenido no se puede cambiar, porque no hay alternativas válidas para este contenido.</key>
|
||||
<key alias="docTypeChanged">Tipo de documento cambiado</key>
|
||||
<key alias="mapProperties">Mapeo de propiedades</key>
|
||||
<key alias="mapToProperty">Mapea a la propiedad</key>
|
||||
<key alias="newTemplate">Nueva plantilla</key>
|
||||
<key alias="newType">Nuevo tipo</key>
|
||||
<key alias="none">ninguno</key>
|
||||
<key alias="selectedContent">Contenido</key>
|
||||
<key alias="selectNewDocType">Selecciona un nuevo Tipo de Documento</key>
|
||||
<key alias="successMessage">El tipo de documento del contenido seleccionado ha sido cambiado correctamente a [new type] y las siguientes propiedades mapeadas:</key>
|
||||
<key alias="to">a</key>
|
||||
<key alias="validationErrorPropertyWithMoreThanOneMapping">No se ha podido completar el mapeo de propiedades porque uno o más propiedades tienen más de un mapeo definido.</key>
|
||||
<key alias="validDocTypesNote">Solo se muestran otros tipos válidos para el contenido actual.</key>
|
||||
</area>
|
||||
<area alias="content">
|
||||
<key alias="about">Acerca de</key>
|
||||
@@ -142,7 +141,7 @@
|
||||
<key alias="nodeName">Título de la página</key>
|
||||
<key alias="otherElements">Propiedades</key>
|
||||
<key alias="parentNotPublished">Este documento ha sido publicado pero no es visible porque el padre '%0%' no esta publicado</key>
|
||||
<key alias="parentNotPublishedAnomaly">Oops: this document is published but is not in the cache (internal error)</key>
|
||||
<key alias="parentNotPublishedAnomaly">Upss: este documento está publicado pero no está en la caché (error interno)</key>
|
||||
<key alias="publish">Publicar</key>
|
||||
<key alias="publishStatus">Estado de la Publicación</key>
|
||||
<key alias="releaseDate">Publicar el</key>
|
||||
@@ -158,21 +157,21 @@
|
||||
<key alias="updateDateDesc" version="7.0">Fecha/hora este documento fue modificado</key>
|
||||
<key alias="uploadClear">Eliminar archivo</key>
|
||||
<key alias="urls">Vínculo al documento</key>
|
||||
<key alias="memberof">Member of group(s)</key>
|
||||
<key alias="notmemberof">Not a member of group(s)</key>
|
||||
<key alias="childItems" version="7.0">Child items</key>
|
||||
<key alias="memberof">Miembro de grupo(s)</key>
|
||||
<key alias="notmemberof">No es miembreo de grupo(s)</key>
|
||||
<key alias="childItems" version="7.0">Nodos hijo</key>
|
||||
<key alias="target" version="7.0">Target</key>
|
||||
</area>
|
||||
<area alias="media">
|
||||
<key alias="clickToUpload">Click to upload</key>
|
||||
<key alias="dropFilesHere">Drop your files here...</key>
|
||||
<key alias="clickToUpload">Haz click para subir archivos</key>
|
||||
<key alias="dropFilesHere">Arrastra los archivos aquí...</key>
|
||||
</area>
|
||||
<area alias="create">
|
||||
<key alias="chooseNode">¿Dónde quieres crear el nuevo %0%</key>
|
||||
<key alias="createUnder">Crear debajo de</key>
|
||||
<key alias="updateData">Elije un tipo y un título</key>
|
||||
<key alias="noDocumentTypes" version="7.0"><![CDATA[There are no allowed document types available. You must enable these in the settings section under <strong>"document types"</strong>.]]></key>
|
||||
<key alias="noMediaTypes" version="7.0"><![CDATA[There are no allowed media types available. You must enable these in the settings section under <strong>"media types"</strong>.]]></key>
|
||||
<key alias="noDocumentTypes" version="7.0"><![CDATA[No hay disponibles tipos de documentos permitidos. Debes habilitarlos en la sección "Ajustes" en <strong>"Tipos de documentos"</strong>.]]></key>
|
||||
<key alias="noMediaTypes" version="7.0"><![CDATA[No hay disponibles tipos de medios permitidos. Debes habilitarlos en la sección "Ajustes" en <strong>"Tipos de medios"</strong>.]]></key>
|
||||
</area>
|
||||
<area alias="dashboard">
|
||||
<key alias="browser">Navega en tu sitio Web</key>
|
||||
@@ -235,23 +234,23 @@
|
||||
]]></key>
|
||||
</area>
|
||||
<area alias="placeholders">
|
||||
<key alias="username">Introduzca su nombre de usuario</key>
|
||||
<key alias="password">Introduzca su contraseña</key>
|
||||
<key alias="nameentity">Nombre de %0%...</key>
|
||||
<key alias="entername">Introduzca un nombre ...</key>
|
||||
<key alias="search">Buscar ...</key>
|
||||
<key alias="filter">Filtrar ...</key>
|
||||
<key alias="username">Escribe tu nombre de usuario</key>
|
||||
<key alias="password">Escribe tu contraseña</key>
|
||||
<key alias="nameentity">Nombre del %0%...</key>
|
||||
<key alias="entername">Escribe un nombre...</key>
|
||||
<key alias="search">Escribe tu búsqueda...</key>
|
||||
<key alias="filter">Escribe para filtrar resultados...</key>
|
||||
</area>
|
||||
<area alias="editcontenttype">
|
||||
<key alias="allowedchildnodetypes">Tipos de nodos hijos permitidos</key>
|
||||
<key alias="contenttypecompositions">Document Type Compositions</key>
|
||||
<key alias="contenttypecompositions">Composiciones de Tipo de Documento</key>
|
||||
<key alias="create">Crear</key>
|
||||
<key alias="deletetab">Borrar pestaña</key>
|
||||
<key alias="description">Descripción</key>
|
||||
<key alias="newtab">Nueva pestaña</key>
|
||||
<key alias="tab">Pestaña</key>
|
||||
<key alias="thumbnail">Miniatura</key>
|
||||
<key alias="hasListView">Enable list view</key>
|
||||
<key alias="hasListView">Permitir vista de listado</key>
|
||||
</area>
|
||||
<area alias="editdatatype">
|
||||
<key alias="addPrevalue">añadir prevalor</key>
|
||||
@@ -450,8 +449,7 @@
|
||||
<key alias="runwayInstalledText"><![CDATA[Tienes puestos los cimientos. Selecciona los módulos que desees instalar sobre ellos.<br /> Esta es nuestra lista de módulos recomendados, selecciona los que desees instalar, o mira la <a href="#" onclick="toggleModules(); return false;" id="toggleModuleList">lista completa de módulos</a> ]]></key>
|
||||
<key alias="runwayOnlyProUsers">Sólo recomendado para usuarios expertos</key>
|
||||
<key alias="runwaySimpleSite">Quiero empezar con un sitio web sencillo</key>
|
||||
<key alias="runwaySimpleSiteText"><![CDATA[<p> "Runway" es un sitio web sencillo que contiene unos tipos de documentos y plantillas básicos. El instalador puede configurar Runway por ti de forma automática, pero fácilmente puedes editarlo, extenderlo o eliminarlo. No es necesario y puedes usar Umbrao perfectamente sin él. Sin embargo, Runway ofrece unos cimientos sencillos basados en buenas prácticas para iniciarte más rápido que nunca. Si eliges instalar Runway, puedes seleccionar bloques de construcción básicos llamados Módulos de Runway de forma opcional para realzar tus páginas de Runway. </> <small> <em>Incluido con Runway:</em> Página de inicio, página de Cómo empezar, página de Instalación de módulos.<br /> <em>Módulos opcionales:</em> Navegación superior, Mapa del sitio, Contacto, Galería. </small>
|
||||
However, Runway offers an easy foundation based on best practices to get you started faster than ever. If you choose to install Runway, you can optionally select basic building blocks called Runway Modules to enhance your Runway pages. </p> <small> <em>Included with Runway:</em> Home page, Getting Started page, Installing Modules page.<br /> <em>Optional Modules:</em> Top Navigation, Sitemap, Contact, Gallery. </small> ]]></key>
|
||||
<key alias="runwaySimpleSiteText"><![CDATA[<p> "Runway" es un sitio web sencillo que contiene unos tipos de documentos y plantillas básicos. El instalador puede configurar Runway por ti de forma automática, pero fácilmente puedes editarlo, extenderlo o eliminarlo. No es necesario y puedes usar Umbrao perfectamente sin él. Sin embargo, Runway ofrece unos cimientos sencillos basados en buenas prácticas para iniciarte más rápido que nunca. Si eliges instalar Runway, puedes seleccionar bloques de construcción básicos llamados Módulos de Runway de forma opcional para realzar tus páginas de Runway. </> <small> <em>Incluido con Runway:</em> Página de inicio, página de Cómo empezar, página de Instalación de módulos.<br /> <em>Módulos opcionales:</em> Navegación superior, Mapa del sitio, Contacto, Galería. </small> ]]></key>
|
||||
<key alias="runwayWhatIsRunway">¿Qué es Runway?</key>
|
||||
<key alias="step1">Paso 1 de 5. Aceptar los términos de la licencia</key>
|
||||
<key alias="step2">Paso 2 de 5. Configuración de la base de datos</key>
|
||||
@@ -480,15 +478,15 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="renewSession">Renovar su sessión para guardar sus cambios</key>
|
||||
</area>
|
||||
<area alias="login">
|
||||
<key alias="greeting0">Happy super Sunday</key>
|
||||
<key alias="greeting1">Happy manic Monday </key>
|
||||
<key alias="greeting2">Happy tubular Tuesday</key>
|
||||
<key alias="greeting3">Happy wonderful Wednesday</key>
|
||||
<key alias="greeting4">Happy thunderous Thursday</key>
|
||||
<key alias="greeting5">Happy funky Friday</key>
|
||||
<key alias="greeting6">Happy Caturday</key>
|
||||
<key alias="instruction">Log in below</key>
|
||||
<key alias="timeout">Session timed out</key>
|
||||
<key alias="greeting0">Feliz super domingo</key>
|
||||
<key alias="greeting1">Feliz lunes</key>
|
||||
<key alias="greeting2">Tremendo martes</key>
|
||||
<key alias="greeting3">Maravilloso miércoles</key>
|
||||
<key alias="greeting4">Fantástico jueves</key>
|
||||
<key alias="greeting5">¡Ya es viernes!</key>
|
||||
<key alias="greeting6">Resplandeciente sábado</key>
|
||||
<key alias="instruction">Iniciar sesión</key>
|
||||
<key alias="timeout">La sesión ha caducado</key>
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.com" style="text-decoration: none" target="_blank">umbraco.com</a></p> ]]></key>
|
||||
</area>
|
||||
|
||||
@@ -628,6 +626,10 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="tab">Pestaña</key>
|
||||
<key alias="tabname">Nombre de la pestaña</key>
|
||||
<key alias="tabs">Pestañas</key>
|
||||
<key alias="contentTypeEnabled">Tipo de Contenido Maestro activado</key>
|
||||
<key alias="contentTypeUses">Este Tipo de Contenido usa</key>
|
||||
<key alias="asAContentMasterType">como Tipo de Contenido Maestro. Las pestañas para los Tipos de Contenido Maestros no se muestran y solo se pueden modificar desde el Tipo de Contenido Maestro</key>
|
||||
<key alias="noPropertiesDefinedOnTab">No existen propiedades para esta pestaña. Haga clic en el enlace "añadir nueva propiedad" para crear una nueva propiedad.</key>
|
||||
<key alias="masterDocumentType">Tipo de documento Maestro</key>
|
||||
<key alias="createMatchingTemplate">Crear template correspondiente</key>
|
||||
</area>
|
||||
@@ -842,8 +844,8 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="usertype">Tipo de usuario</key>
|
||||
<key alias="userTypes">Tipos de usuarios</key>
|
||||
<key alias="writer">Redactor</key>
|
||||
<key alias="yourProfile" version="7.0">Your profile</key>
|
||||
<key alias="yourHistory" version="7.0">Your recent history</key>
|
||||
<key alias="sessionExpires" version="7.0">Session expires in</key>
|
||||
<key alias="yourProfile" version="7.0">Tu perfil</key>
|
||||
<key alias="yourHistory" version="7.0">Tu historial reciente</key>
|
||||
<key alias="sessionExpires" version="7.0">La sesión caduca en</key>
|
||||
</area>
|
||||
</language>
|
||||
@@ -233,10 +233,6 @@
|
||||
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
@@ -261,6 +257,12 @@
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
</dependentAssembly>
|
||||
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
|
||||
@@ -84,15 +84,9 @@ namespace Umbraco.Web.Install.Controllers
|
||||
|
||||
public IEnumerable<Package> GetPackages()
|
||||
{
|
||||
var r = new org.umbraco.our.Repository();
|
||||
var modules = r.Modules();
|
||||
|
||||
return modules.Select(package => new Package()
|
||||
{
|
||||
Id = package.RepoGuid,
|
||||
Name = package.Text,
|
||||
Thumbnail = package.Thumbnail
|
||||
});
|
||||
var installHelper = new InstallHelper(UmbracoContext);
|
||||
var starterKits = installHelper.GetStarterKits();
|
||||
return starterKits;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Web;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Web.UI;
|
||||
@@ -11,6 +12,7 @@ using umbraco.BusinessLogic;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Web.Install.InstallSteps;
|
||||
using Umbraco.Web.Install.Models;
|
||||
@@ -39,7 +41,7 @@ namespace Umbraco.Web.Install
|
||||
public IEnumerable<InstallSetupStep> GetAllSteps()
|
||||
{
|
||||
return new List<InstallSetupStep>
|
||||
{
|
||||
{
|
||||
new NewInstallStep(_umbContext.Application),
|
||||
new UpgradeStep(),
|
||||
new FilePermissionsStep(),
|
||||
@@ -85,12 +87,12 @@ namespace Umbraco.Web.Install
|
||||
{
|
||||
Directory.Move(IOHelper.MapPath(SystemDirectories.Install), IOHelper.MapPath("~/app_data/temp/install_backup"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Directory.Exists(IOHelper.MapPath("~/Areas/UmbracoInstall")))
|
||||
{
|
||||
{
|
||||
Directory.Delete(IOHelper.MapPath("~/Areas/UmbracoInstall"), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void InstallStatus(bool isCompleted, string errorMsg)
|
||||
@@ -165,7 +167,9 @@ namespace Umbraco.Web.Install
|
||||
if (result == 1)
|
||||
{
|
||||
//the user has not been configured
|
||||
return true;
|
||||
//this is always true on UaaS, need to check if there's multiple users too
|
||||
var usersResult = _umbContext.Application.DatabaseContext.Database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoUser");
|
||||
return usersResult == 1;
|
||||
}
|
||||
|
||||
// //check if there are any content types configured, if there isn't then we will consider this a new install
|
||||
@@ -182,5 +186,29 @@ namespace Umbraco.Web.Install
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<Package> GetStarterKits()
|
||||
{
|
||||
var packages = new List<Package>();
|
||||
|
||||
try
|
||||
{
|
||||
var requestUri = string.Format("http://our.umbraco.org/webapi/StarterKit/Get/?umbracoVersion={0}",
|
||||
UmbracoVersion.Current);
|
||||
|
||||
using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri))
|
||||
using (var httpClient = new HttpClient())
|
||||
using (var response = httpClient.SendAsync(request).Result)
|
||||
{
|
||||
packages = response.Content.ReadAsAsync<IEnumerable<Package>>().Result.ToList();
|
||||
}
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
LogHelper.Error<InstallHelper>("Could not download list of available starter kits", ex);
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,16 +21,17 @@ namespace Umbraco.Web.Install.InstallSteps
|
||||
|
||||
private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66";
|
||||
|
||||
//adding a package guid hardcoded, so we can change the sent package remotely, currently this just points to txt kit
|
||||
//but a future starterkit will be inserted under the same guid on our.
|
||||
private const string PackageGuid = "69E44BEB-15FF-4CEE-8B64-0A7DAE498657";
|
||||
|
||||
public override InstallSetupResult Execute(Guid? starterKitId)
|
||||
{
|
||||
//if there is no value assigned then use the default starter kit
|
||||
if (starterKitId.HasValue == false)
|
||||
{
|
||||
starterKitId = Guid.Parse(PackageGuid);
|
||||
var installHelper = new InstallHelper(UmbracoContext.Current);
|
||||
var starterKits = installHelper.GetStarterKits().FirstOrDefault();
|
||||
if (starterKits != null)
|
||||
starterKitId = starterKits.Id;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
else if (starterKitId.Value == Guid.Empty)
|
||||
{
|
||||
@@ -57,7 +58,7 @@ namespace Umbraco.Web.Install.InstallSteps
|
||||
}
|
||||
if (repo.HasConnection() == false)
|
||||
{
|
||||
throw new InstallException("Cannot connect to repository");
|
||||
throw new InstallException("Cannot connect to repository");
|
||||
}
|
||||
var installer = new Installer();
|
||||
|
||||
@@ -76,7 +77,7 @@ namespace Umbraco.Web.Install.InstallSteps
|
||||
var installer = new Installer();
|
||||
installer.LoadConfig(packageFile);
|
||||
installer.InstallFiles(manifestId, packageFile);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override string View
|
||||
|
||||
@@ -223,9 +223,13 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
json = JObject.Parse((string)p.Value);
|
||||
}
|
||||
catch (JsonException ex)
|
||||
catch (JsonException)
|
||||
{
|
||||
LogHelper.Error<ImageCropperPropertyEditor>("Could not parse the value into a JSON structure! Value: " + p.Value, ex);
|
||||
//note: we are swallowing this exception because in some cases a normal string/non json value will be passed in which will just be the
|
||||
// file path like /media/23454/hello.jpg
|
||||
// This will happen everytime an image is uploaded via the folder browser and we don't really want to pollute the log since it's not actually
|
||||
// a problem and we take care of this below.
|
||||
// see: http://issues.umbraco.org/issue/U4-4756
|
||||
}
|
||||
if (json != null && json["src"] != null)
|
||||
{
|
||||
|
||||
@@ -415,7 +415,7 @@ namespace Umbraco.Web.Security
|
||||
if (member != null)
|
||||
{
|
||||
var propValue = member.Properties[prop.Alias];
|
||||
if (propValue != null)
|
||||
if (propValue != null && propValue.Value != null)
|
||||
{
|
||||
value = propValue.Value.ToString();
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
private string _defaultMemberTypeAlias = "Member";
|
||||
private volatile bool _hasDefaultMember = false;
|
||||
private static readonly object Locker = new object();
|
||||
private bool _providerKeyAsGuid = false;
|
||||
|
||||
public override string ProviderName
|
||||
{
|
||||
@@ -58,7 +59,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
|
||||
protected override MembershipUser ConvertToMembershipUser(IMember entity)
|
||||
{
|
||||
return entity.AsConcreteMembershipUser(Name);
|
||||
return entity.AsConcreteMembershipUser(Name, _providerKeyAsGuid);
|
||||
}
|
||||
|
||||
public string LockPropertyTypeAlias { get; private set; }
|
||||
@@ -85,6 +86,15 @@ namespace Umbraco.Web.Security.Providers
|
||||
}
|
||||
_hasDefaultMember = true;
|
||||
}
|
||||
|
||||
//devs can configure the provider user key to be a guid if they want, by default it is int
|
||||
if (config["providerKeyType"] != null)
|
||||
{
|
||||
if (config["providerKeyType"] == "guid")
|
||||
{
|
||||
_providerKeyAsGuid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string DefaultMemberTypeAlias
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
protected override MembershipUser ConvertToMembershipUser(IUser entity)
|
||||
{
|
||||
//the provider user key is always the int id
|
||||
return entity.AsConcreteMembershipUser(Name);
|
||||
return entity.AsConcreteMembershipUser(Name, true);
|
||||
}
|
||||
|
||||
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
|
||||
|
||||
@@ -500,15 +500,18 @@ namespace umbraco
|
||||
() => GetMediaDo(MediaId, Deep));
|
||||
|
||||
if (xml != null)
|
||||
{
|
||||
return FromXElement(xml, xml.Attribute("nodeTypeAlias").Value);
|
||||
{
|
||||
//returning the root element of the Media item fixes the problem
|
||||
return xml.CreateNavigator().Select("/");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var xml = GetMediaDo(MediaId, Deep);
|
||||
return FromXElement(xml, xml.Attribute("nodeTypeAlias").Value);
|
||||
|
||||
//returning the root element of the Media item fixes the problem
|
||||
return xml.CreateNavigator().Select("/");
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
@@ -536,15 +539,6 @@ namespace umbraco
|
||||
return serialized;
|
||||
}
|
||||
|
||||
private static XPathNodeIterator FromXElement(XNode xml, string mediaContentType)
|
||||
{
|
||||
var xp = xml.CreateNavigator();
|
||||
var xpath = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema
|
||||
? "/node"
|
||||
: String.Format("/{0}", Casing.SafeAliasWithForcingCheck(mediaContentType));
|
||||
return xp.Select(xpath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a member as an xml object
|
||||
/// </summary>
|
||||
|
||||
+80
-50
@@ -16,6 +16,7 @@ using System.Web.UI.WebControls;
|
||||
using ClientDependency.Core;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Strings;
|
||||
@@ -296,6 +297,8 @@ namespace umbraco.controls
|
||||
IconType = BasePage.speechBubbleIcon.success
|
||||
}, _contentType.Alias, _contentType.Text, txtAlias.Text, txtName.Text, _contentType.PropertyTypes.Select(x => x.Alias).ToArray());
|
||||
|
||||
var isMediaType = Request.Path.ToLowerInvariant().Contains("editmediatype.aspx");
|
||||
|
||||
//Add the async operation to the page
|
||||
//NOTE: Must pass in a null and do not pass in a true to the 'executeInParallel', this is changed in .net 4.5 for the better, otherwise you'll get a ysod.
|
||||
Page.RegisterAsyncTask(new PageAsyncTask(BeginAsyncSaveOperation, EndAsyncSaveOperation, null, state));
|
||||
@@ -306,7 +309,7 @@ namespace umbraco.controls
|
||||
Trace.Write("ContentTypeControlNew", "executing task");
|
||||
|
||||
//we need to re-set the UmbracoContext since it will be nulled and our cache handlers need it
|
||||
//global::Umbraco.Web.UmbracoContext.Current = asyncState.UmbracoContext;
|
||||
global::Umbraco.Web.UmbracoContext.Current = asyncState.UmbracoContext;
|
||||
|
||||
_contentType.ContentTypeItem.Name = txtName.Text;
|
||||
_contentType.ContentTypeItem.Alias = txtAlias.Text; // raw, contentType.Alias takes care of it
|
||||
@@ -320,47 +323,73 @@ namespace umbraco.controls
|
||||
var ids = SaveAllowedChildTypes();
|
||||
_contentType.ContentTypeItem.AllowedContentTypes = ids.Select(x => new ContentTypeSort {Id = new Lazy<int>(() => x), SortOrder = i++});
|
||||
|
||||
//Saving ContentType Compositions
|
||||
var compositionIds = SaveCompositionContentTypes();
|
||||
var existingCompsitionIds = _contentType.ContentTypeItem.CompositionIds().ToList();
|
||||
if (compositionIds.Any())
|
||||
// figure out whether compositions are locked
|
||||
var allContentTypes = Request.Path.ToLowerInvariant().Contains("editmediatype.aspx")
|
||||
? ApplicationContext.Services.ContentTypeService.GetAllMediaTypes().Cast<IContentTypeComposition>().ToArray()
|
||||
: ApplicationContext.Services.ContentTypeService.GetAllContentTypes().Cast<IContentTypeComposition>().ToArray();
|
||||
var isUsing = allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == _contentType.Id)).ToArray();
|
||||
|
||||
// if compositions are locked, do nothing (leave them as they are)
|
||||
// else process the checkbox list and add/remove compositions accordingly
|
||||
|
||||
if (isUsing.Length == 0)
|
||||
{
|
||||
//Iterate ContentType Ids from the save-collection
|
||||
foreach (var compositionId in compositionIds)
|
||||
//Saving ContentType Compositions
|
||||
var compositionIds = SaveCompositionContentTypes();
|
||||
var existingCompsitionIds = _contentType.ContentTypeItem.CompositionIds().ToList();
|
||||
if (compositionIds.Any())
|
||||
{
|
||||
//If the compositionId is the Id of the current ContentType we skip it
|
||||
if(_contentType.Id.Equals(compositionId)) continue;
|
||||
// if some compositions were checked in the list, iterate over them
|
||||
foreach (var compositionId in compositionIds)
|
||||
{
|
||||
// ignore if it is the current content type
|
||||
if (_contentType.Id.Equals(compositionId)) continue;
|
||||
|
||||
//If the Id already exists we'll just skip it
|
||||
if (existingCompsitionIds.Any(x => x.Equals(compositionId))) continue;
|
||||
// ignore if it is already a composition of the content type
|
||||
if (existingCompsitionIds.Any(x => x.Equals(compositionId))) continue;
|
||||
|
||||
//New Ids will get added to the collection
|
||||
var compositionType = Services.ContentTypeService.GetContentType(compositionId);
|
||||
var added = _contentType.ContentTypeItem.AddContentType(compositionType);
|
||||
//TODO if added=false then return error message
|
||||
// add to the content type compositions
|
||||
var compositionType = isMediaType
|
||||
? Services.ContentTypeService.GetMediaType(compositionId).SafeCast<IContentTypeComposition>()
|
||||
: Services.ContentTypeService.GetContentType(compositionId).SafeCast<IContentTypeComposition>();
|
||||
try
|
||||
{
|
||||
//TODO if added=false then return error message
|
||||
var added = _contentType.ContentTypeItem.AddContentType(compositionType);
|
||||
}
|
||||
catch (InvalidCompositionException ex)
|
||||
{
|
||||
state.SaveArgs.IconType = BasePage.speechBubbleIcon.error;
|
||||
state.SaveArgs.Message = ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
// then iterate over removed = existing except checked
|
||||
var removeIds = existingCompsitionIds.Except(compositionIds);
|
||||
foreach (var removeId in removeIds)
|
||||
{
|
||||
// and remove from the content type composition
|
||||
var compositionType = isMediaType
|
||||
? Services.ContentTypeService.GetMediaType(removeId).SafeCast<IContentTypeComposition>()
|
||||
: Services.ContentTypeService.GetContentType(removeId).SafeCast<IContentTypeComposition>();
|
||||
var removed = _contentType.ContentTypeItem.RemoveContentType(compositionType.Alias);
|
||||
}
|
||||
}
|
||||
|
||||
//Iterate the set except of existing and new Ids
|
||||
var removeIds = existingCompsitionIds.Except(compositionIds);
|
||||
foreach (var removeId in removeIds)
|
||||
else if (existingCompsitionIds.Any())
|
||||
{
|
||||
//Remove ContentTypes that was deselected in the list
|
||||
var compositionType = Services.ContentTypeService.GetContentType(removeId);
|
||||
var removed = _contentType.ContentTypeItem.RemoveContentType(compositionType.Alias);
|
||||
// else none were checked - if the content type had compositions,
|
||||
// iterate over them all and remove them
|
||||
var removeIds = existingCompsitionIds.Except(compositionIds); // except here makes no sense?
|
||||
foreach (var removeId in removeIds)
|
||||
{
|
||||
// remove existing
|
||||
var compositionType = isMediaType
|
||||
? Services.ContentTypeService.GetMediaType(removeId).SafeCast<IContentTypeComposition>()
|
||||
: Services.ContentTypeService.GetContentType(removeId).SafeCast<IContentTypeComposition>();
|
||||
var removed = _contentType.ContentTypeItem.RemoveContentType(compositionType.Alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (existingCompsitionIds.Any())
|
||||
{
|
||||
//Iterate the set except of existing and new Ids
|
||||
var removeIds = existingCompsitionIds.Except(compositionIds);
|
||||
foreach (var removeId in removeIds)
|
||||
{
|
||||
//Remove ContentTypes that was deselected in the list
|
||||
var compositionType = Services.ContentTypeService.GetContentType(removeId);
|
||||
var removed = _contentType.ContentTypeItem.RemoveContentType(compositionType.Alias);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var tabs = SaveTabs();
|
||||
foreach (var tab in tabs)
|
||||
@@ -406,6 +435,11 @@ namespace umbraco.controls
|
||||
state.SaveArgs.Message = ex.Message;
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state.SaveArgs.IconType = BasePage.speechBubbleIcon.error;
|
||||
state.SaveArgs.Message = ex.Message;
|
||||
}
|
||||
|
||||
Trace.Write("ContentTypeControlNew", "task completing");
|
||||
};
|
||||
@@ -676,7 +710,9 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
|
||||
if (Page.IsPostBack == false)
|
||||
{
|
||||
var allContentTypes = ApplicationContext.Services.ContentTypeService.GetAllContentTypes().ToArray();
|
||||
var allContentTypes = Request.Path.ToLowerInvariant().Contains("editmediatype.aspx")
|
||||
? ApplicationContext.Services.ContentTypeService.GetAllMediaTypes().Cast<IContentTypeComposition>().ToArray()
|
||||
: ApplicationContext.Services.ContentTypeService.GetAllContentTypes().Cast<IContentTypeComposition>().ToArray();
|
||||
|
||||
// note: there are many sanity checks missing here and there ;-((
|
||||
// make sure once and for all
|
||||
@@ -695,7 +731,7 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
DualContentTypeCompositions.Value = "";
|
||||
|
||||
PlaceHolderContentTypeCompositions.Controls.Add(new Literal { Text = "<em>This content type is used as a parent and/or in "
|
||||
+ "a composition, and therefore cannot be composed itself.<br /><br />"
|
||||
+ "a composition, and therefore cannot be composed itself.<br /><br />Used by: "
|
||||
+ string.Join(", ", isUsing.Select(x => x.Name))
|
||||
+ "</em>" });
|
||||
}
|
||||
@@ -780,16 +816,10 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
|
||||
private int[] SaveCompositionContentTypes()
|
||||
{
|
||||
var tmp = new ArrayList();
|
||||
foreach (ListItem li in lstContentTypeCompositions.Items)
|
||||
{
|
||||
if (li.Selected)
|
||||
tmp.Add(int.Parse(li.Value));
|
||||
}
|
||||
var ids = new int[tmp.Count];
|
||||
for (int i = 0; i < tmp.Count; i++) ids[i] = (int)tmp[i];
|
||||
|
||||
return ids;
|
||||
return lstContentTypeCompositions.Items.Cast<ListItem>()
|
||||
.Where(x => x.Selected)
|
||||
.Select(x => int.Parse(x.Value))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -1052,7 +1082,7 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
|
||||
private string GetHtmlForNoPropertiesMessageListItem()
|
||||
{
|
||||
return @"<li class=""no-properties-on-tab"">" + ui.Text("settings", "noPropertiesDefinedOnTab") + "</li></ul>";
|
||||
return @"<li class=""no-properties-on-tab"">" + ui.Text("settings", "noPropertiesDefinedOnTab", Security.CurrentUser) + "</li></ul>";
|
||||
}
|
||||
|
||||
private void SavePropertyType(SaveClickEventArgs e, IContentTypeComposition contentTypeItem)
|
||||
@@ -1106,7 +1136,7 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Message = ui.Text("contentTypeDublicatePropertyType");
|
||||
e.Message = ui.Text("contentTypeDublicatePropertyType", Security.CurrentUser);
|
||||
e.IconType = BasePage.speechBubbleIcon.warning;
|
||||
}
|
||||
}
|
||||
@@ -1409,7 +1439,7 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
|
||||
LoadContentType();
|
||||
|
||||
var ea = new SaveClickEventArgs(ui.Text("contentTypeTabCreated"));
|
||||
var ea = new SaveClickEventArgs(ui.Text("contentTypeTabCreated", Security.CurrentUser));
|
||||
ea.IconType = BasePage.speechBubbleIcon.success;
|
||||
|
||||
RaiseBubbleEvent(new object(), ea);
|
||||
@@ -1448,7 +1478,7 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }});
|
||||
|
||||
LoadContentType();
|
||||
|
||||
var ea = new SaveClickEventArgs(ui.Text("contentTypeTabDeleted"));
|
||||
var ea = new SaveClickEventArgs(ui.Text("contentTypeTabDeleted", Security.CurrentUser));
|
||||
ea.IconType = BasePage.speechBubbleIcon.success;
|
||||
|
||||
RaiseBubbleEvent(new object(), ea);
|
||||
|
||||
@@ -24,13 +24,18 @@ namespace umbraco
|
||||
//NOTE: TypeID is the parent id!
|
||||
//NOTE: ParentID is aparently a flag to determine if we are to create a template! Hack much ?! :P
|
||||
var parentId = TypeID != 0 ? TypeID : -1;
|
||||
var contentType = parentId == -1
|
||||
? new ContentType(-1)
|
||||
: new ContentType(ApplicationContext.Current.Services.ContentTypeService.GetContentType(parentId));
|
||||
contentType.CreatorId = User.Id;
|
||||
|
||||
// when creating a content type, enforce PascalCase
|
||||
// preserve separator because contentType.Alias will re-alias it
|
||||
contentType.Alias = Alias.ToCleanString(CleanStringType.Alias | CleanStringType.PascalCase, ' ');
|
||||
var cleanAlias = Alias.ToCleanString(CleanStringType.Alias | CleanStringType.PascalCase, ' ');
|
||||
|
||||
var contentType = parentId == -1
|
||||
? new ContentType(-1)
|
||||
: new ContentType(ApplicationContext.Current.Services.ContentTypeService.GetContentType(parentId), cleanAlias);
|
||||
|
||||
contentType.CreatorId = User.Id;
|
||||
|
||||
contentType.Alias = cleanAlias;
|
||||
contentType.Name = Alias.Replace("'", "''");
|
||||
contentType.Icon = ".sprTreeFolder";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user