WIP refactor commit for getting all variants at once saving, this requires pulling apart a lot of the models and corresponding binders and validators.

This commit is contained in:
Shannon
2018-07-19 19:32:07 +10:00
parent 888f8cfc56
commit 18cd9ea1e8
49 changed files with 1157 additions and 919 deletions

View File

@@ -1,31 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// A model representing a content base item to be saved
/// </summary>
[DataContract(Name = "content", Namespace = "")]
public abstract class ContentBaseItemSave<TPersisted> : ContentItemBasic<ContentPropertyBasic, TPersisted>, IHaveUploadedFiles
where TPersisted : IContentBase
{
protected ContentBaseItemSave()
{
UploadedFiles = new List<ContentPropertyFile>();
}
/// <summary>
/// The action to perform when saving this content item
/// </summary>
[DataMember(Name = "action", IsRequired = true)]
[Required]
public ContentSaveAction Action { get; set; }
[IgnoreDataMember]
public List<ContentPropertyFile> UploadedFiles { get; private set; }
}
}

View File

@@ -0,0 +1,59 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// A model representing a content item to be saved
/// </summary>
[DataContract(Name = "content", Namespace = "")]
public abstract class ContentBaseSave<TPersisted> : ContentItemBasic<ContentPropertyBasic, TPersisted>, IContentSave<TPersisted>
where TPersisted : IContentBase
{
protected ContentBaseSave()
{
UploadedFiles = new List<ContentPropertyFile>();
}
#region IContentSave
/// <inheritdoc />
[DataMember(Name = "action", IsRequired = true)]
[Required]
public ContentSaveAction Action { get; set; }
[IgnoreDataMember]
public List<ContentPropertyFile> UploadedFiles { get; }
//These need explicit implementation because we are using internal models
/// <inheritdoc />
[IgnoreDataMember]
TPersisted IContentSave<TPersisted>.PersistedContent { get; set; }
//These need explicit implementation because we are using internal models
/// <inheritdoc />
[IgnoreDataMember]
ContentItemDto<TPersisted> IContentSave<TPersisted>.ContentDto { get; set; }
//Non explicit internal getter so we don't need to explicitly cast in our own code
[IgnoreDataMember]
internal TPersisted PersistedContent
{
get => ((IContentSave<TPersisted>)this).PersistedContent;
set => ((IContentSave<TPersisted>) this).PersistedContent = value;
}
//Non explicit internal getter so we don't need to explicitly cast in our own code
[IgnoreDataMember]
internal ContentItemDto<TPersisted> ContentDto
{
get => ((IContentSave<TPersisted>)this).ContentDto;
set => ((IContentSave<TPersisted>) this).ContentDto = value;
}
#endregion
}
}

View File

@@ -85,26 +85,5 @@ namespace Umbraco.Web.Models.ContentEditing
set => _properties = value;
}
/// <summary>
/// The real persisted content object - used during inbound model binding
/// </summary>
/// <remarks>
/// This is not used for outgoing model information.
/// </remarks>
[IgnoreDataMember]
internal TPersisted PersistedContent { get; set; }
/// <summary>
/// The DTO object used to gather all required content data including data type information etc... for use with validation - used during inbound model binding
/// </summary>
/// <remarks>
/// We basically use this object to hydrate all required data from the database into one object so we can validate everything we need
/// instead of having to look up all the data individually.
/// This is not used for outgoing model information.
/// </remarks>
[IgnoreDataMember]
internal ContentItemDto<TPersisted> ContentDto { get; set; }
}
}

View File

@@ -22,7 +22,7 @@ namespace Umbraco.Web.Models.ContentEditing
AllowPreview = true;
Notifications = new List<Notification>();
Errors = new Dictionary<string, object>();
ContentVariants = new List<ContentVariantDisplay>();
Variants = new List<ContentVariantDisplay>();
ContentApps = new List<ContentApp>();
}
@@ -65,7 +65,7 @@ namespace Umbraco.Web.Models.ContentEditing
/// If a content item is invariant, this collection will only contain one item, else it will contain all culture variants
/// </remarks>
[DataMember(Name = "variants")]
public IEnumerable<ContentVariantDisplay> ContentVariants { get; set; }
public IEnumerable<ContentVariantDisplay> Variants { get; set; }
[DataMember(Name = "owner")]
public UserProfile Owner { get; set; }

