diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs index a0e68d23a7..60e5ddfd04 100644 --- a/src/Umbraco.Core/Constants-PropertyEditors.cs +++ b/src/Umbraco.Core/Constants-PropertyEditors.cs @@ -7,7 +7,12 @@ /// public static class PropertyEditors { - /// + /// + /// Used to prefix generic properties that are internal content properties + /// + public const string InternalGenericPropertiesPrefix = "_umb_"; + + /// /// Guid for the Checkbox list datatype. /// public const string CheckBoxList = "B4471851-82B6-4C75-AFA4-39FA9C6A75E9"; diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js index 14fb6d8da8..57d3692df2 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js @@ -53,7 +53,7 @@ label: "Grid", id: 4, properties: [ - { alias: "grid", label: "Grid", view: "grid", controller: "umbraco.grid", value: "test", hideLabel: true } + { alias: "grid", label: "Grid", view: "grid", value: "test", hideLabel: true } ] }, { label: "Generic Properties", @@ -62,7 +62,7 @@ { label: 'Created by', description: 'Original author', - value: 1, + value: "Administrator", view: "readonlyvalue", alias: "_umb_createdby" }, @@ -71,9 +71,6 @@ description: 'Time this document was created', value: new Date().toIsoDateTimeString(), view: "readonlyvalue", - //NOTE: No need for filters because the date is a formatted string already because - // that is how it comes from the server as a pre-formatted json string - //config: {filter: 'date', format: 'medium'}, alias: "_umb_createdate" }, { @@ -99,10 +96,10 @@ label: 'Template', value: "1234", view: "templatepicker", - alias: "_umb_template" + alias: "_umb_template" }, { - alias: "test", label: "Stuff", view: "test", controller: "umbraco.embeddedcontent", value: "", + alias: "test", label: "Stuff", view: "test", value: "", config: { fields: [ { alias: "embedded", label: "Embbeded", view: "textstring", value: "" }, diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js index 4341e27e26..d09dcd261c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js @@ -56,14 +56,14 @@ angular.module('umbraco.mocks'). alias: "tab03", id: 3, properties: [ - { alias: "grid", label: "Grid", view: "grid", controller: "umbraco.grid", value: "test", hideLabel: true } + { alias: "grid", label: "Grid", view: "grid", value: "test", hideLabel: true } ] },{ label: "WIP", alias: "tab04", id: 4, properties: [ - { alias: "tes", label: "Stuff", view: "test", controller: "umbraco.embeddedcontent", value: "", + { alias: "tes", label: "Stuff", view: "test", value: "", config: { fields: [ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js new file mode 100644 index 0000000000..174e3816bf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js @@ -0,0 +1,15 @@ +function booleanEditorController($scope, $rootScope, assetsService) { + + $scope.renderModel = { + value: false + }; + if ($scope.model && $scope.model.value && ($scope.model.value.toString() === "1" || angular.lowercase($scope.model.value) === "true")) { + $scope.renderModel.value = true; + } + + $scope.$watch("renderModel.value", function (newVal) { + $scope.model.value = newVal === true ? "1" : "0"; + }); + +} +angular.module("umbraco").controller("Umbraco.Editors.BooleanController", booleanEditorController); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html index d01704ffe4..7f606e583c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html @@ -1 +1,3 @@ - + + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/templatepicker/templatepicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/templatepicker/templatepicker.html new file mode 100644 index 0000000000..ebd32d0748 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/templatepicker/templatepicker.html @@ -0,0 +1,4 @@ +
+
TODO: Implement this picker
+
+
\ No newline at end of file diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs index e08540b242..ad961c4b50 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs @@ -17,6 +17,9 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "publishDate")] public DateTime? PublishDate { get; set; } + + [DataMember(Name = "template")] + public string Template { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplayBase.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplayBase.cs index c696aeb675..867f3a6ebc 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplayBase.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplayBase.cs @@ -13,6 +13,12 @@ namespace Umbraco.Web.Models.ContentEditing Notifications = new List(); } + /// + /// The name of the content type + /// + [DataMember(Name = "contentTypeName")] + public string ContentTypeName { get; set; } + /// /// This is used to add custom localized messages/strings to the response for the app to use for localized UI purposes. /// diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs index d9fab62343..3063d9b522 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs @@ -1,13 +1,17 @@ using System; +using System.Linq; using System.Linq.Expressions; using AutoMapper; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Mapping; +using Umbraco.Core.PropertyEditors; using Umbraco.Web.Models.ContentEditing; +using umbraco; namespace Umbraco.Web.Models.Mapping { + /// /// Declares how model mappings for content /// @@ -15,6 +19,7 @@ namespace Umbraco.Web.Models.Mapping { public override void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext) { + //FROM IContent TO ContentItemDisplay config.CreateMap() .ForMember( @@ -29,11 +34,24 @@ namespace Umbraco.Web.Models.Mapping .ForMember( dto => dto.ContentTypeAlias, expression => expression.MapFrom(content => content.ContentType.Alias)) + .ForMember( + dto => dto.ContentTypeName, + expression => expression.MapFrom(content => content.ContentType.Name)) .ForMember( dto => dto.PublishDate, expression => expression.MapFrom(content => GetPublishedDate(content, applicationContext))) + .ForMember( + dto => dto.Template, + expression => expression.MapFrom(content => content.Template.Name)) .ForMember(display => display.Properties, expression => expression.Ignore()) - .ForMember(display => display.Tabs, expression => expression.ResolveUsing()); + .ForMember(display => display.Tabs, expression => expression.ResolveUsing()) + .AfterMap((content, display) => TabsAndPropertiesResolver.MapGenericProperties(content, display, new ContentPropertyDisplay + { + Alias = string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix), + Label = "Template", //TODO: localize this? + Value = display.Template, + View = "templatepicker" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor + })); //FROM IContent TO ContentItemBasic config.CreateMap>() diff --git a/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs b/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs index f610c08926..fe3643da87 100644 --- a/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs @@ -29,9 +29,13 @@ namespace Umbraco.Web.Models.Mapping expression => expression.MapFrom(content => content.ContentType.Icon)) .ForMember( dto => dto.ContentTypeAlias, - expression => expression.MapFrom(content => content.ContentType.Alias)) + expression => expression.MapFrom(content => content.ContentType.Alias)) + .ForMember( + dto => dto.ContentTypeName, + expression => expression.MapFrom(content => content.ContentType.Name)) .ForMember(display => display.Properties, expression => expression.Ignore()) - .ForMember(display => display.Tabs, expression => expression.ResolveUsing()); + .ForMember(display => display.Tabs, expression => expression.ResolveUsing()) + .AfterMap((media, display) => TabsAndPropertiesResolver.MapGenericProperties(media, display)); //FROM IMedia TO ContentItemBasic config.CreateMap>() diff --git a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs index c943cf8ff0..3f284f8a7b 100644 --- a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs @@ -1,8 +1,12 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using AutoMapper; +using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.PropertyEditors; using Umbraco.Web.Models.ContentEditing; +using umbraco; namespace Umbraco.Web.Models.Mapping { @@ -11,6 +15,83 @@ namespace Umbraco.Web.Models.Mapping ///
internal class TabsAndPropertiesResolver : ValueResolver>> { + /// + /// Maps properties on to the generic properties tab + /// + /// + /// + /// + /// Any additional custom properties to assign to the generic properties tab. + /// + /// + /// The generic properties tab is mapped during AfterMap and is responsible for + /// setting up the properties such as Created date, udpated date, template selected, etc... + /// + public static void MapGenericProperties( + TPersisted content, + ContentItemDisplayBase display, + params ContentPropertyDisplay[] customProperties) + where TPersisted : IContentBase + { + var genericProps = display.Tabs.Single(x => x.Id == 0); + + //store the current props to append to the newly inserted ones + var currProps = genericProps.Properties.ToArray(); + + var labelEditor = PropertyEditorResolver.Current.GetById(new Guid(Constants.PropertyEditors.NoEdit)).ValueEditor.View; + + var contentProps = new List + { + new ContentPropertyDisplay + { + Alias = string.Format("{0}creator", Constants.PropertyEditors.InternalGenericPropertiesPrefix), + Label = ui.Text("content", "createBy"), + Description = "Original author", //TODO: Localize this + Value = display.Owner.Name, + View = labelEditor + }, + new ContentPropertyDisplay + { + Alias = string.Format("{0}createdate", Constants.PropertyEditors.InternalGenericPropertiesPrefix), + Label = ui.Text("content", "createDate"), + Description = "Time this document was created", //TODO: Localize this + Value = display.CreateDate.ToIsoString(), + View = labelEditor + }, + new ContentPropertyDisplay + { + Alias = string.Format("{0}updatedate", Constants.PropertyEditors.InternalGenericPropertiesPrefix), + Label = ui.Text("content", "updateDate"), + Description = "Time this document was last updated", //TODO: Localize this + Value = display.UpdateDate.ToIsoString(), + View = labelEditor + }, + new ContentPropertyDisplay + { + Alias = string.Format("{0}id", Constants.PropertyEditors.InternalGenericPropertiesPrefix), + Label = "Id", + Value = display.Id.ToInvariantString(), + View = labelEditor + }, + new ContentPropertyDisplay + { + Alias = string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix), + Label = ui.Text("content", "documentType"), + Value = display.ContentTypeName, + View = labelEditor + } + }; + + //add the custom ones + contentProps.AddRange(customProperties); + + //now add the user props + contentProps.AddRange(currProps); + + //re-assign + genericProps.Properties = contentProps; + } + protected override IEnumerable> ResolveCore(IContentBase content) { var aggregateTabs = new List>(); diff --git a/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs new file mode 100644 index 0000000000..b4122573c4 --- /dev/null +++ b/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs @@ -0,0 +1,10 @@ +using Umbraco.Core; +using Umbraco.Core.PropertyEditors; + +namespace Umbraco.Web.PropertyEditors +{ + [PropertyEditor(Constants.PropertyEditors.NoEdit, "Label", "readonlyvalue")] + public class LabelPropertyEditor : PropertyEditor + { + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/PropertyEditors/TextStringPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/TextStringPropertyEditor.cs index 7524c56a5c..fa6cfe0cd2 100644 --- a/src/Umbraco.Web/PropertyEditors/TextStringPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/TextStringPropertyEditor.cs @@ -8,7 +8,6 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.Textbox, "Textstring", "textstring")] public class TextStringPropertyEditor : PropertyEditor { diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 2a730f08ba..52d20f9661 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -300,6 +300,7 @@ +