Browse Source

ContentData refactored and bugfixes with asset editor.

pull/65/head
Sebastian Stehle 9 years ago
parent
commit
dbcb576f1d
  1. 11
      src/Squidex.Core/ContentEnricher.cs
  2. 67
      src/Squidex.Core/ContentExtensions.cs
  3. 6
      src/Squidex.Core/ContentValidator.cs
  4. 227
      src/Squidex.Core/Contents/ContentData.cs
  5. 133
      src/Squidex.Core/Contents/IdContentData.cs
  6. 193
      src/Squidex.Core/Contents/NamedContentData.cs
  7. 2
      src/Squidex.Core/Schemas/AssetsField.cs
  8. 2
      src/Squidex.Events/Contents/ContentCreated.cs
  9. 2
      src/Squidex.Events/Contents/ContentUpdated.cs
  10. 22
      src/Squidex.Infrastructure.MongoDb/IMongoEntity.cs
  11. 2
      src/Squidex.Infrastructure.MongoDb/MongoEntity.cs
  12. 78
      src/Squidex.Read.MongoDb/Contents/MongoContentEntity.cs
  13. 3
      src/Squidex.Read.MongoDb/Contents/MongoContentRepository_EventHandling.cs
  14. 18
      src/Squidex.Read.MongoDb/Utils/EntityMapper.cs
  15. 6
      src/Squidex.Read.MongoDb/Utils/MongoCollectionExtensions.cs
  16. 2
      src/Squidex.Read/Contents/IContentEntity.cs
  17. 2
      src/Squidex.Write/Contents/Commands/ContentDataCommand.cs
  18. 2
      src/Squidex.Write/Contents/ContentDomainObject.cs
  19. 8
      src/Squidex/Controllers/ContentApi/ContentsController.cs
  20. 2
      src/Squidex/Controllers/ContentApi/Models/ContentDto.cs
  21. 12
      src/Squidex/app/shared/components/assets-editor.component.ts
  22. 2
      tests/Squidex.Core.Tests/ContentEnrichmentTests.cs
  23. 30
      tests/Squidex.Core.Tests/ContentValidationTests.cs
  24. 255
      tests/Squidex.Core.Tests/Contents/ContentDataTests.cs
  25. 81
      tests/Squidex.Core.Tests/Schemas/AssetsFieldTests.cs
  26. 12
      tests/Squidex.Write.Tests/Contents/ContentCommandHandlerTests.cs
  27. 8
      tests/Squidex.Write.Tests/Contents/ContentDomainObjectTests.cs

11
src/Squidex.Core/ContentEnricher.cs

@ -14,7 +14,7 @@ using Squidex.Infrastructure.Json;
namespace Squidex.Core namespace Squidex.Core
{ {
public sealed class ContentEnricher public sealed class ContentEnricher<T>
{ {
private readonly Schema schema; private readonly Schema schema;
private readonly PartitionResolver partitionResolver; private readonly PartitionResolver partitionResolver;
@ -29,13 +29,14 @@ namespace Squidex.Core
this.partitionResolver = partitionResolver; this.partitionResolver = partitionResolver;
} }
public void Enrich(ContentData data) public void Enrich(ContentData<T> data)
{ {
Guard.NotNull(data, nameof(data)); Guard.NotNull(data, nameof(data));
foreach (var field in schema.FieldsByName.Values) foreach (var field in schema.Fields)
{ {
var fieldData = data.GetOrCreate(field.Name, k => new ContentFieldData()); var fieldKey = data.GetKey(field);
var fieldData = data.GetOrCreate(fieldKey, k => new ContentFieldData());
var fieldPartition = partitionResolver(field.Paritioning); var fieldPartition = partitionResolver(field.Paritioning);
foreach (var partitionItem in fieldPartition) foreach (var partitionItem in fieldPartition)
@ -45,7 +46,7 @@ namespace Squidex.Core
if (fieldData.Count > 0) if (fieldData.Count > 0)
{ {
data.AddField(field.Name, fieldData); data[fieldKey] = fieldData;
} }
} }
} }

67
src/Squidex.Core/ContentExtensions.cs

@ -6,9 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Core.Contents; using Squidex.Core.Contents;
using Squidex.Core.Schemas; using Squidex.Core.Schemas;
@ -20,16 +18,14 @@ namespace Squidex.Core
{ {
public static class ContentExtensions public static class ContentExtensions
{ {
public static ContentData Enrich(this ContentData data, Schema schema, PartitionResolver partitionResolver) public static void Enrich<T>(this ContentData<T> data, Schema schema, PartitionResolver partitionResolver)
{ {
var enricher = new ContentEnricher(schema, partitionResolver); var enricher = new ContentEnricher<T>(schema, partitionResolver);
enricher.Enrich(data); enricher.Enrich(data);
return data;
} }
public static async Task ValidateAsync(this ContentData data, Schema schema, PartitionResolver partitionResolver, IList<ValidationError> errors) public static async Task ValidateAsync(this NamedContentData data, Schema schema, PartitionResolver partitionResolver, IList<ValidationError> errors)
{ {
var validator = new ContentValidator(schema, partitionResolver); var validator = new ContentValidator(schema, partitionResolver);
@ -41,7 +37,7 @@ namespace Squidex.Core
} }
} }
public static async Task ValidatePartialAsync(this ContentData data, Schema schema, PartitionResolver partitionResolver, IList<ValidationError> errors) public static async Task ValidatePartialAsync(this NamedContentData data, Schema schema, PartitionResolver partitionResolver, IList<ValidationError> errors)
{ {
var validator = new ContentValidator(schema, partitionResolver); var validator = new ContentValidator(schema, partitionResolver);
@ -52,60 +48,5 @@ namespace Squidex.Core
errors.Add(error); errors.Add(error);
} }
} }
public static IEnumerable<Guid> GetReferencedIds(this ContentData data, Schema schema)
{
var foundReferences = new HashSet<Guid>();
foreach (var field in schema.Fields)
{
if (field is IReferenceField referenceField)
{
var fieldData = data.GetOrDefault(field.Id.ToString());
if (fieldData == null)
{
continue;
}
foreach (var partitionValue in fieldData.Where(x => x.Value != null))
{
var ids = referenceField.GetReferencedIds(partitionValue.Value);
foreach (var id in ids.Where(x => foundReferences.Add(x)))
{
yield return id;
}
}
}
}
}
public static ContentData ToCleanedReferences(this ContentData data, Schema schema, ISet<Guid> deletedReferencedIds)
{
var result = new ContentData(data);
foreach (var field in schema.Fields)
{
if (field is IReferenceField referenceField)
{
var fieldData = data.GetOrDefault(field.Id.ToString());
if (fieldData == null)
{
continue;
}
foreach (var partitionValue in fieldData.Where(x => x.Value != null).ToList())
{
var newValue = referenceField.RemoveDeletedReferences(partitionValue.Value, deletedReferencedIds);
fieldData[partitionValue.Key] = newValue;
}
}
}
return result;
}
} }
} }

6
src/Squidex.Core/ContentValidator.cs