View File

@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
namespace Umbraco.Web.Models.ContentEditing
{
@@ -10,13 +12,28 @@ namespace Umbraco.Web.Models.ContentEditing
/// A model representing a content item to be saved
/// </summary>
[DataContract(Name = "content", Namespace = "")]
public class ContentItemSave : ContentBaseItemSave<IContent>
public class ContentItemSave : IContentSave<IContent>
{
/// <summary>
/// The language Id for the content variation being saved
/// </summary>
[DataMember(Name = "culture")]
public string Culture { get; set; } //TODO: Change this to ContentVariationPublish, but this will all change anyways when we can edit all variants at once
protected ContentItemSave()
{
UploadedFiles = new List<ContentPropertyFile>();
Variants = new List<ContentVariantSave>();
}
[DataMember(Name = "id", IsRequired = true)]
[Required]
public int Id { get; set; }
[DataMember(Name = "parentId", IsRequired = true)]
[Required]
public int ParentId { get; set; }
[DataMember(Name = "variants", IsRequired = true)]
public IEnumerable<ContentVariantSave> Variants { get; set; }
[DataMember(Name = "contentTypeAlias", IsRequired = true)]
[Required(AllowEmptyStrings = false)]
public string ContentTypeAlias { get; set; }
/// <summary>
/// The template alias to save
@@ -24,16 +41,48 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "templateAlias")]
public string TemplateAlias { get; set; }
//TODO: these will need to move to the variant
[DataMember(Name = "releaseDate")]
public DateTime? ReleaseDate { get; set; }
[DataMember(Name = "expireDate")]
public DateTime? ExpireDate { get; set; }
/// <summary>
/// Indicates that these variations should also be published
/// </summary>
[DataMember(Name = "publishVariations")]
public IEnumerable<ContentVariationPublish> PublishVariations { get; set; }
#region IContentSave
[DataMember(Name = "action", IsRequired = true)]
[Required]
public ContentSaveAction Action { get; set; }
[IgnoreDataMember]
public List<ContentPropertyFile> UploadedFiles { get; }
//These need explicit implementation because we are using internal models
/// <inheritdoc />
[IgnoreDataMember]
IContent IContentSave<IContent>.PersistedContent { get; set; }
//These need explicit implementation because we are using internal models
/// <inheritdoc />
[IgnoreDataMember]
ContentItemDto<IContent> IContentSave<IContent>.ContentDto { get; set; }
//Non explicit internal getter so we don't need to explicitly cast in our own code
[IgnoreDataMember]
internal IContent PersistedContent
{
get => ((IContentSave<IContent>)this).PersistedContent;
set => ((IContentSave<IContent>)this).PersistedContent = value;
}
//Non explicit internal getter so we don't need to explicitly cast in our own code
[IgnoreDataMember]
internal ContentItemDto<IContent> ContentDto
{
get => ((IContentSave<IContent>)this).ContentDto;
set => ((IContentSave<IContent>)this).ContentDto = value;
}
#endregion
}
}

View File

@@ -0,0 +1,37 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Validation;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "contentVariant", Namespace = "")]
public class ContentVariantSave : IContentProperties<ContentPropertyBasic>
{
public ContentVariantSave()
{
Properties = new List<ContentPropertyBasic>();
}
[DataMember(Name = "name", IsRequired = true)]
[RequiredForPersistence(AllowEmptyStrings = false, ErrorMessage = "Required")]
public string Name { get; set; }
[DataMember(Name = "properties")]
public IEnumerable<ContentPropertyBasic> Properties { get; set; }
/// <summary>
/// The culture of this variant, if this is invariant than this is null or empty
/// </summary>
[DataMember(Name = "culture")]
public string Culture { get; set; }
/// <summary>
/// Indicates if the variant should be published or unpublished
/// </summary>
[DataMember(Name = "publish")]
public bool Publish { get; set; }
}
}

