diff --git a/src/Umbraco.Web.UI/umbraco/js/umbraco.controllers.js b/src/Umbraco.Web.UI/umbraco/js/umbraco.controllers.js index 1e0990d61a..2a9598d9de 100644 --- a/src/Umbraco.Web.UI/umbraco/js/umbraco.controllers.js +++ b/src/Umbraco.Web.UI/umbraco/js/umbraco.controllers.js @@ -89,6 +89,7 @@ angular.module('umbraco').controller("NavigationController", $scope.ui.mode("default-hidenav"); }; + //SD: Pretty sure this is not used ?! function loadTree(section) { $scope.currentSection = section; @@ -268,8 +269,16 @@ angular.module("umbraco").controller("Umbraco.Common.LegacyController", function($scope, $routeParams){ $scope.legacyPath = decodeURI($routeParams.p); }); -angular.module('umbraco').controller("Umbraco.Editors.ContentCreateController", function ($scope, $routeParams,contentTypeFactory) { - $scope.allowedTypes = contentTypeFactory.getAllowedTypes($scope.currentNode.id); +angular.module('umbraco').controller("Umbraco.Editors.ContentCreateController", function ($scope, $routeParams, contentTypeResource) { + + //get the allowed content types and update the property when it resolves + contentTypeResource.getAllowedTypes($scope.currentNode.id) + .then(function (data) { + $scope.allowedTypes = data; + }, function (reason) { + alert(reason); + return; + }); }); angular.module("umbraco").controller("Umbraco.Editors.ContentEditController", function ($scope, $routeParams, contentFactory, notifications) { @@ -452,7 +461,7 @@ angular.module("umbraco").controller("Umbraco.Editors.GridController", function( }) }); angular.module("umbraco") - .controller("Umbraco.Editors.ListViewController", function ($rootScope, $scope, contentFactory, contentTypeFactory) { + .controller("Umbraco.Editors.ListViewController", function ($rootScope, $scope, contentFactory, contentTypeResource) { $scope.options = { take: 10, offset: 0, @@ -462,7 +471,15 @@ angular.module("umbraco") }; $scope.pagination = new Array(100); - $scope.listViewAllowedTypes = contentTypeFactory.getAllowedTypes($scope.content.id); + + //get the allowed content types and update the property when it resolves + contentTypeResource.getAllowedTypes($scope.content.id) + .then(function (data) { + $scope.listViewAllowedTypes = data; + }, function (reason) { + alert(reason); + return; + }); $scope.next = function(){ if($scope.options.offset < $scope.listViewResultSet.pages){ diff --git a/src/Umbraco.Web.UI/umbraco/js/umbraco.resources.js b/src/Umbraco.Web.UI/umbraco/js/umbraco.resources.js index 06e35ebbb4..7c5a210afc 100644 --- a/src/Umbraco.Web.UI/umbraco/js/umbraco.resources.js +++ b/src/Umbraco.Web.UI/umbraco/js/umbraco.resources.js @@ -9,9 +9,10 @@ define(['app', 'angular'], function (app, angular) { /** * @ngdoc factory - * @name umbraco.resources.trees.umbTreeResource + * @name umbraco.resources.treeResource + * @description Loads in data for trees **/ - function umbTreeResource($q, $http) { + function treeResource($q, $http) { /** internal method to get the tree app url */ function getTreeAppUrl(section) { @@ -61,8 +62,75 @@ define(['app', 'angular'], function (app, angular) { } }; } - angular.module('umbraco').factory('umbTreeResource', umbTreeResource); + angular.module('umbraco').factory('treeResource', treeResource); + /** + * @ngdoc factory + * @name umbraco.resources.contentTypeResource + * @description Loads in data for content types + **/ + function contentTypeResource($q, $http) { + + /** internal method to get the tree app url */ + function getChildContentTypesUrl(contentId) { + return Umbraco.Sys.ServerVariables.contentTypeApiBaseUrl + "GetAllowedChildrenForContent?contentId=" + contentId; + } + + return { + + //return a content type with a given ID + getContentType: function (id) { + + return { + name: "News Article", + alias: "newsArticle", + id: id, + tabs: [] + }; + + }, + //return all available types + all: function () { + return []; + }, + + //return children inheriting a given type + children: function (id) { + return []; + }, + + //return all content types a type inherits from + parents: function (id) { + return []; + }, + + //return all types allowed under given document + getAllowedTypes: function (contentId) { + + var deferred = $q.defer(); + + //go and get the tree data + $http.get(getChildContentTypesUrl(contentId)). + success(function (data, status, headers, config) { + deferred.resolve(data); + }). + error(function (data, status, headers, config) { + deferred.reject('Failed to retreive data for content id ' + contentId); + }); + + return deferred.promise; + + //OLD TEST DATA + //return [ + //{ name: "News Article", description: "Standard news article", alias: "newsArticle", id: 1234, cssClass: "file" }, + //{ name: "News Area", description: "Area to hold all news articles, there should be only one", alias: "newsArea", id: 1234, cssClass: "suitcase" }, + //{ name: "Employee", description: "Employee profile information page", alias: "employee", id: 1234, cssClass: "user" } + //]; + } + + }; + } + angular.module('umbraco.resources.contentType', []).factory('contentTypeResource', contentTypeResource); angular.module('umbraco.resources.content', []) @@ -204,47 +272,49 @@ define(['app', 'angular'], function (app, angular) { return factory; }); -angular.module('umbraco.resources.contentType', []) -.factory('contentTypeFactory', function () { - return { +//angular.module('umbraco.resources.contentType', []) +//.factory('contentTypeFactory', function () { +// return { - //return a content type with a given ID - getContentType: function(id){ +// //return a content type with a given ID +// getContentType: function(id){ - return { - name: "News Article", - alias: "newsArticle", - id: id, - tabs:[] - }; +// return { +// name: "News Article", +// alias: "newsArticle", +// id: id, +// tabs:[] +// }; - }, - //return all availabel types - all: function(){ - return []; - }, +// }, +// //return all available types +// all: function(){ +// return []; +// }, - //return children inheriting a given type - children: function(id){ - return []; - }, +// //return children inheriting a given type +// children: function(id){ +// return []; +// }, - //return all content types a type inherite from - parents: function(id){ - return []; - }, +// //return all content types a type inherits from +// parents: function(id){ +// return []; +// }, + +// //return all types allowed under given document +// getAllowedTypes: function(documentId){ +// return [ +// {name: "News Article", description: "Standard news article", alias: "newsArticle", id: 1234, cssClass:"file"}, +// {name: "News Area", description: "Area to hold all news articles, there should be only one", alias: "newsArea", id: 1234, cssClass:"suitcase"}, +// {name: "Employee", description: "Employee profile information page", alias: "employee", id: 1234, cssClass:"user"} +// ]; +// } + +// }; +//}); - //return all types allowed under given document - getAllowedTypes: function(documentId){ - return [ - {name: "News Article", description: "Standard news article", alias: "newsArticle", id: 1234, cssClass:"file"}, - {name: "News Area", description: "Area to hold all news articles, there should be only one", alias: "newsArea", id: 1234, cssClass:"suitcase"}, - {name: "Employee", description: "Employee profile information page", alias: "employee", id: 1234, cssClass:"user"} - ]; - } - }; -}); angular.module('umbraco.resources.localization', []) .factory('localizationFactory', function () { var localizationArray = []; diff --git a/src/Umbraco.Web.UI/umbraco/js/umbraco.services.js b/src/Umbraco.Web.UI/umbraco/js/umbraco.services.js index da4f69a35a..a723b60b2d 100644 --- a/src/Umbraco.Web.UI/umbraco/js/umbraco.services.js +++ b/src/Umbraco.Web.UI/umbraco/js/umbraco.services.js @@ -287,7 +287,7 @@ angular.module('umbraco.services.section', []) }); angular.module('umbraco.services.tree', []) -.factory('tree', function ($q, umbTreeResource) { +.factory('tree', function ($q, treeResource) { //implement this in local storage var treeArray = []; var currentSection = "content"; @@ -310,7 +310,7 @@ angular.module('umbraco.services.tree', []) return treeArray[cacheKey]; } - umbTreeResource.loadApplication(section) + treeResource.loadApplication(section) .then(function (data) { //this will be called once the tree app data has loaded var result = { @@ -475,7 +475,7 @@ angular.module('umbraco.services.tree', []) } var deferred = $q.defer(); - umbTreeResource.loadNodes(section, treeItem) + treeResource.loadNodes(section, treeItem) .then(function (data) { //now that we have the data, we need to add the childLevel property to each item for (var i = 0; i < data.length; i++) { diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 522afb57b2..9874cc9c54 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -48,7 +48,8 @@ namespace Umbraco.Web.Editors { {"umbracoPath", GlobalSettings.Path}, {"contentEditorApiBaseUrl", Url.GetUmbracoApiService("PostSaveContent").TrimEnd("PostSaveContent")}, - {"treeApplicationApiBaseUrl", Url.GetUmbracoApiService("GetTreeData").TrimEnd("GetTreeData")} + {"treeApplicationApiBaseUrl", Url.GetUmbracoApiService("GetTreeData").TrimEnd("GetTreeData")}, + {"contentTypeApiBaseUrl", Url.GetUmbracoApiService("GetAllowedChildrenForContent").TrimEnd("GetAllowedChildrenForContent")} }; return JavaScript(ServerVariablesParser.Parse(d)); diff --git a/src/Umbraco.Web/Editors/ContentEditorApiController.cs b/src/Umbraco.Web/Editors/ContentEditorApiController.cs index f292982556..8ca3164ae9 100644 --- a/src/Umbraco.Web/Editors/ContentEditorApiController.cs +++ b/src/Umbraco.Web/Editors/ContentEditorApiController.cs @@ -14,13 +14,12 @@ using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Editors { - /// /// The API controller used for editing content /// [PluginController("UmbracoEditors")] [ValidationFilter] - public class ContentEditorApiController : UmbracoApiController + public class ContentEditorApiController : UmbracoAuthorizedApiController { private readonly ContentModelMapper _contentModelMapper; @@ -60,7 +59,7 @@ namespace Umbraco.Web.Editors /// public ContentItemDisplay GetContent(int id) { - var foundContent = ApplicationContext.Services.ContentService.GetById(id); + var foundContent = Services.ContentService.GetById(id); if (foundContent == null) { ModelState.AddModelError("id", string.Format("content with id: {0} was not found", id)); @@ -111,7 +110,7 @@ namespace Umbraco.Web.Editors } //save the item - ApplicationContext.Services.ContentService.Save(contentItem.PersistedContent); + Services.ContentService.Save(contentItem.PersistedContent); //return the updated model return _contentModelMapper.ToContentItemDisplay(contentItem.PersistedContent); diff --git a/src/Umbraco.Web/Editors/ContentTypeApiController.cs b/src/Umbraco.Web/Editors/ContentTypeApiController.cs new file mode 100644 index 0000000000..039603169f --- /dev/null +++ b/src/Umbraco.Web/Editors/ContentTypeApiController.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using System.Net; +using System.Web.Http; +using Umbraco.Web.Models.Mapping; +using Umbraco.Web.WebApi; +using System.Linq; + +namespace Umbraco.Web.Editors +{ + /// + /// An API controller used for dealing with content types + /// + public class ContentTypeApiController : UmbracoAuthorizedApiController + { + private readonly ContentTypeModelMapper _contentTypeModelMapper; + + /// + /// Constructor + /// + public ContentTypeApiController() + : this(UmbracoContext.Current, new ContentTypeModelMapper(UmbracoContext.Current.Application)) + { + } + + /// + /// Constructor + /// + /// + /// + internal ContentTypeApiController(UmbracoContext umbracoContext, ContentTypeModelMapper contentModelMapper) + : base(umbracoContext) + { + _contentTypeModelMapper = contentModelMapper; + } + + /// + /// Returns the allowed child content type objects for the content item id passed in + /// + /// + public IEnumerable GetAllowedChildrenForContent(int contentId) + { + var contentItem = Services.ContentService.GetById(contentId); + if (contentItem == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + return Services.ContentTypeService.GetContentTypeChildren(contentItem.ContentTypeId) + .Select(x => _contentTypeModelMapper.ToContentItemBasic(x)); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemBase.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemBasic.cs similarity index 87% rename from src/Umbraco.Web/Models/ContentEditing/ContentItemBase.cs rename to src/Umbraco.Web/Models/ContentEditing/ContentItemBasic.cs index 7a509a41cd..777f02018f 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentItemBase.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemBasic.cs @@ -10,10 +10,10 @@ namespace Umbraco.Web.Models.ContentEditing /// A model representing a basic content item /// [DataContract(Name = "content", Namespace = "")] - public abstract class ContentItemBase + public abstract class ContentItemBasic where T: ContentPropertyBase { - protected ContentItemBase() + protected ContentItemBasic() { //ensure its not null _properties = new List(); @@ -48,7 +48,7 @@ namespace Umbraco.Web.Models.ContentEditing [JsonIgnore] internal ContentItemDto ContentDto { get; set; } - protected bool Equals(ContentItemBase other) + protected bool Equals(ContentItemBasic other) { return Id == other.Id; } @@ -57,7 +57,7 @@ namespace Umbraco.Web.Models.ContentEditing { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - var other = obj as ContentItemBase; + var other = obj as ContentItemBasic; return other != null && Equals(other); } diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs index 2e6aff38bd..8f3ad5e7da 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs @@ -10,7 +10,7 @@ namespace Umbraco.Web.Models.ContentEditing /// /// A model representing a content item to be displayed in the back office /// - public class ContentItemDisplay : ContentItemBase + public class ContentItemDisplay : ContentItemBasic { public ContentItemDisplay() { diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemDto.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemDto.cs index 671b734c5d..9e39578fb9 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentItemDto.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemDto.cs @@ -3,7 +3,7 @@ /// /// Represents a content item from the database including all of the required data that we need to work with such as data type data /// - internal class ContentItemDto : ContentItemBase + internal class ContentItemDto : ContentItemBasic { } diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs index 9f5a699f40..c211d21002 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs @@ -6,7 +6,7 @@ namespace Umbraco.Web.Models.ContentEditing /// /// A model representing a content item to be saved /// - public class ContentItemSave : ContentItemBase + public class ContentItemSave : ContentItemBasic { public ContentItemSave() { diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentTypeBasic.cs b/src/Umbraco.Web/Models/ContentEditing/ContentTypeBasic.cs new file mode 100644 index 0000000000..aba2f90dfe --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/ContentTypeBasic.cs @@ -0,0 +1,32 @@ +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models.ContentEditing +{ + /// + /// A basic version of a content type + /// + /// + /// Generally used to return the minimal amount of data about a content type + /// + [DataContract(Name = "contentType", Namespace = "")] + public class ContentTypeBasic + { + [DataMember(Name = "id", IsRequired = true)] + [Required] + public int Id { get; set; } + + [DataMember(Name = "name", IsRequired = true)] + [Required] + public string Name { get; set; } + + [DataMember(Name = "alias", IsRequired = true)] + [Required] + public string Alias { get; set; } + + [DataMember(Name = "description")] + public string Description { get; set; } + + public string Icon { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs index e04a013fc8..3b5c431351 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs @@ -10,7 +10,29 @@ using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Models.Mapping { - //TODO: Convert this over to mapping engine if people agree to it + internal class ContentTypeModelMapper + { + private readonly ApplicationContext _applicationContext; + + public ContentTypeModelMapper(ApplicationContext applicationContext) + { + _applicationContext = applicationContext; + } + + public ContentTypeBasic ToContentItemBasic(IContentType contentType) + { + return new ContentTypeBasic + { + Alias = contentType.Alias, + Id = contentType.Id, + Description = contentType.Description, + Icon = contentType.Icon, + Name = contentType.Name + }; + } + } + + internal class ContentModelMapper { private readonly ApplicationContext _applicationContext; @@ -79,7 +101,7 @@ namespace Umbraco.Web.Models.Mapping }; } - public ContentItemDto ToContentItemDto(IContent content) + internal ContentItemDto ToContentItemDto(IContent content) { return new ContentItemDto { diff --git a/src/Umbraco.Web/Trees/TreeNode.cs b/src/Umbraco.Web/Trees/TreeNode.cs index 5b18f2f750..037ab3887f 100644 --- a/src/Umbraco.Web/Trees/TreeNode.cs +++ b/src/Umbraco.Web/Trees/TreeNode.cs @@ -36,7 +36,7 @@ namespace Umbraco.Web.Trees /// /// The unique identifier for the node /// - [DataMember(Name = "nodeId")] + [DataMember(Name = "id")] public string NodeId { get; private set; } /// diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 95b48c79a1..d5eaf5eda8 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -292,6 +292,8 @@ + + @@ -316,7 +318,7 @@ True Resources.resx - +