@ -38,7 +38,7 @@ namespace Squidex.Core
this.partitionResolver = partitionResolver; this.partitionResolver = partitionResolver;
} }
public async Task ValidatePartialAsync(ContentData data) public async Task ValidatePartialAsync(NamedContentData data)
{ {
Guard.NotNull(data, nameof(data)); Guard.NotNull(data, nameof(data));
@ -77,7 +77,7 @@ namespace Squidex.Core
} }
} }
public async Task ValidateAsync(ContentData data) public async Task ValidateAsync(NamedContentData data)
{ {
Guard.NotNull(data, nameof(data)); Guard.NotNull(data, nameof(data));
@ -91,7 +91,7 @@ namespace Squidex.Core
} }
} }
private void ValidateUnknownFields(ContentData data) private void ValidateUnknownFields(NamedContentData data)
{ {
foreach (var fieldData in data) foreach (var fieldData in data)
{ {

227
src/Squidex.Core/Contents/ContentData.cs

@ -9,7 +9,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Squidex.Core.Schemas; using Squidex.Core.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -18,41 +17,33 @@ using Squidex.Infrastructure;
namespace Squidex.Core.Contents namespace Squidex.Core.Contents
{ {
public sealed class ContentData : Dictionary<string, ContentFieldData>, IEquatable<ContentData> public abstract class ContentData<T> : Dictionary<T, ContentFieldData>, IEquatable<ContentData<T>>
{ {
public ContentData() public IEnumerable<KeyValuePair<T, ContentFieldData>> ValidValues
: base(StringComparer.OrdinalIgnoreCase)
{ {
get { return this.Where(x => x.Value != null); }
} }
public ContentData(IDictionary<string, ContentFieldData> copy) protected ContentData(IEqualityComparer<T> comparer)
: base(copy, StringComparer.OrdinalIgnoreCase) : base(comparer)
{ {
} }
public ContentData AddField(string fieldName, ContentFieldData data) protected ContentData(IDictionary<T, ContentFieldData> copy, IEqualityComparer<T> comparer)
: base(copy, comparer)
{ {
Guard.ValidPropertyName(fieldName, nameof(fieldName));
this[fieldName] = data;
return this;
} }
public ContentData MergeInto(ContentData other) protected static TResult Merge<TResult>(TResult source, TResult target) where TResult : ContentData<T>
{ {
Guard.NotNull(other, nameof(other)); if (ReferenceEquals(target, source))
var result = new ContentData(this);
if (ReferenceEquals(other, this))
{ {
return result; return source;
} }
foreach (var otherValue in other) foreach (var otherValue in source)
{ {
var fieldValue = result.GetOrAdd(otherValue.Key, x => new ContentFieldData()); var fieldValue = target.GetOrAdd(otherValue.Key, x => new ContentFieldData());
foreach (var value in otherValue.Value) foreach (var value in otherValue.Value)
{ {
@ -60,223 +51,85 @@ namespace Squidex.Core.Contents
} }
} }
return result; return target;
} }
public ContentData ToCleaned() protected static TResult Clean<TResult>(TResult source, TResult target) where TResult : ContentData<T>
{ {
var result = new ContentData(); foreach (var fieldValue in source.ValidValues)
foreach (var fieldValue in this.Where(x => x.Value != null))
{ {
var resultValue = new ContentFieldData(); var resultValue = new ContentFieldData();
foreach (var partitionValue in fieldValue.Value.Where(x => x.Value != null && x.Value.Type != JTokenType.Null)) foreach (var partitionValue in fieldValue.Value.Where(x => IsNotNull(x.Value)))
{ {
resultValue[partitionValue.Key] = partitionValue.Value; resultValue[partitionValue.Key] = partitionValue.Value;
} }
if (resultValue.Count > 0) if (resultValue.Count > 0)
{ {
result[fieldValue.Key] = resultValue; target[fieldValue.Key] = resultValue;
} }
} }
return result; return target;
} }
public ContentData ToIdModel(Schema schema, bool encodeJsonField) public IEnumerable<Guid> GetReferencedIds(Schema schema)
{ {
Guard.NotNull(schema, nameof(schema)); Guard.NotNull(schema, nameof(schema));
var result = new ContentData(); var foundReferences = new HashSet<Guid>();
foreach (var fieldValue in this)
{
if (!schema.FieldsByName.TryGetValue(fieldValue.Key, out Field field))
{
continue;
}
var fieldId = field.Id.ToString();
if (encodeJsonField && field is JsonField)
{
var encodedValue = new ContentFieldData();
foreach (var partitionValue in fieldValue.Value) foreach (var field in schema.Fields)
{
if (partitionValue.Value == null || partitionValue.Value.Type == JTokenType.Null)
{ {
encodedValue[partitionValue.Key] = null; if (field is IReferenceField referenceField)
}
else
{ {
var value = Convert.ToBase64String(Encoding.UTF8.GetBytes(partitionValue.Value.ToString())); var fieldKey = GetKey(field);
var fieldData = this.GetOrDefault(fieldKey);
encodedValue[partitionValue.Key] = value;
}
}
result[fieldId] = encodedValue; if (fieldData == null)
}
else
{
result[fieldId] = fieldValue.Value;
}
}
return result;
}
public ContentData ToNameModel(Schema schema, bool decodeJsonField)
{
Guard.NotNull(schema, nameof(schema));
var result = new ContentData();
foreach (var fieldValue in this)
{
if (!long.TryParse(fieldValue.Key, out long fieldId) || !schema.FieldsById.TryGetValue(fieldId, out Field field))
{ {
continue; continue;
} }
if (decodeJsonField && field is JsonField) foreach (var partitionValue in fieldData.Where(x => x.Value != null))
{ {
var encodedValue = new ContentFieldData(); var ids = referenceField.GetReferencedIds(partitionValue.Value);
foreach (var partitionValue in fieldValue.Value) foreach (var id in ids.Where(x => foundReferences.Add(x)))
{ {
if (partitionValue.Value == null || partitionValue.Value.Type == JTokenType.Null) yield return id;
{
encodedValue[partitionValue.Key] = null;
} }
else
{
var value = Encoding.UTF8.GetString(Convert.FromBase64String(partitionValue.Value.ToString()));
encodedValue[partitionValue.Key] = JToken.Parse(value);
} }
} }
result[field.Name] = encodedValue;
} }
else
{
result[field.Name] = fieldValue.Value;
} }
}
return result;
}
public ContentData ToApiModel(Schema schema, LanguagesConfig languagesConfig, IReadOnlyCollection<Language> languagePreferences = null, bool excludeHidden = true)
{
Guard.NotNull(schema, nameof(schema));
Guard.NotNull(languagesConfig, nameof(languagesConfig));
var codeForInvariant = InvariantPartitioning.Instance.Master.Key; public override bool Equals(object obj)
var codeForMasterLanguage = languagesConfig.Master.Language.Iso2Code;
var result = new ContentData();
foreach (var fieldValue in this)
{
if (!schema.FieldsByName.TryGetValue(fieldValue.Key, out Field field) || (excludeHidden && field.IsHidden))
{
continue;
}
var fieldResult = new ContentFieldData();
var fieldValues = fieldValue.Value;
if (field.Paritioning.Equals(Partitioning.Language))
{
foreach (var languageConfig in languagesConfig)
{
var languageCode = languageConfig.Key;
if (fieldValues.TryGetValue(languageCode, out JToken value))
{
fieldResult.Add(languageCode, value);
}
else if (languageConfig == languagesConfig.Master && fieldValues.TryGetValue(codeForInvariant, out value))
{
fieldResult.Add(languageCode, value);
}
}
}
else
{
if (fieldValues.TryGetValue(codeForInvariant, out JToken value))
{
fieldResult.Add(codeForInvariant, value);
}
else if (fieldValues.TryGetValue(codeForMasterLanguage, out value))
{
fieldResult.Add(codeForInvariant, value);
}
else if (fieldValues.Count > 0)
{
fieldResult.Add(codeForInvariant, fieldValues.Values.First());
}
}
result.Add(field.Name, fieldResult);
}
return result;
}
public object ToLanguageModel(LanguagesConfig languagesConfig, IReadOnlyCollection<Language> languagePreferences = null)
{
Guard.NotNull(languagesConfig, nameof(languagesConfig));
if (languagePreferences == null || languagePreferences.Count == 0)
{ {
return this; return Equals(obj as ContentData<T>);
} }
if (languagePreferences.Count == 1 && languagesConfig.TryGetConfig(languagePreferences.First(), out var languageConfig)) public bool Equals(ContentData<T> other)
{ {
languagePreferences = languagePreferences.Union(languageConfig.Fallback).ToList(); return other != null && (ReferenceEquals(this, other) || this.EqualsDictionary(other));
} }
var result = new Dictionary<string, JToken>(); public override int GetHashCode()
foreach (var fieldValue in this)
{
var fieldValues = fieldValue.Value;
foreach (var language in languagePreferences)
{
if (fieldValues.TryGetValue(language, out JToken value) && value != null)
{ {
result[fieldValue.Key] = value; return this.DictionaryHashCode();
break;
}
}
}
return result;
} }
public override bool Equals(object obj) protected static bool IsNull(JToken value)
{ {
return Equals(obj as ContentData); return value == null || value.Type == JTokenType.Null;
} }
public bool Equals(ContentData other) protected static bool IsNotNull(JToken value)
{ {
return other != null && (ReferenceEquals(this, other) || this.EqualsDictionary(other)); return value != null && value.Type != JTokenType.Null;
} }
public override int GetHashCode() public abstract T GetKey(Field field);
{
return this.DictionaryHashCode();
}
} }
} }

133
src/Squidex.Core/Contents/IdContentData.cs

@ -0,0 +1,133 @@
// ==========================================================================
// NamedContentData.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
using Squidex.Core.Schemas;
using Squidex.Infrastructure;
// ReSharper disable InvertIf
namespace Squidex.Core.Contents
{
public sealed class IdContentData : ContentData<long>, IEquatable<IdContentData>
{
public IdContentData()
: base(EqualityComparer<long>.Default)
{
}
public IdContentData(IdContentData copy)
: base(copy, EqualityComparer<long>.Default)
{
}
public IdContentData MergeInto(IdContentData target)
{
return Merge(this, target);
}
public IdContentData ToCleaned()
{
return Clean(this, new IdContentData());
}
public IdContentData AddField(long id, ContentFieldData data)
{
Guard.GreaterThan(id, 0, nameof(id));
this[id] = data;
return this;
}
public IdContentData ToCleanedReferences(Schema schema, ISet<Guid> deletedReferencedIds)
{
var result = new IdContentData(this);
foreach (var field in schema.Fields)
{
if (field is IReferenceField referenceField)
{
var fieldKey = GetKey(field);
var fieldData = this.GetOrDefault(fieldKey);
if (fieldData == null)
{
continue;
}
foreach (var partitionValue in fieldData.Where(x => IsNotNull(x.Value)).ToList())
{
var newValue = referenceField.RemoveDeletedReferences(partitionValue.Value, deletedReferencedIds);
fieldData[partitionValue.Key] = newValue;
}
}
}
return result;
}
public NamedContentData ToNameModel(Schema schema, bool decodeJsonField)
{
Guard.NotNull(schema, nameof(schema));
var result = new NamedContentData();
foreach (var fieldValue in this)
{
if (!schema.FieldsById.TryGetValue(fieldValue.Key, out Field field))
{
continue;
}
if (decodeJsonField && field is JsonField)
{
var encodedValue = new ContentFieldData();
foreach (var partitionValue in fieldValue.Value)
{
if (IsNull(partitionValue.Value))
{
encodedValue[partitionValue.Key] = null;
}
else
{
var value = Encoding.UTF8.GetString(Convert.FromBase64String(partitionValue.Value.ToString()));
encodedValue[partitionValue.Key] = JToken.Parse(value);
}
}
result[field.Name] = encodedValue;
}
else
{
result[field.Name] = fieldValue.Value;
}
}
return result;
}
public bool Equals(IdContentData other)
{
return base.Equals(other);
}
public override long GetKey(Field field)
{
return field.Id;
}
}
}

193
src/Squidex.Core/Contents/NamedContentData.cs

@ -0,0 +1,193 @@
// ==========================================================================
// NamedContentData.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
using Squidex.Core.Schemas;
using Squidex.Infrastructure;
// ReSharper disable InvertIf
namespace Squidex.Core.Contents
{
public sealed class NamedContentData : ContentData<string>, IEquatable<NamedContentData>
{
public NamedContentData()
: base(StringComparer.OrdinalIgnoreCase)
{
}
public NamedContentData MergeInto(NamedContentData target)
{
return Merge(this, target);
}
public NamedContentData ToCleaned()
{
return Clean(this, new NamedContentData());
}
public NamedContentData AddField(string name, ContentFieldData data)
{
Guard.NotNullOrEmpty(name, nameof(name));
this[name] = data;
return this;
}
public IdContentData ToIdModel(Schema schema, bool encodeJsonField)
{
Guard.NotNull(schema, nameof(schema));
var result = new IdContentData();
foreach (var fieldValue in this)
{
if (!schema.FieldsByName.TryGetValue(fieldValue.Key, out Field field))
{
continue;
}
var fieldId = field.Id;
if (encodeJsonField && field is JsonField)
{
var encodedValue = new ContentFieldData();
foreach (var partitionValue in fieldValue.Value)
{
if (IsNull(partitionValue.Value))
{
encodedValue[partitionValue.Key] = null;
}
else
{
var value = Convert.ToBase64String(Encoding.UTF8.GetBytes(partitionValue.Value.ToString()));
encodedValue[partitionValue.Key] = value;
}
}
result[fieldId] = encodedValue;
}
else
{
result[fieldId] = fieldValue.Value;
}
}
return result;
}
public NamedContentData ToApiModel(Schema schema, LanguagesConfig languagesConfig, IReadOnlyCollection<Language> languagePreferences = null, bool excludeHidden = true)
{
Guard.NotNull(schema, nameof(schema));
Guard.NotNull(languagesConfig, nameof(languagesConfig));
var codeForInvariant = InvariantPartitioning.Instance.Master.Key;
var codeForMasterLanguage = languagesConfig.Master.Language.Iso2Code;
var result = new NamedContentData();
foreach (var fieldValue in this)
{
if (!schema.FieldsByName.TryGetValue(fieldValue.Key, out Field field) || (excludeHidden && field.IsHidden))
{
continue;
}
var fieldResult = new ContentFieldData();
var fieldValues = fieldValue.Value;
if (field.Paritioning.Equals(Partitioning.Language))
{
foreach (var languageConfig in languagesConfig)
{
var languageCode = languageConfig.Key;
if (fieldValues.TryGetValue(languageCode, out JToken value))
{
fieldResult.Add(languageCode, value);
}
else if (languageConfig == languagesConfig.Master && fieldValues.TryGetValue(codeForInvariant, out value))
{
fieldResult.Add(languageCode, value);
}
}
}
else
{
if (fieldValues.TryGetValue(codeForInvariant, out JToken value))
{
fieldResult.Add(codeForInvariant, value);
}
else if (fieldValues.TryGetValue(codeForMasterLanguage, out value))
{
fieldResult.Add(codeForInvariant, value);
}
else if (fieldValues.Count > 0)
{
fieldResult.Add(codeForInvariant, fieldValues.Values.First());
}
}
result.Add(GetKey(field), fieldResult);
}
return result;
}
public object ToLanguageModel(LanguagesConfig languagesConfig, IReadOnlyCollection<Language> languagePreferences = null)
{
Guard.NotNull(languagesConfig, nameof(languagesConfig));
if (languagePreferences == null || languagePreferences.Count == 0)
{
return this;
}
if (languagePreferences.Count == 1 && languagesConfig.TryGetConfig(languagePreferences.First(), out var languageConfig))
{
languagePreferences = languagePreferences.Union(languageConfig.Fallback).ToList();
}
var result = new Dictionary<string, JToken>();
foreach (var fieldValue in this)
{
var fieldValues = fieldValue.Value;
foreach (var language in languagePreferences)
{
if (fieldValues.TryGetValue(language, out JToken value) && value != null)
{
result[fieldValue.Key] = value;
break;
}
}
}
return result;
}
public bool Equals(NamedContentData other)
{
return base.Equals(other);
}
public override string GetKey(Field field)
{
return field.Name;
}
}
}

2
src/Squidex.Core/Schemas/AssetsField.cs

@ -54,7 +54,7 @@ namespace Squidex.Core.Schemas
public JToken RemoveDeletedReferences(JToken value, ISet<Guid> deletedReferencedIds) public JToken RemoveDeletedReferences(JToken value, ISet<Guid> deletedReferencedIds)
{ {
if (value == null) if (value == null || value.Type == JTokenType.Null)
{ {
return null; return null;
} }

2
src/Squidex.Events/Contents/ContentCreated.cs

@ -14,6 +14,6 @@ namespace Squidex.Events.Contents
[TypeName("ContentCreatedEvent")] [TypeName("ContentCreatedEvent")]
public class ContentCreated : ContentEvent public class ContentCreated : ContentEvent
{ {
public ContentData Data { get; set; } public NamedContentData Data { get; set; }
} }
} }

2
src/Squidex.Events/Contents/ContentUpdated.cs

@ -14,6 +14,6 @@ namespace Squidex.Events.Contents
[TypeName("ContentUpdatedEvent")] [TypeName("ContentUpdatedEvent")]
public class ContentUpdated : ContentEvent public class ContentUpdated : ContentEvent
{ {
public ContentData Data { get; set; } public NamedContentData Data { get; set; }
} }
} }

22
src/Squidex.Infrastructure.MongoDb/IMongoEntity.cs

@ -0,0 +1,22 @@
// ==========================================================================
// IMongoEntity.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using NodaTime;
namespace Squidex.Infrastructure.MongoDb
{
public interface IMongoEntity
{
Guid Id { get; set; }
Instant Created { get; set; }
Instant LastModified { get; set; }
}
}

2
src/Squidex.Infrastructure.MongoDb/MongoEntity.cs

@ -13,7 +13,7 @@ using NodaTime;
namespace Squidex.Infrastructure.MongoDb namespace Squidex.Infrastructure.MongoDb
{ {
public abstract class MongoEntity public abstract class MongoEntity : IMongoEntity
{ {
[BsonId] [BsonId]
[BsonElement] [BsonElement]

78
src/Squidex.Read.MongoDb/Contents/MongoContentEntity.cs

@ -14,7 +14,7 @@ using MongoDB.Bson;
using MongoDB.Bson.IO; using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Squidex.Core; using NodaTime;
using Squidex.Core.Contents; using Squidex.Core.Contents;
using Squidex.Core.Schemas; using Squidex.Core.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -27,53 +27,66 @@ using JsonConvert = Newtonsoft.Json.JsonConvert;
namespace Squidex.Read.MongoDb.Contents namespace Squidex.Read.MongoDb.Contents
{ {
public sealed class MongoContentEntity : MongoEntity, IContentEntity public sealed class MongoContentEntity : IContentEntity, IMongoEntity
{ {
private static readonly JsonWriterSettings Settings = new JsonWriterSettings { OutputMode = JsonOutputMode.Strict }; private static readonly JsonWriterSettings Settings = new JsonWriterSettings { OutputMode = JsonOutputMode.Strict };
private const int MaxLength = 1024 * 1024; private const int MaxLength = 1024 * 1024;
private ContentData contentData; private NamedContentData contentData;
[BsonRequired] [BsonId]
[BsonElement] [BsonElement]
[BsonRepresentation(BsonType.String)]
public Guid Id { get; set; }
[BsonRequired]
[BsonElement("ct")]
public Instant Created { get; set; }
[BsonRequired]
[BsonElement("mt")]
public Instant LastModified { get; set; }
[BsonRequired]
[BsonElement("pu")]
public bool IsPublished { get; set; } public bool IsPublished { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement("dt")]
public string Text { get; set; } public string DataText { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement("vs")]
public long Version { get; set; } public long Version { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement("ai")]
public Guid AppId { get; set; } public Guid AppId { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement("si")]
public Guid SchemaId { get; set; } public Guid SchemaId { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement("cb")]
public RefToken CreatedBy { get; set; } public RefToken CreatedBy { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement("mb")]
public RefToken LastModifiedBy { get; set; } public RefToken LastModifiedBy { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement("do")]
public BsonDocument Data { get; set; } public BsonDocument DataObject { get; set; }
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement("rf")]
public List<Guid> ReferencedIds { get; set; } = new List<Guid>(); public List<Guid> ReferencedIds { get; set; } = new List<Guid>();
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement("rd")]
public List<Guid> ReferencedIdsDeleted { get; set; } = new List<Guid>(); public List<Guid> ReferencedIdsDeleted { get; set; } = new List<Guid>();
ContentData IContentEntity.Data NamedContentData IContentEntity.Data
{ {
get get
{ {
@ -83,13 +96,14 @@ namespace Squidex.Read.MongoDb.Contents
public void ParseData(Schema schema) public void ParseData(Schema schema)
{ {
if (Data != null) if (DataObject != null)
{ {
var jsonString = Data.ToJson(Settings); var jsonString = DataObject.ToJson(Settings);
contentData = JsonConvert.DeserializeObject<ContentData>(jsonString); contentData =
contentData = contentData.ToCleanedReferences(schema, new HashSet<Guid>(ReferencedIdsDeleted)); JsonConvert.DeserializeObject<IdContentData>(jsonString)
contentData = contentData.ToNameModel(schema, true); .ToCleanedReferences(schema, new HashSet<Guid>(ReferencedIdsDeleted))
.ToNameModel(schema, true);
} }
else else
{ {
@ -97,27 +111,27 @@ namespace Squidex.Read.MongoDb.Contents
} }
} }
public void SetData(Schema schema, ContentData newContentData) public void SetData(Schema schema, NamedContentData newContentData)
{ {
newContentData = newContentData?.ToIdModel(schema, true);
if (newContentData != null) if (newContentData != null)
{ {
var jsonString = JsonConvert.SerializeObject(newContentData); var idModel = newContentData.ToIdModel(schema, true);
var jsonString = JsonConvert.SerializeObject(idModel);
DataObject = BsonDocument.Parse(jsonString);
DataText = ExtractText(idModel);
Data = BsonDocument.Parse(jsonString); ReferencedIds = idModel.GetReferencedIds(schema).ToList();
} }
else else
{ {
Data = null; DataObject = null;
DataText = string.Empty;
} }
ReferencedIds = newContentData?.GetReferencedIds(schema).ToList() ?? new List<Guid>();
Text = ExtractText(newContentData);
} }
private static string ExtractText(ContentData data) private static string ExtractText(IdContentData data)
{ {
if (data == null) if (data == null)
{ {

3
src/Squidex.Read.MongoDb/Contents/MongoContentRepository_EventHandling.cs

@ -8,7 +8,6 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver; using MongoDB.Driver;
using Squidex.Events.Assets; using Squidex.Events.Assets;
using Squidex.Events.Contents; using Squidex.Events.Contents;
@ -65,7 +64,7 @@ namespace Squidex.Read.MongoDb.Contents
{ {
await collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.ReferencedIds)); await collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.ReferencedIds));
await collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.IsPublished)); await collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.IsPublished));
await collection.Indexes.CreateOneAsync(IndexKeys.Text(x => x.Text)); await collection.Indexes.CreateOneAsync(IndexKeys.Text(x => x.DataText));
}); });
} }

18
src/Squidex.Read.MongoDb/Utils/EntityMapper.cs

@ -17,7 +17,7 @@ namespace Squidex.Read.MongoDb.Utils
{ {
public static class EntityMapper public static class EntityMapper
{ {
public static T Create<T>(SquidexEvent @event, EnvelopeHeaders headers) where T : MongoEntity, new() public static T Create<T>(SquidexEvent @event, EnvelopeHeaders headers) where T : IMongoEntity, new()
{ {
var entity = new T(); var entity = new T();
@ -32,7 +32,7 @@ namespace Squidex.Read.MongoDb.Utils
return Update(@event, headers, entity); return Update(@event, headers, entity);
} }
public static T Update<T>(SquidexEvent @event, EnvelopeHeaders headers, T entity) where T : MongoEntity, new() public static T Update<T>(SquidexEvent @event, EnvelopeHeaders headers, T entity) where T : IMongoEntity, new()
{ {
SetVersion(headers, entity); SetVersion(headers, entity);
SetLastModified(headers, entity); SetLastModified(headers, entity);
@ -41,22 +41,22 @@ namespace Squidex.Read.MongoDb.Utils
return entity; return entity;
} }
private static void SetId(EnvelopeHeaders headers, MongoEntity entity) private static void SetId(EnvelopeHeaders headers, IMongoEntity entity)
{ {
entity.Id = headers.AggregateId(); entity.Id = headers.AggregateId();
} }
private static void SetCreated(EnvelopeHeaders headers, MongoEntity entity) private static void SetCreated(EnvelopeHeaders headers, IMongoEntity entity)
{ {
entity.Created = headers.Timestamp(); entity.Created = headers.Timestamp();
} }
private static void SetLastModified(EnvelopeHeaders headers, MongoEntity entity) private static void SetLastModified(EnvelopeHeaders headers, IMongoEntity entity)
{ {
entity.LastModified = headers.Timestamp(); entity.LastModified = headers.Timestamp();
} }
private static void SetVersion(EnvelopeHeaders headers, MongoEntity entity) private static void SetVersion(EnvelopeHeaders headers, IMongoEntity entity)
{ {
if (entity is IEntityWithVersion withVersion) if (entity is IEntityWithVersion withVersion)
{ {
@ -64,7 +64,7 @@ namespace Squidex.Read.MongoDb.Utils
} }
} }
private static void SetCreatedBy(SquidexEvent @event, MongoEntity entity) private static void SetCreatedBy(SquidexEvent @event, IMongoEntity entity)
{ {
if (entity is IEntityWithCreatedBy withCreatedBy) if (entity is IEntityWithCreatedBy withCreatedBy)
{ {
@ -72,7 +72,7 @@ namespace Squidex.Read.MongoDb.Utils
} }
} }
private static void SetLastModifiedBy(SquidexEvent @event, MongoEntity entity) private static void SetLastModifiedBy(SquidexEvent @event, IMongoEntity entity)
{ {
if (entity is IEntityWithLastModifiedBy withModifiedBy) if (entity is IEntityWithLastModifiedBy withModifiedBy)
{ {
@ -80,7 +80,7 @@ namespace Squidex.Read.MongoDb.Utils
} }
} }
private static void SetAppId(SquidexEvent @event, MongoEntity entity) private static void SetAppId(SquidexEvent @event, IMongoEntity entity)
{ {
if (entity is IAppRefEntity appEntity && @event is AppEvent appEvent) if (entity is IAppRefEntity appEntity && @event is AppEvent appEvent)
{ {

6
src/Squidex.Read.MongoDb/Utils/MongoCollectionExtensions.cs

@ -18,7 +18,7 @@ namespace Squidex.Read.MongoDb.Utils
{ {
public static class MongoCollectionExtensions public static class MongoCollectionExtensions
{ {
public static Task CreateAsync<T>(this IMongoCollection<T> collection, SquidexEvent @event, EnvelopeHeaders headers, Action<T> updater) where T : MongoEntity, new() public static Task CreateAsync<T>(this IMongoCollection<T> collection, SquidexEvent @event, EnvelopeHeaders headers, Action<T> updater) where T : IMongoEntity, new()
{ {
var entity = EntityMapper.Create<T>(@event, headers); var entity = EntityMapper.Create<T>(@event, headers);
@ -27,7 +27,7 @@ namespace Squidex.Read.MongoDb.Utils
return collection.InsertOneIfNotExistsAsync(entity); return collection.InsertOneIfNotExistsAsync(entity);
} }
public static async Task CreateAsync<T>(this IMongoCollection<T> collection, SquidexEvent @event, EnvelopeHeaders headers, Func<T, Task> updater) where T : MongoEntity, new() public static async Task CreateAsync<T>(this IMongoCollection<T> collection, SquidexEvent @event, EnvelopeHeaders headers, Func<T, Task> updater) where T : IMongoEntity, new()
{ {
var entity = EntityMapper.Create<T>(@event, headers); var entity = EntityMapper.Create<T>(@event, headers);
@ -36,7 +36,7 @@ namespace Squidex.Read.MongoDb.Utils
await collection.InsertOneIfNotExistsAsync(entity); await collection.InsertOneIfNotExistsAsync(entity);
} }
public static async Task UpdateAsync<T>(this IMongoCollection<T> collection, SquidexEvent @event, EnvelopeHeaders headers, Action<T> updater) where T : MongoEntity, new() public static async Task UpdateAsync<T>(this IMongoCollection<T> collection, SquidexEvent @event, EnvelopeHeaders headers, Action<T> updater) where T : IMongoEntity, new()
{ {
var entity = await collection.Find(t => t.Id == headers.AggregateId()).FirstOrDefaultAsync(); var entity = await collection.Find(t => t.Id == headers.AggregateId()).FirstOrDefaultAsync();

2
src/Squidex.Read/Contents/IContentEntity.cs

@ -14,6 +14,6 @@ namespace Squidex.Read.Contents
{ {
bool IsPublished { get; } bool IsPublished { get; }
ContentData Data { get; } NamedContentData Data { get; }
} }
} }

2
src/Squidex.Write/Contents/Commands/ContentDataCommand.cs

@ -14,7 +14,7 @@ namespace Squidex.Write.Contents.Commands
{ {
public abstract class ContentDataCommand : ContentCommand, IValidatable public abstract class ContentDataCommand : ContentCommand, IValidatable
{ {
public ContentData Data { get; set; } public NamedContentData Data { get; set; }
public void Validate(IList<ValidationError> errors) public void Validate(IList<ValidationError> errors)
{ {

2
src/Squidex.Write/Contents/ContentDomainObject.cs

@ -23,7 +23,7 @@ namespace Squidex.Write.Contents
private bool isDeleted; private bool isDeleted;
private bool isCreated; private bool isCreated;
private bool isPublished; private bool isPublished;
private ContentData data; private NamedContentData data;
public bool IsDeleted public bool IsDeleted
{ {

8
src/Squidex/Controllers/ContentApi/ContentsController.cs

@ -112,13 +112,13 @@ namespace Squidex.Controllers.ContentApi
[HttpPost] [HttpPost]
[Route("content/{app}/{name}/")] [Route("content/{app}/{name}/")]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostContent([FromBody] ContentData request, [FromQuery] bool publish = false) public async Task<IActionResult> PostContent([FromBody] NamedContentData request, [FromQuery] bool publish = false)
{ {
var command = new CreateContent { ContentId = Guid.NewGuid(), Data = request.ToCleaned(), Publish = publish }; var command = new CreateContent { ContentId = Guid.NewGuid(), Data = request.ToCleaned(), Publish = publish };
var context = await CommandBus.PublishAsync(command); var context = await CommandBus.PublishAsync(command);
var result = context.Result<EntityCreatedResult<ContentData>>(); var result = context.Result<EntityCreatedResult<NamedContentData>>();
var response = ContentDto.Create(command, result); var response = ContentDto.Create(command, result);
return CreatedAtAction(nameof(GetContent), new { id = response.Id }, response); return CreatedAtAction(nameof(GetContent), new { id = response.Id }, response);
@ -127,7 +127,7 @@ namespace Squidex.Controllers.ContentApi
[HttpPut] [HttpPut]
[Route("content/{app}/{name}/{id}")] [Route("content/{app}/{name}/{id}")]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutContent(Guid id, [FromBody] ContentData request) public async Task<IActionResult> PutContent(Guid id, [FromBody] NamedContentData request)
{ {
var command = new UpdateContent { ContentId = id, Data = request.ToCleaned() }; var command = new UpdateContent { ContentId = id, Data = request.ToCleaned() };
@ -139,7 +139,7 @@ namespace Squidex.Controllers.ContentApi
[HttpPatch] [HttpPatch]
[Route("content/{app}/{name}/{id}")] [Route("content/{app}/{name}/{id}")]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PatchContent(Guid id, [FromBody] ContentData request) public async Task<IActionResult> PatchContent(Guid id, [FromBody] NamedContentData request)
{ {
var command = new PatchContent { ContentId = id, Data = request.ToCleaned() }; var command = new PatchContent { ContentId = id, Data = request.ToCleaned() };

2
src/Squidex/Controllers/ContentApi/Models/ContentDto.cs

@ -61,7 +61,7 @@ namespace Squidex.Controllers.ContentApi.Models
/// </summary> /// </summary>
public long Version { get; set; } public long Version { get; set; }
public static ContentDto Create(CreateContent command, EntityCreatedResult<ContentData> result) public static ContentDto Create(CreateContent command, EntityCreatedResult<NamedContentData> result)
{ {
var now = SystemClock.Instance.GetCurrentInstant(); var now = SystemClock.Instance.GetCurrentInstant();

12
src/Squidex/app/shared/components/assets-editor.component.ts

@ -74,10 +74,12 @@ export class AssetsEditorComponent extends AppComponentBase implements ControlVa
this.oldAssets = ImmutableArray.empty<AssetDto>(); this.oldAssets = ImmutableArray.empty<AssetDto>();
if (value && value.length > 0) { if (value && value.length > 0) {
const assetIds: string[] = value;
this.appNameOnce() this.appNameOnce()
.switchMap(app => this.assetsService.getAssets(app, 10000, 0, undefined, undefined, value)) .switchMap(app => this.assetsService.getAssets(app, 10000, 0, undefined, undefined, value))
.subscribe(dtos => { .subscribe(dtos => {
this.oldAssets = ImmutableArray.of(dtos.items); this.oldAssets = ImmutableArray.of(assetIds.map(id => dtos.items.find(x => x.id === id)));
}); });
} }
} }
@ -100,14 +102,16 @@ export class AssetsEditorComponent extends AppComponentBase implements ControlVa
} }
} }
public onAssetLoaded(file: File, asset: AssetDto) { public onAssetDropped(asset: AssetDto) {
this.newAssets = this.newAssets.remove(file); if (asset) {
this.oldAssets = this.oldAssets.pushFront(asset); this.oldAssets = this.oldAssets.pushFront(asset);
this.updateValue(); this.updateValue();
} }
}
public onAssetDropped(asset: AssetDto) { public onAssetLoaded(file: File, asset: AssetDto) {
this.newAssets = this.newAssets.remove(file);
this.oldAssets = this.oldAssets.pushFront(asset); this.oldAssets = this.oldAssets.pushFront(asset);
this.updateValue(); this.updateValue();

2
tests/Squidex.Core.Tests/ContentEnrichmentTests.cs

@ -43,7 +43,7 @@ namespace Squidex.Core
new GeolocationFieldProperties())); new GeolocationFieldProperties()));
var data = var data =
new ContentData() new NamedContentData()
.AddField("my-string", .AddField("my-string",
new ContentFieldData() new ContentFieldData()
.AddValue("de", "de-string")) .AddValue("de", "de-string"))

30
tests/Squidex.Core.Tests/ContentValidationTests.cs

@ -26,7 +26,7 @@ namespace Squidex.Core
public async Task Should_add_error_if_validating_data_with_unknown_field() public async Task Should_add_error_if_validating_data_with_unknown_field()
{ {
var data = var data =
new ContentData() new NamedContentData()
.AddField("unknown", .AddField("unknown",
new ContentFieldData()); new ContentFieldData());
@ -45,7 +45,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { MaxValue = 100 })); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { MaxValue = 100 }));
var data = var data =
new ContentData() new NamedContentData()
.AddField("my-field", .AddField("my-field",
new ContentFieldData() new ContentFieldData()
.SetValue(1000)); .SetValue(1000));
@ -65,7 +65,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant)); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant));
var data = var data =
new ContentData() new NamedContentData()
.AddField("my-field", .AddField("my-field",
new ContentFieldData() new ContentFieldData()
.AddValue("es", 1) .AddValue("es", 1)
@ -87,7 +87,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language, new NumberFieldProperties { IsRequired = true })); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language, new NumberFieldProperties { IsRequired = true }));
var data = var data =
new ContentData(); new NamedContentData();
await data.ValidateAsync(schema, languagesConfig.ToResolver(), errors); await data.ValidateAsync(schema, languagesConfig.ToResolver(), errors);
@ -105,7 +105,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { IsRequired = true })); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { IsRequired = true }));
var data = var data =
new ContentData(); new NamedContentData();
await data.ValidateAsync(schema, languagesConfig.ToResolver(), errors); await data.ValidateAsync(schema, languagesConfig.ToResolver(), errors);
@ -122,7 +122,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language)); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language));
var data = var data =
new ContentData() new NamedContentData()
.AddField("my-field", .AddField("my-field",
new ContentFieldData() new ContentFieldData()
.AddValue("de", 1) .AddValue("de", 1)
@ -146,7 +146,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new StringField(1, "my-field", Partitioning.Language, new StringFieldProperties { IsRequired = true })); schema = schema.AddOrUpdateField(new StringField(1, "my-field", Partitioning.Language, new StringFieldProperties { IsRequired = true }));
var data = var data =
new ContentData() new NamedContentData()
.AddField("my-field", .AddField("my-field",
new ContentFieldData() new ContentFieldData()
.AddValue("es", "value")); .AddValue("es", "value"));
@ -162,7 +162,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language)); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language));
var data = var data =
new ContentData() new NamedContentData()
.AddField("my-field", .AddField("my-field",
new ContentFieldData() new ContentFieldData()
.AddValue("es", 1) .AddValue("es", 1)
@ -182,7 +182,7 @@ namespace Squidex.Core
public async Task Should_add_error_if_validating_partial_data_with_unknown_field() public async Task Should_add_error_if_validating_partial_data_with_unknown_field()
{ {
var data = var data =
new ContentData() new NamedContentData()
.AddField("unknown", .AddField("unknown",
new ContentFieldData()); new ContentFieldData());
@ -201,7 +201,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { MaxValue = 100 })); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { MaxValue = 100 }));
var data = var data =
new ContentData() new NamedContentData()
.AddField("my-field", .AddField("my-field",
new ContentFieldData() new ContentFieldData()
.SetValue(1000)); .SetValue(1000));
@ -221,7 +221,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant)); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant));
var data = var data =
new ContentData() new NamedContentData()
.AddField("my-field", .AddField("my-field",
new ContentFieldData() new ContentFieldData()
.AddValue("es", 1) .AddValue("es", 1)
@ -243,7 +243,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language, new NumberFieldProperties { IsRequired = true })); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language, new NumberFieldProperties { IsRequired = true }));
var data = var data =
new ContentData(); new NamedContentData();
await data.ValidatePartialAsync(schema, languagesConfig.ToResolver(), errors); await data.ValidatePartialAsync(schema, languagesConfig.ToResolver(), errors);
@ -256,7 +256,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { IsRequired = true })); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Invariant, new NumberFieldProperties { IsRequired = true }));
var data = var data =
new ContentData(); new NamedContentData();
await data.ValidatePartialAsync(schema, languagesConfig.ToResolver(), errors); await data.ValidatePartialAsync(schema, languagesConfig.ToResolver(), errors);
@ -269,7 +269,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language)); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language));
var data = var data =
new ContentData() new NamedContentData()
.AddField("my-field", .AddField("my-field",
new ContentFieldData() new ContentFieldData()
.AddValue("de", 1) .AddValue("de", 1)
@ -290,7 +290,7 @@ namespace Squidex.Core
schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language)); schema = schema.AddOrUpdateField(new NumberField(1, "my-field", Partitioning.Language));
var data = var data =
new ContentData() new NamedContentData()
.AddField("my-field", .AddField("my-field",
new ContentFieldData() new ContentFieldData()
.AddValue("es", 1) .AddValue("es", 1)

255
tests/Squidex.Core.Tests/Contents/ContentDataTests.cs

@ -6,7 +6,10 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Moq;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Squidex.Core.Schemas; using Squidex.Core.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -21,6 +24,8 @@ namespace Squidex.Core.Contents
.AddOrUpdateField(new NumberField(1, "field1", Partitioning.Language)) .AddOrUpdateField(new NumberField(1, "field1", Partitioning.Language))
.AddOrUpdateField(new NumberField(2, "field2", Partitioning.Invariant)) .AddOrUpdateField(new NumberField(2, "field2", Partitioning.Invariant))
.AddOrUpdateField(new NumberField(3, "field3", Partitioning.Invariant).Hide()) .AddOrUpdateField(new NumberField(3, "field3", Partitioning.Invariant).Hide())
.AddOrUpdateField(new AssetsField(5, "assets1", Partitioning.Invariant, new Mock<IAssetTester>().Object))
.AddOrUpdateField(new AssetsField(6, "assets2", Partitioning.Invariant, new Mock<IAssetTester>().Object))
.AddOrUpdateField(new JsonField(4, "json", Partitioning.Language)); .AddOrUpdateField(new JsonField(4, "json", Partitioning.Language));
private readonly LanguagesConfig languagesConfig = LanguagesConfig.Create(Language.EN, Language.DE); private readonly LanguagesConfig languagesConfig = LanguagesConfig.Create(Language.EN, Language.DE);
@ -28,7 +33,7 @@ namespace Squidex.Core.Contents
public void Should_convert_to_id_model() public void Should_convert_to_id_model()
{ {
var input = var input =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("en", "en_string") .AddValue("en", "en_string")
@ -43,12 +48,12 @@ namespace Squidex.Core.Contents
var actual = input.ToIdModel(schema, false); var actual = input.ToIdModel(schema, false);
var expected = var expected =
new ContentData() new IdContentData()
.AddField("1", .AddField(1,
new ContentFieldData() new ContentFieldData()
.AddValue("en", "en_string") .AddValue("en", "en_string")
.AddValue("de", "de_string")) .AddValue("de", "de_string"))
.AddField("2", .AddField(2,
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 3)); .AddValue("iv", 3));
@ -59,7 +64,7 @@ namespace Squidex.Core.Contents
public void Should_convert_to_encoded_id_model() public void Should_convert_to_encoded_id_model()
{ {
var input = var input =
new ContentData() new NamedContentData()
.AddField("json", .AddField("json",
new ContentFieldData() new ContentFieldData()
.AddValue("en", new JObject()) .AddValue("en", new JObject())
@ -69,8 +74,8 @@ namespace Squidex.Core.Contents
var actual = input.ToIdModel(schema, true); var actual = input.ToIdModel(schema, true);
var expected = var expected =
new ContentData() new IdContentData()
.AddField("4", .AddField(4,
new ContentFieldData() new ContentFieldData()
.AddValue("en", "e30=") .AddValue("en", "e30=")
.AddValue("de", null) .AddValue("de", null)
@ -80,25 +85,25 @@ namespace Squidex.Core.Contents
} }
[Fact] [Fact]
public void Should_convert_from_id_model() public void Should_convert_to_name_model()
{ {
var input = var input =
new ContentData() new IdContentData()
.AddField("1", .AddField(1,
new ContentFieldData() new ContentFieldData()
.AddValue("en", "en_string") .AddValue("en", "en_string")
.AddValue("de", "de_string")) .AddValue("de", "de_string"))
.AddField("2", .AddField(2,
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 3)) .AddValue("iv", 3))
.AddField("99", .AddField(99,
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 3)); .AddValue("iv", 3));
var actual = input.ToNameModel(schema, false); var actual = input.ToNameModel(schema, false);
var expected = var expected =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("en", "en_string") .AddValue("en", "en_string")
@ -111,11 +116,11 @@ namespace Squidex.Core.Contents
} }
[Fact] [Fact]
public void Should_convert_from_encoded_id_model() public void Should_convert_to_encoded_name_model()
{ {
var input = var input =
new ContentData() new IdContentData()
.AddField("4", .AddField(4,
new ContentFieldData() new ContentFieldData()
.AddValue("en", "e30=") .AddValue("en", "e30=")
.AddValue("de", null) .AddValue("de", null)
@ -129,15 +134,8 @@ namespace Squidex.Core.Contents
[Fact] [Fact]
public void Should_cleanup_old_fields() public void Should_cleanup_old_fields()
{ {
var expected =
new ContentData()
.AddField("field1",
new ContentFieldData()
.AddValue("en", "en_string")
.AddValue("de", "de_string"));
var input = var input =
new ContentData() new NamedContentData()
.AddField("field0", .AddField("field0",
new ContentFieldData() new ContentFieldData()
.AddValue("en", "en_string")) .AddValue("en", "en_string"))
@ -148,21 +146,21 @@ namespace Squidex.Core.Contents
var actual = input.ToApiModel(schema, languagesConfig); var actual = input.ToApiModel(schema, languagesConfig);
Assert.Equal(expected, actual);
}
[Fact]
public void Should_cleanup_old_languages()
{
var expected = var expected =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("en", "en_string") .AddValue("en", "en_string")
.AddValue("de", "de_string")); .AddValue("de", "de_string"));
Assert.Equal(expected, actual);
}
[Fact]
public void Should_cleanup_old_languages()
{
var input = var input =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("en", "en_string") .AddValue("en", "en_string")
@ -171,20 +169,21 @@ namespace Squidex.Core.Contents
var actual = input.ToApiModel(schema, languagesConfig); var actual = input.ToApiModel(schema, languagesConfig);
var expected =
new NamedContentData()
.AddField("field1",
new ContentFieldData()
.AddValue("en", "en_string")
.AddValue("de", "de_string"));
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
[Fact] [Fact]
public void Should_provide_invariant_from_master_language() public void Should_provide_invariant_from_master_language()
{ {
var expected =
new ContentData()
.AddField("field2",
new ContentFieldData()
.AddValue("iv", 3));
var input = var input =
new ContentData() new NamedContentData()
.AddField("field2", .AddField("field2",
new ContentFieldData() new ContentFieldData()
.AddValue("de", 2) .AddValue("de", 2)
@ -192,62 +191,84 @@ namespace Squidex.Core.Contents
var actual = input.ToApiModel(schema, languagesConfig); var actual = input.ToApiModel(schema, languagesConfig);
var expected =
new NamedContentData()
.AddField("field2",
new ContentFieldData()
.AddValue("iv", 3));
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
[Fact] [Fact]
public void Should_provide_master_language_from_invariant() public void Should_provide_master_language_from_invariant()
{ {
var expected =
new ContentData()
.AddField("field1",
new ContentFieldData()
.AddValue("en", 3));
var input = var input =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 3)); .AddValue("iv", 3));
var actual = input.ToApiModel(schema, languagesConfig); var actual = input.ToApiModel(schema, languagesConfig);
var expected =
new NamedContentData()
.AddField("field1",
new ContentFieldData()
.AddValue("en", 3));
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
[Fact] [Fact]
public void Should_remove_null_values_when_cleaning() public void Should_remove_null_values_from_name_model_when_cleaning()
{ {
var input =
new NamedContentData()
.AddField("field1", null)
.AddField("field2",
new ContentFieldData()
.AddValue("en", 2)
.AddValue("it", null));
var actual = input.ToCleaned();
var expected = var expected =
new ContentData() new NamedContentData()
.AddField("field2", .AddField("field2",
new ContentFieldData() new ContentFieldData()
.AddValue("en", 2)); .AddValue("en", 2));
Assert.Equal(expected, actual);
}
[Fact]
public void Should_remove_null_values_from_id_model_when_cleaning()
{
var input = var input =
new ContentData() new IdContentData()
.AddField("field1", null) .AddField(1, null)
.AddField("field2", .AddField(2,
new ContentFieldData() new ContentFieldData()
.AddValue("en", 2) .AddValue("en", 2)
.AddValue("it", null)); .AddValue("it", null));
var actual = input.ToCleaned(); var actual = input.ToCleaned();
var expected =
new IdContentData()
.AddField(2,
new ContentFieldData()
.AddValue("en", 2));
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
[Fact] [Fact]
public void Should_provide_invariant_from_first_language() public void Should_provide_invariant_from_first_language()
{ {
var expected =
new ContentData()
.AddField("field2",
new ContentFieldData()
.AddValue("iv", 2));
var input = var input =
new ContentData() new NamedContentData()
.AddField("field2", .AddField("field2",
new ContentFieldData() new ContentFieldData()
.AddValue("de", 2) .AddValue("de", 2)
@ -255,20 +276,20 @@ namespace Squidex.Core.Contents
var actual = input.ToApiModel(schema, languagesConfig); var actual = input.ToApiModel(schema, languagesConfig);
var expected =
new NamedContentData()
.AddField("field2",
new ContentFieldData()
.AddValue("iv", 2));
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
[Fact] [Fact]
public void Should_not_include_hidden_field() public void Should_not_include_hidden_field()
{ {
var expected =
new ContentData()
.AddField("field2",
new ContentFieldData()
.AddValue("iv", 5));
var input = var input =
new ContentData() new NamedContentData()
.AddField("field2", .AddField("field2",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 5)) .AddValue("iv", 5))
@ -278,6 +299,12 @@ namespace Squidex.Core.Contents
var actual = input.ToApiModel(schema, languagesConfig); var actual = input.ToApiModel(schema, languagesConfig);
var expected =
new NamedContentData()
.AddField("field2",
new ContentFieldData()
.AddValue("iv", 5));
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
@ -285,7 +312,7 @@ namespace Squidex.Core.Contents
public void Should_return_original_when_no_language_preferences_defined() public void Should_return_original_when_no_language_preferences_defined()
{ {
var data = var data =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 1)); .AddValue("iv", 1));
@ -297,7 +324,7 @@ namespace Squidex.Core.Contents
public void Should_return_flat_list_when_single_languages_specified() public void Should_return_flat_list_when_single_languages_specified()
{ {
var data = var data =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("de", 1) .AddValue("de", 1)
@ -333,7 +360,7 @@ namespace Squidex.Core.Contents
public void Should_return_flat_list_when_languages_specified() public void Should_return_flat_list_when_languages_specified()
{ {
var data = var data =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("de", 1) .AddValue("de", 1)
@ -362,10 +389,10 @@ namespace Squidex.Core.Contents
} }
[Fact] [Fact]
public void Should_merge_two_data() public void Should_merge_two_name_models()
{ {
var lhs = var lhs =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 1)) .AddValue("iv", 1))
@ -374,7 +401,7 @@ namespace Squidex.Core.Contents
.AddValue("de", 2)); .AddValue("de", 2));
var rhs = var rhs =
new ContentData() new NamedContentData()
.AddField("field2", .AddField("field2",
new ContentFieldData() new ContentFieldData()
.AddValue("en", 3)) .AddValue("en", 3))
@ -383,7 +410,7 @@ namespace Squidex.Core.Contents
.AddValue("iv", 4)); .AddValue("iv", 4));
var expected = var expected =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 1)) .AddValue("iv", 1))
@ -400,11 +427,50 @@ namespace Squidex.Core.Contents
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
[Fact]
public void Should_merge_two_id_models()
{
var lhs =
new IdContentData()
.AddField(1,
new ContentFieldData()
.AddValue("iv", 1))
.AddField(2,
new ContentFieldData()
.AddValue("de", 2));
var rhs =
new IdContentData()
.AddField(2,
new ContentFieldData()
.AddValue("en", 3))
.AddField(3,
new ContentFieldData()
.AddValue("iv", 4));
var expected =
new IdContentData()
.AddField(1,
new ContentFieldData()
.AddValue("iv", 1))
.AddField(2,
new ContentFieldData()
.AddValue("de", 2)
.AddValue("en", 3))
.AddField(3,
new ContentFieldData()
.AddValue("iv", 4));
var actual = lhs.MergeInto(rhs);
Assert.Equal(expected, actual);
}
[Fact] [Fact]
public void Should_be_equal_when_data_have_same_structure() public void Should_be_equal_when_data_have_same_structure()
{ {
var lhs = var lhs =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 2)) .AddValue("iv", 2))
@ -413,7 +479,7 @@ namespace Squidex.Core.Contents
.AddValue("iv", 2)); .AddValue("iv", 2));
var rhs = var rhs =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 2)) .AddValue("iv", 2))
@ -430,7 +496,7 @@ namespace Squidex.Core.Contents
public void Should_not_be_equal_when_data_have_not_same_structure() public void Should_not_be_equal_when_data_have_not_same_structure()
{ {
var lhs = var lhs =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 2)) .AddValue("iv", 2))
@ -439,7 +505,7 @@ namespace Squidex.Core.Contents
.AddValue("iv", 2)); .AddValue("iv", 2));
var rhs = var rhs =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("en", 2)) .AddValue("en", 2))
@ -451,5 +517,42 @@ namespace Squidex.Core.Contents
Assert.False(lhs.Equals((object)rhs)); Assert.False(lhs.Equals((object)rhs));
Assert.NotEqual(lhs.GetHashCode(), rhs.GetHashCode()); Assert.NotEqual(lhs.GetHashCode(), rhs.GetHashCode());
} }
[Fact]
public void Should_remove_ids()
{
var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid();
var input =
new NamedContentData()
.AddField("assets1",
new ContentFieldData()
.AddValue("iv", new JArray(id1.ToString(), id2.ToString())));
var ids = input.GetReferencedIds(schema).ToArray();
Assert.Equal(new[] { id1, id2 }, ids);
}
[Fact]
public void Should_cleanup_deleted_ids()
{
var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid();
var input =
new IdContentData()
.AddField(5,
new ContentFieldData()
.AddValue("iv", new JArray(id1.ToString(), id2.ToString())));
var actual = input.ToCleanedReferences(schema, new HashSet<Guid>(new[] { id2 }));
var cleanedValue = (JArray)actual[5]["iv"];
Assert.Equal(1, cleanedValue.Count);
Assert.Equal(id1.ToString(), cleanedValue[0]);
}
} }
} }