View File

@@ -4,10 +4,10 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.Serialization;
using Umbraco.Core.Models;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// Represents the variant info for a content item
/// </summary>

View File

@@ -1,18 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// Used to indicate which additional variants to publish when a content item is published
/// </summary>
public class ContentVariationPublish
{
[DataMember(Name = "culture", IsRequired = true)]
[Required]
public string Culture { get; set; }
[DataMember(Name = "segment")]
public string Segment { get; set; }
}
}

View File

@@ -3,10 +3,12 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using System.Web.Http.ModelBinding;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Models.Validation;
using Umbraco.Core.Serialization;
using Umbraco.Web.WebApi;
namespace Umbraco.Web.Models.ContentEditing
{

View File

@@ -1,7 +1,24 @@
using System.Collections.Generic;
using Umbraco.Core.Models;
namespace Umbraco.Web.Models.ContentEditing
{
///// <summary>
///// An interface that needs to be implemented for the ContentItemValidationHelper to be used
///// </summary>
///// <typeparam name="TPersisted"></typeparam>
///// <remarks>
///// We want to share the validation and model binding logic with content, media and members but because of variants content
///// is now quite different than the others so this allows us to continue sharing the logic between these models.
///// </remarks>
//internal interface IContentItemValidationHelperModel<TPersisted>
// where TPersisted : IContentBase
//{
// TPersisted GetPersisted();
// ContentItemDto<TPersisted> GetDto();
// IContentProperties<ContentPropertyBasic> GetProperties();
//}
public interface IContentProperties<T>
where T : ContentPropertyBasic
{

View File

@@ -0,0 +1,35 @@
using Umbraco.Core.Models;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// An interface exposes the shared parts of content, media, members that we use during model binding in order to share logic
/// </summary>
/// <typeparam name="TPersisted"></typeparam>
internal interface IContentSave<TPersisted> : IHaveUploadedFiles
where TPersisted : IContentBase
{
/// <summary>
/// The action to perform when saving this content item
/// </summary>
ContentSaveAction Action { get; set; }
/// <summary>
/// The real persisted content object - used during inbound model binding
/// </summary>
/// <remarks>
/// This is not used for outgoing model information.
/// </remarks>
TPersisted PersistedContent { get; set; }
/// <summary>
/// The DTO object used to gather all required content data including data type information etc... for use with validation - used during inbound model binding
/// </summary>
/// <remarks>
/// We basically use this object to hydrate all required data from the database into one object so we can validate everything we need
/// instead of having to look up all the data individually.
/// This is not used for outgoing model information.
/// </remarks>
ContentItemDto<TPersisted> ContentDto { get; set; }
}
}

View File

@@ -1,5 +1,6 @@
using System.Runtime.Serialization;
using Umbraco.Core.Models;
using Umbraco.Web.WebApi.Filters;
namespace Umbraco.Web.Models.ContentEditing
{
@@ -7,8 +8,7 @@ namespace Umbraco.Web.Models.ContentEditing
/// A model representing a media item to be saved
/// </summary>
[DataContract(Name = "content", Namespace = "")]
public class MediaItemSave : ContentBaseItemSave<IMedia>
public class MediaItemSave : ContentBaseSave<IMedia>
{
}
}

View File

@@ -3,14 +3,14 @@ using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
using Umbraco.Core.Models.Validation;
using Umbraco.Web.WebApi.Filters;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// A model representing a member to be saved
/// </summary>
public class MemberSave : ContentBaseItemSave<IMember>
/// <inheritdoc />
public class MemberSave : ContentBaseSave<IMember>
{
[DataMember(Name = "username", IsRequired = true)]
@@ -35,6 +35,7 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "isApproved")]
public bool IsApproved { get; set; }
//TODO: Need to add question / answer support
}