diff --git a/src/Umbraco.Core/Constants-ObjectTypes.cs b/src/Umbraco.Core/Constants-ObjectTypes.cs
index 81bd66928d..4f225aaccb 100644
--- a/src/Umbraco.Core/Constants-ObjectTypes.cs
+++ b/src/Umbraco.Core/Constants-ObjectTypes.cs
@@ -9,6 +9,16 @@ namespace Umbraco.Core
///
public static class ObjectTypes
{
+ ///
+ /// Guid for a doc type container
+ ///
+ public const string DocumentTypeContainer = "2F7A2769-6B0B-4468-90DD-AF42D64F7F16";
+
+ ///
+ /// Guid for a doc type container
+ ///
+ public const string MediaTypeContainer = "42AEF799-B288-4744-9B10-BE144B73CDC4";
+
///
/// Guid for a Content Item object.
///
diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs
index e9d4451314..239792bf08 100644
--- a/src/Umbraco.Core/Models/PropertyType.cs
+++ b/src/Umbraco.Core/Models/PropertyType.cs
@@ -9,6 +9,7 @@ using Umbraco.Core.Strings;
namespace Umbraco.Core.Models
{
+
///
/// Defines the type of a object
///
diff --git a/src/Umbraco.Core/Models/UmbracoEntityExtensions.cs b/src/Umbraco.Core/Models/UmbracoEntityExtensions.cs
index edcc25ade8..987be2a276 100644
--- a/src/Umbraco.Core/Models/UmbracoEntityExtensions.cs
+++ b/src/Umbraco.Core/Models/UmbracoEntityExtensions.cs
@@ -11,6 +11,20 @@ namespace Umbraco.Core.Models
internal static class UmbracoEntityExtensions
{
+ public static bool HasChildren(this IUmbracoEntity entity)
+ {
+ if (entity.AdditionalData.ContainsKey("HasChildren"))
+ {
+ var convert = entity.AdditionalData["HasChildren"].TryConvertTo();
+ if (convert)
+ {
+ return convert.Result;
+ }
+ }
+ return false;
+ }
+
+
public static object GetAdditionalDataValueIgnoreCase(this IUmbracoEntity entity, string key, object defaultVal)
{
if (entity.AdditionalData.ContainsKeyIgnoreCase(key) == false) return defaultVal;
diff --git a/src/Umbraco.Core/Models/UmbracoObjectTypes.cs b/src/Umbraco.Core/Models/UmbracoObjectTypes.cs
index 37ad181682..8f9acbd057 100644
--- a/src/Umbraco.Core/Models/UmbracoObjectTypes.cs
+++ b/src/Umbraco.Core/Models/UmbracoObjectTypes.cs
@@ -109,6 +109,13 @@ namespace Umbraco.Core.Models
///
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.DataType, typeof(IDataTypeDefinition))]
[FriendlyName("Data Type")]
- DataType
+ DataType,
+
+ ///
+ /// Entity Container
+ ///
+ [UmbracoObjectTypeAttribute(Constants.ObjectTypes.DocumentTypeContainer)]
+ [FriendlyName("Document Type Container")]
+ DocumentTypeContainer
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs
index 8dba129d93..17f9afe258 100644
--- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs
@@ -33,6 +33,66 @@ namespace Umbraco.Core.Persistence.Repositories
{
}
+ ///
+ /// The container object type - used for organizing content types
+ ///
+ protected abstract Guid ContainerObjectTypeId { get; }
+
+ public Attempt CreateFolder(int parentId, string name, int userId)
+ {
+ name = name.Trim();
+
+ Mandate.ParameterNotNullOrEmpty(name, "name");
+
+ var exists = Database.FirstOrDefault(
+ new Sql().Select("*")
+ .From(SqlSyntax)
+ .Where(dto => dto.ParentId == parentId && dto.Text == name && dto.NodeObjectType == ContainerObjectTypeId));
+
+ if (exists != null)
+ {
+ return Attempt.Fail(exists.NodeId, new InvalidOperationException("A folder with the same name already exists"));
+ }
+
+ var level = 0;
+ var path = "-1";
+ if (parentId > -1)
+ {
+ var parent = Database.FirstOrDefault(
+ new Sql().Select("*")
+ .From(SqlSyntax)
+ .Where(dto => dto.NodeId == parentId && dto.NodeObjectType == ContainerObjectTypeId));
+
+ if (parent == null)
+ {
+ return Attempt.Fail(0, new NullReferenceException("No content type container found with parent id " + parentId));
+ }
+ level = parent.Level;
+ path = parent.Path;
+ }
+
+ var folder = new NodeDto
+ {
+ CreateDate = DateTime.Now,
+ Level = Convert.ToInt16(level + 1),
+ NodeObjectType = ContainerObjectTypeId,
+ ParentId = parentId,
+ Path = path,
+ SortOrder = 0,
+ Text = name,
+ Trashed = false,
+ UniqueId = Guid.NewGuid(),
+ UserId = userId
+ };
+
+ Database.Save(folder);
+ //update the path
+ folder.Path = folder.Path + "," + folder.NodeId;
+ Database.Save(folder);
+
+ return Attempt.Succeed(folder.NodeId);
+ }
+
///
/// Returns the content type ids that match the query
///
diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs
index 40679af854..4db21a5616 100644
--- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs
@@ -242,6 +242,12 @@ namespace Umbraco.Core.Persistence.Repositories
#endregion
-
+ ///
+ /// The container object type - used for organizing content types
+ ///
+ protected override Guid ContainerObjectTypeId
+ {
+ get { return new Guid(Constants.ObjectTypes.DocumentTypeContainer); }
+ }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentTypeRepository.cs
index e3ce084cf7..b612a9109d 100644
--- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentTypeRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentTypeRepository.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Querying;
@@ -18,5 +19,7 @@ namespace Umbraco.Core.Persistence.Repositories
///
///
IEnumerable GetAllPropertyTypeAliases();
+
+ Attempt CreateFolder(int parentId, string name, int userId);
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs
index cc51fd6e7c..13cdab400e 100644
--- a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs
@@ -181,5 +181,13 @@ namespace Umbraco.Core.Persistence.Repositories
}
#endregion
+
+ ///
+ /// The container object type - used for organizing content types
+ ///
+ protected override Guid ContainerObjectTypeId
+ {
+ get { throw new NotImplementedException(); }
+ }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs
index bb6099a206..d9c8e815be 100644
--- a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs
@@ -241,6 +241,14 @@ namespace Umbraco.Core.Persistence.Repositories
#endregion
+ ///
+ /// The container object type - used for organizing content types
+ ///
+ protected override Guid ContainerObjectTypeId
+ {
+ get { throw new NotImplementedException(); }
+ }
+
///
/// Override so we can specify explicit db type's on any property types that are built-in.
///
diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBase.cs b/src/Umbraco.Core/Services/ContentTypeServiceBase.cs
index d5ebaabdb6..d22ba90d5d 100644
--- a/src/Umbraco.Core/Services/ContentTypeServiceBase.cs
+++ b/src/Umbraco.Core/Services/ContentTypeServiceBase.cs
@@ -15,6 +15,14 @@ namespace Umbraco.Core.Services
{
}
+ public Attempt CreateFolder(int parentId, string name, int userId = 0)
+ {
+ using (var repo = RepositoryFactory.CreateContentTypeRepository(UowProvider.GetUnitOfWork()))
+ {
+ return repo.CreateFolder(parentId, name, userId);
+ }
+ }
+
///
/// This is called after an content type is saved and is used to update the content xml structures in the database
/// if they are required to be updated.
diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs
index 695d092bd4..1d249aa6d1 100644
--- a/src/Umbraco.Core/Services/EntityService.cs
+++ b/src/Umbraco.Core/Services/EntityService.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using Umbraco.Core.Cache;
using Umbraco.Core.CodeAnnotations;
using Umbraco.Core.Logging;
@@ -34,7 +35,28 @@ namespace Umbraco.Core.Services
{typeof (IMedia).FullName, new Tuple>(UmbracoObjectTypes.Media, mediaService.GetById)},
{typeof (IMediaType).FullName, new Tuple>(UmbracoObjectTypes.MediaType, contentTypeService1.GetMediaType)},
{typeof (IMember).FullName, new Tuple>(UmbracoObjectTypes.Member, memberService.GetById)},
- {typeof (IMemberType).FullName, new Tuple>(UmbracoObjectTypes.MemberType, memberTypeService.Get)}
+ {typeof (IMemberType).FullName, new Tuple>(UmbracoObjectTypes.MemberType, memberTypeService.Get)},
+ //{typeof (IUmbracoEntity).FullName, new Tuple>(UmbracoObjectTypes.EntityContainer, id =>
+ //{
+ // using (var uow = UowProvider.GetUnitOfWork())
+ // {
+ // var found = uow.Database.FirstOrDefault("SELECT * FROM umbracoNode WHERE id=@id", new { id = id });
+ // return found == null ? null : new UmbracoEntity(found.Trashed)
+ // {
+ // Id = found.NodeId,
+ // Name = found.Text,
+ // Key = found.UniqueId,
+ // SortOrder = found.SortOrder,
+ // Path = found.Path,
+ // NodeObjectTypeId = found.NodeObjectType.Value,
+ // CreateDate = found.CreateDate,
+ // CreatorId = found.UserId.Value,
+ // Level = found.Level,
+ // ParentId = found.ParentId
+ // };
+ // }
+
+ //})}
};
}
@@ -61,6 +83,7 @@ namespace Umbraco.Core.Services
case UmbracoObjectTypes.DocumentType:
case UmbracoObjectTypes.Member:
case UmbracoObjectTypes.DataType:
+ case UmbracoObjectTypes.DocumentTypeContainer:
return uow.Database.ExecuteScalar(new Sql().Select("id").From().Where(dto => dto.UniqueId == key));
case UmbracoObjectTypes.RecycleBin:
case UmbracoObjectTypes.Stylesheet:
diff --git a/src/Umbraco.Core/Services/IContentTypeService.cs b/src/Umbraco.Core/Services/IContentTypeService.cs
index 9e2d179bb0..a538840e36 100644
--- a/src/Umbraco.Core/Services/IContentTypeService.cs
+++ b/src/Umbraco.Core/Services/IContentTypeService.cs
@@ -10,6 +10,8 @@ namespace Umbraco.Core.Services
///
public interface IContentTypeService : IService
{
+ Attempt CreateFolder(int parentId, string name, int userId = 0);
+
///
/// Gets all property type aliases.
///
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
index 48e7030571..461e2800e7 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
@@ -139,6 +139,14 @@ function contentTypeResource($q, $http, umbRequestHelper) {
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostSave"), contentType),
'Failed to save data for content type id ' + contentType.id);
+ },
+
+ createFolder: function(parentId, name) {
+
+ return umbRequestHelper.resourcePromise(
+ $http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCreateFolder", { parentId: parentId, name: name })),
+ 'Failed to create a folder under parent id ' + parentId);
+
}
};
diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttype/create.html b/src/Umbraco.Web.UI.Client/src/views/documenttype/create.html
index ca31abb93c..b7c95d49c4 100644
--- a/src/Umbraco.Web.UI.Client/src/views/documenttype/create.html
+++ b/src/Umbraco.Web.UI.Client/src/views/documenttype/create.html
@@ -1,45 +1,51 @@
-
-
-
-
Create a page under {{currentNode.name}}
+
-
-
-
+
+
Create a page under {{currentNode.name}}
-
+
+
+
+
-
-
-
-
-
-
-
-