81
tests/Squidex.Core.Tests/Schemas/AssetsFieldTests.cs

@ -8,6 +8,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using FluentAssertions; using FluentAssertions;
using Moq; using Moq;
@ -110,6 +111,86 @@ namespace Squidex.Core.Schemas
new[] { $"<FIELD> contains invalid asset '{assetId}'" }); new[] { $"<FIELD> contains invalid asset '{assetId}'" });
} }
[Fact]
public void Should_return_ids()
{
var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid();
var sut = new AssetsField(1, "my-asset", Partitioning.Invariant, assetTester.Object);
var result = sut.GetReferencedIds(CreateValue(id1, id2)).ToArray();
Assert.Equal(new[] { id1, id2 }, result);
}
[Fact]
public void Should_empty_list_for_referenced_ids_when_null()
{
var sut = new AssetsField(1, "my-asset", Partitioning.Invariant, assetTester.Object);
var result = sut.GetReferencedIds(null).ToArray();
Assert.Empty(result);
}
[Fact]
public void Should_empty_list_for_referenced_ids_when_other_type()
{
var sut = new AssetsField(1, "my-asset", Partitioning.Invariant, assetTester.Object);
var result = sut.GetReferencedIds("invalid").ToArray();
Assert.Empty(result);
}
[Fact]
public void Should_return_null_when_removing_references_from_null_array()
{
var sut = new AssetsField(1, "my-asset", Partitioning.Invariant, assetTester.Object);
var result = sut.RemoveDeletedReferences(null, null);
Assert.Null(result);
}
[Fact]
public void Should_return_null_when_removing_references_from_null_json_array()
{
var sut = new AssetsField(1, "my-asset", Partitioning.Invariant, assetTester.Object);
var result = sut.RemoveDeletedReferences(JValue.CreateNull(), null);
Assert.Null(result);
}
[Fact]
public void Should_remove_deleted_references()
{
var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid();
var sut = new AssetsField(1, "my-asset", Partitioning.Invariant, assetTester.Object);
var result = sut.RemoveDeletedReferences(CreateValue(id1, id2), new HashSet<Guid>(new[] { id2 }));
Assert.Equal(CreateValue(id1), result);
}
[Fact]
public void Should_return_same_token_when_removing_references_and_nothing_to_remove()
{
var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid();
var sut = new AssetsField(1, "my-asset", Partitioning.Invariant, assetTester.Object);
var token = CreateValue(id1, id2);
var result = sut.RemoveDeletedReferences(token, new HashSet<Guid>(new[] { Guid.NewGuid() }));
Assert.Same(token, result);
}
private static JToken CreateValue(params Guid[] ids) private static JToken CreateValue(params Guid[] ids)
{ {
return ids == null ? JValue.CreateNull() : (JToken)new JArray(ids); return ids == null ? JValue.CreateNull() : (JToken)new JArray(ids);

12
tests/Squidex.Write.Tests/Contents/ContentCommandHandlerTests.cs

@ -34,7 +34,7 @@ namespace Squidex.Write.Contents
private readonly Mock<IAppProvider> appProvider = new Mock<IAppProvider>(); private readonly Mock<IAppProvider> appProvider = new Mock<IAppProvider>();
private readonly Mock<ISchemaEntity> schemaEntity = new Mock<ISchemaEntity>(); private readonly Mock<ISchemaEntity> schemaEntity = new Mock<ISchemaEntity>();
private readonly Mock<IAppEntity> appEntity = new Mock<IAppEntity>(); private readonly Mock<IAppEntity> appEntity = new Mock<IAppEntity>();
private readonly ContentData data = new ContentData().AddField("my-field", new ContentFieldData().SetValue(1)); private readonly NamedContentData data = new NamedContentData().AddField("my-field", new ContentFieldData().SetValue(1));
private readonly LanguagesConfig languagesConfig = LanguagesConfig.Create(Language.DE); private readonly LanguagesConfig languagesConfig = LanguagesConfig.Create(Language.DE);
private readonly Guid contentId = Guid.NewGuid(); private readonly Guid contentId = Guid.NewGuid();
@ -60,7 +60,7 @@ namespace Squidex.Write.Contents
[Fact] [Fact]
public async Task Create_should_throw_exception_if_data_is_not_valid() public async Task Create_should_throw_exception_if_data_is_not_valid()
{ {
var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = new ContentData() }); var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = new NamedContentData() });
await TestCreate(content, async _ => await TestCreate(content, async _ =>
{ {
@ -78,7 +78,7 @@ namespace Squidex.Write.Contents
await sut.HandleAsync(context); await sut.HandleAsync(context);
}); });
Assert.Equal(data, context.Result<EntityCreatedResult<ContentData>>().IdOrValue); Assert.Equal(data, context.Result<EntityCreatedResult<NamedContentData>>().IdOrValue);
} }
[Fact] [Fact]
@ -86,7 +86,7 @@ namespace Squidex.Write.Contents
{ {
CreateContent(); CreateContent();
var context = CreateContextForCommand(new UpdateContent { ContentId = contentId, Data = new ContentData() }); var context = CreateContextForCommand(new UpdateContent { ContentId = contentId, Data = new NamedContentData() });
await TestUpdate(content, async _ => await TestUpdate(content, async _ =>
{ {
@ -112,7 +112,7 @@ namespace Squidex.Write.Contents
{ {
CreateContent(); CreateContent();
var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = new ContentData() }); var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = new NamedContentData() });
await TestUpdate(content, async _ => await TestUpdate(content, async _ =>
{ {
@ -123,7 +123,7 @@ namespace Squidex.Write.Contents
[Fact] [Fact]
public async Task Patch_should_update_domain_object() public async Task Patch_should_update_domain_object()
{ {
var otherContent = new ContentData().AddField("my-field", new ContentFieldData().SetValue(3)); var otherContent = new NamedContentData().AddField("my-field", new ContentFieldData().SetValue(3));
CreateContent(); CreateContent();

8
tests/Squidex.Write.Tests/Contents/ContentDomainObjectTests.cs

@ -23,13 +23,13 @@ namespace Squidex.Write.Contents
public class ContentDomainObjectTests : HandlerTestBase<ContentDomainObject> public class ContentDomainObjectTests : HandlerTestBase<ContentDomainObject>
{ {
private readonly ContentDomainObject sut; private readonly ContentDomainObject sut;
private readonly ContentData data = private readonly NamedContentData data =
new ContentData() new NamedContentData()
.AddField("field1", .AddField("field1",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 1)); .AddValue("iv", 1));
private readonly ContentData otherData = private readonly NamedContentData otherData =
new ContentData() new NamedContentData()
.AddField("field2", .AddField("field2",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", 2)); .AddValue("iv", 2));

Loading…
Cancel
Save