diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs index cf1ad40a6..ffd1eb029 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs @@ -6,6 +6,8 @@ // All rights reserved. // ========================================================================== +using System.Collections.Generic; +using Newtonsoft.Json.Linq; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas @@ -13,9 +15,36 @@ namespace Squidex.Domain.Apps.Core.Schemas [TypeName(nameof(AssetsField))] public sealed class AssetsFieldProperties : FieldProperties { - public int? MinItems { get; set; } + private int? minItems; + private int? maxItems; - public int? MaxItems { get; set; } + public int? MinItems + { + get + { + return minItems; + } + set + { + ThrowIfFrozen(); + + minItems = value; + } + } + + public int? MaxItems + { + get + { + return maxItems; + } + set + { + ThrowIfFrozen(); + + maxItems = value; + } + } public override T Accept(IFieldPropertiesVisitor visitor) { diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs index f773ce620..3f3e56ab9 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs @@ -6,6 +6,8 @@ // All rights reserved. // ========================================================================== +using System.Collections.Generic; +using Newtonsoft.Json.Linq; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas @@ -13,9 +15,36 @@ namespace Squidex.Domain.Apps.Core.Schemas [TypeName(nameof(BooleanField))] public sealed class BooleanFieldProperties : FieldProperties { - public bool? DefaultValue { get; set; } + private BooleanFieldEditor editor; + private bool? defaultValue; - public BooleanFieldEditor Editor { get; set; } + public bool? DefaultValue + { + get + { + return defaultValue; + } + set + { + ThrowIfFrozen(); + + defaultValue = value; + } + } + + public BooleanFieldEditor Editor + { + get + { + return editor; + } + set + { + ThrowIfFrozen(); + + editor = value; + } + } public override T Accept(IFieldPropertiesVisitor visitor) { diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs index 9c03a46c8..6adcae338 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs @@ -6,6 +6,9 @@ // All rights reserved. // ========================================================================== +using System; +using System.Collections.Generic; +using Newtonsoft.Json.Linq; using NodaTime; using Squidex.Infrastructure; @@ -14,15 +17,81 @@ namespace Squidex.Domain.Apps.Core.Schemas [TypeName(nameof(DateTimeField))] public sealed class DateTimeFieldProperties : FieldProperties { - public Instant? MaxValue { get; set; } + private DateTimeFieldEditor editor; + private DateTimeCalculatedDefaultValue? calculatedDefaultValue; + private Instant? maxValue; + private Instant? minValue; + private Instant? defaultValue; - public Instant? MinValue { get; set; } + public Instant? MaxValue + { + get + { + return maxValue; + } + set + { + ThrowIfFrozen(); + + maxValue = value; + } + } + + public Instant? MinValue + { + get + { + return minValue; + } + set + { + ThrowIfFrozen(); + + minValue = value; + } + } + + public Instant? DefaultValue + { + get + { + return defaultValue; + } + set + { + ThrowIfFrozen(); + + defaultValue = value; + } + } + + public DateTimeCalculatedDefaultValue? CalculatedDefaultValue + { + get + { + return calculatedDefaultValue; + } + set + { + ThrowIfFrozen(); - public Instant? DefaultValue { get; set; } + calculatedDefaultValue = value; + } + } - public DateTimeFieldEditor Editor { get; set; } + public DateTimeFieldEditor Editor + { + get + { + return editor; + } + set + { + ThrowIfFrozen(); - public DateTimeCalculatedDefaultValue? CalculatedDefaultValue { get; set; } + editor = value; + } + } public override T Accept(IFieldPropertiesVisitor visitor) { diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Field.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Field.cs index 2f9edf612..d10500fc1 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Field.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Field.cs @@ -6,11 +6,12 @@ // All rights reserved. // ========================================================================== +using System.Diagnostics.Contracts; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas { - public abstract class Field + public abstract class Field : Cloneable { private readonly long fieldId; private readonly Partitioning partitioning; @@ -63,32 +64,52 @@ namespace Squidex.Domain.Apps.Core.Schemas this.partitioning = partitioning; } - public void Lock() + [Pure] + public Field Lock() { - isLocked = true; + return Clone(clone => + { + clone.isLocked = true; + }); } - public void Hide() + [Pure] + public Field Hide() { - isHidden = true; + return Clone(clone => + { + clone.isHidden = true; + }); } - public void Show() + [Pure] + public Field Show() { - isHidden = false; + return Clone(clone => + { + clone.isHidden = false; + }); } - public void Disable() + [Pure] + public Field Disable() { - isDisabled = true; + return Clone(clone => + { + clone.isDisabled = true; + }); } - public void Enable() + [Pure] + public Field Enable() { - isDisabled = false; + return Clone(clone => + { + clone.isDisabled = false; + }); } - public abstract void Update(FieldProperties newProperties); + public abstract Field Update(FieldProperties newProperties); public abstract T Accept(IFieldVisitor visitor); } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs index c975e4ef9..315dfc925 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs @@ -10,11 +10,51 @@ namespace Squidex.Domain.Apps.Core.Schemas { public abstract class FieldProperties : NamedElementPropertiesBase { - public bool IsRequired { get; set; } + private bool isRequired; + private bool isListField; + private string placeholder; - public bool IsListField { get; set; } + public bool IsRequired + { + get + { + return isRequired; + } + set + { + ThrowIfFrozen(); - public string Placeholder { get; set; } + isRequired = value; + } + } + + public bool IsListField + { + get + { + return isListField; + } + set + { + ThrowIfFrozen(); + + isListField = value; + } + } + + public string Placeholder + { + get + { + return placeholder; + } + set + { + ThrowIfFrozen(); + + placeholder = value; + } + } public abstract T Accept(IFieldPropertiesVisitor visitor); } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Field{T}.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Field{T}.cs index edc05dbb2..1e85e17c1 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Field{T}.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Field{T}.cs @@ -1,5 +1,5 @@ // ========================================================================== -// Field_Generic.cs +// Field{T}.cs // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex Group @@ -7,7 +7,9 @@ // ========================================================================== using System; +using System.Diagnostics.Contracts; using Squidex.Infrastructure; + namespace Squidex.Domain.Apps.Core.Schemas { public abstract class Field : Field where T : FieldProperties, new() @@ -30,13 +32,19 @@ namespace Squidex.Domain.Apps.Core.Schemas Guard.NotNull(properties, nameof(properties)); this.properties = properties; + this.properties.Freeze(); } - public override void Update(FieldProperties newProperties) + [Pure] + public override Field Update(FieldProperties newProperties) { var typedProperties = ValidateProperties(newProperties); - properties = typedProperties; + return Clone(clone => + { + properties = typedProperties; + properties.Freeze(); + }); } private T ValidateProperties(FieldProperties newProperties) diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs index 5e4b34d4e..ef94fd8d4 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs @@ -6,6 +6,8 @@ // All rights reserved. // ========================================================================== +using System.Collections.Generic; +using Newtonsoft.Json.Linq; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas @@ -13,7 +15,21 @@ namespace Squidex.Domain.Apps.Core.Schemas [TypeName(nameof(GeolocationField))] public sealed class GeolocationFieldProperties : FieldProperties { - public GeolocationFieldEditor Editor { get; set; } + private GeolocationFieldEditor editor; + + public GeolocationFieldEditor Editor + { + get + { + return editor; + } + set + { + ThrowIfFrozen(); + + editor = value; + } + } public override T Accept(IFieldPropertiesVisitor visitor) { diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs index f2c6695bd..f7d493781 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs @@ -54,7 +54,7 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json public Schema ToSchema(FieldRegistry fieldRegistry) { - var schema = new Schema(Name); + var fields = new List(); if (Fields != null) { @@ -66,34 +66,24 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json if (fieldModel.IsDisabled) { - field.Disable(); + field = field.Disable(); } if (fieldModel.IsLocked) { - field.Lock(); + field = field.Lock(); } if (fieldModel.IsHidden) { - field.Hide(); + field = field.Hide(); } - schema.AddField(field); + fields.Add(field); } } - if (IsPublished) - { - schema.Publish(); - } - - if (Properties != null) - { - schema.Update(Properties); - } - - return schema; + return new Schema(Name, fields, Properties, IsPublished); } } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs index c432be09a..981da30a1 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs @@ -6,6 +6,8 @@ // All rights reserved. // ========================================================================== +using System.Collections.Generic; +using Newtonsoft.Json.Linq; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/NamedElementPropertiesBase.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/NamedElementPropertiesBase.cs index 7f5a9d572..ca23aec3d 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/NamedElementPropertiesBase.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/NamedElementPropertiesBase.cs @@ -6,12 +6,41 @@ // All rights reserved. // ========================================================================== +using Squidex.Infrastructure; + namespace Squidex.Domain.Apps.Core.Schemas { - public abstract class NamedElementPropertiesBase + public abstract class NamedElementPropertiesBase : Freezable { - public string Label { get; set; } + private string label; + private string hints; + + public string Label + { + get + { + return label; + } + set + { + ThrowIfFrozen(); + + label = value; + } + } + + public string Hints + { + get + { + return hints; + } + set + { + ThrowIfFrozen(); - public string Hints { get; set; } + hints = value; + } + } } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs index ce1703faa..884b145bd 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs @@ -6,6 +6,9 @@ // All rights reserved. // ========================================================================== +using System.Collections.Generic; +using System.Collections.Immutable; +using Newtonsoft.Json.Linq; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas @@ -13,15 +16,81 @@ namespace Squidex.Domain.Apps.Core.Schemas [TypeName(nameof(NumberField))] public sealed class NumberFieldProperties : FieldProperties { - public double? MaxValue { get; set; } + private double? maxValue; + private double? minValue; + private double? defaultValue; + private ImmutableList allowedValues; + private NumberFieldEditor editor; - public double? MinValue { get; set; } + public double? MaxValue + { + get + { + return maxValue; + } + set + { + ThrowIfFrozen(); + + maxValue = value; + } + } + + public double? MinValue + { + get + { + return minValue; + } + set + { + ThrowIfFrozen(); + + minValue = value; + } + } + + public double? DefaultValue + { + get + { + return defaultValue; + } + set + { + ThrowIfFrozen(); + + defaultValue = value; + } + } + + public ImmutableList AllowedValues + { + get + { + return allowedValues; + } + set + { + ThrowIfFrozen(); - public double? DefaultValue { get; set; } + allowedValues = value; + } + } - public double[] AllowedValues { get; set; } + public NumberFieldEditor Editor + { + get + { + return editor; + } + set + { + ThrowIfFrozen(); - public NumberFieldEditor Editor { get; set; } + editor = value; + } + } public override T Accept(IFieldPropertiesVisitor visitor) { diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs index 8a4f76192..6562ca86d 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs @@ -7,6 +7,8 @@ // ========================================================================== using System; +using System.Collections.Generic; +using Newtonsoft.Json.Linq; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas @@ -14,11 +16,51 @@ namespace Squidex.Domain.Apps.Core.Schemas [TypeName(nameof(ReferencesField))] public sealed class ReferencesFieldProperties : FieldProperties { - public int? MinItems { get; set; } + private int? minItems; + private int? maxItems; + private Guid schemaId; - public int? MaxItems { get; set; } + public int? MinItems + { + get + { + return minItems; + } + set + { + ThrowIfFrozen(); + + minItems = value; + } + } + + public int? MaxItems + { + get + { + return maxItems; + } + set + { + ThrowIfFrozen(); - public Guid SchemaId { get; set; } + maxItems = value; + } + } + + public Guid SchemaId + { + get + { + return schemaId; + } + set + { + ThrowIfFrozen(); + + schemaId = value; + } + } public override T Accept(IFieldPropertiesVisitor visitor) { diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs index 8a7a06d40..430def864 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs @@ -8,17 +8,19 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.Contracts; using System.Linq; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas { - public sealed class Schema + public sealed class Schema : Cloneable { private readonly string name; - private readonly List fieldsOrdered = new List(); - private readonly Dictionary fieldsById = new Dictionary(); - private readonly Dictionary fieldsByName = new Dictionary(); + private ImmutableList fieldsOrdered = ImmutableList.Empty; + private ImmutableDictionary fieldsById = ImmutableDictionary.Empty; + private ImmutableDictionary fieldsByName = ImmutableDictionary.Empty; private SchemaProperties properties = new SchemaProperties(); private bool isPublished; @@ -52,43 +54,132 @@ namespace Squidex.Domain.Apps.Core.Schemas get { return properties; } } - public void Publish() + public Schema(string name) { - isPublished = true; - } + Guard.NotNullOrEmpty(name, nameof(name)); - public void Unpublish() - { - isPublished = false; + this.name = name; } - public Schema(string name) + public Schema(string name, IEnumerable fields, SchemaProperties properties, bool isPublished) + : this(name) { Guard.NotNullOrEmpty(name, nameof(name)); - this.name = name; + this.isPublished = isPublished; + + this.properties = properties ?? new SchemaProperties(); + this.properties.Freeze(); + + fieldsOrdered = ImmutableList.Empty.AddRange(fields); + } + + protected override void OnCloned() + { + fieldsById = fieldsOrdered.ToImmutableDictionary(x => x.Id); + fieldsByName = fieldsOrdered.ToImmutableDictionary(x => x.Name); } - public void Update(SchemaProperties newProperties) + [Pure] + public Schema Update(SchemaProperties newProperties) { Guard.NotNull(newProperties, nameof(newProperties)); - properties = newProperties; + return Clone(clone => + { + properties = newProperties; + properties.Freeze(); + }); + } + + [Pure] + public Schema UpdateField(long fieldId, FieldProperties newProperties) + { + return UpdateField(fieldId, field => + { + return field.Update(newProperties); + }); + } + + [Pure] + public Schema LockField(long fieldId) + { + return UpdateField(fieldId, field => + { + return field.Lock(); + }); + } + + [Pure] + public Schema DisableField(long fieldId) + { + return UpdateField(fieldId, field => + { + return field.Disable(); + }); + } + + [Pure] + public Schema EnableField(long fieldId) + { + return UpdateField(fieldId, field => + { + return field.Enable(); + }); + } + + [Pure] + public Schema HideField(long fieldId) + { + return UpdateField(fieldId, field => + { + return field.Hide(); + }); + } + + [Pure] + public Schema ShowField(long fieldId) + { + return UpdateField(fieldId, field => + { + return field.Show(); + }); } - public void DeleteField(long fieldId) + [Pure] + public Schema Publish() + { + return Clone(clone => + { + isPublished = true; + }); + } + + [Pure] + public Schema Unpublish() + { + return Clone(clone => + { + isPublished = false; + }); + } + + [Pure] + public Schema DeleteField(long fieldId) { if (!fieldsById.TryGetValue(fieldId, out var field)) { - return; + return this; } - fieldsById.Remove(fieldId); - fieldsByName.Remove(field.Name); - fieldsOrdered.Remove(field); + return Clone(clone => + { + clone.fieldsOrdered = fieldsOrdered.Remove(field); + }); } - public void ReorderFields(List ids) + [Pure] + public Schema ReorderFields(List ids) { Guard.NotNull(ids, nameof(ids)); @@ -97,13 +188,14 @@ namespace Squidex.Domain.Apps.Core.Schemas throw new ArgumentException("Ids must cover all fields.", nameof(ids)); } - var fields = fieldsOrdered.ToList(); - - fieldsOrdered.Clear(); - fieldsOrdered.AddRange(fields.OrderBy(f => ids.IndexOf(f.Id))); + return Clone(clone => + { + clone.fieldsOrdered = fieldsOrdered.OrderBy(f => ids.IndexOf(f.Id)).ToImmutableList(); + }); } - public void AddField(Field field) + [Pure] + public Schema AddField(Field field) { Guard.NotNull(field, nameof(field)); @@ -112,9 +204,26 @@ namespace Squidex.Domain.Apps.Core.Schemas throw new ArgumentException($"A field with name '{field.Name}' already exists.", nameof(field)); } - fieldsById.Add(field.Id, field); - fieldsByName.Add(field.Name, field); - fieldsOrdered.Add(field); + return Clone(clone => + { + clone.fieldsOrdered = clone.fieldsOrdered.Add(field); + }); + } + + [Pure] + public Schema UpdateField(long fieldId, Func updater) + { + Guard.NotNull(updater, nameof(updater)); + + if (!fieldsById.TryGetValue(fieldId, out var field)) + { + return this; + } + + return Clone(clone => + { + clone.fieldsOrdered = clone.fieldsOrdered.Replace(field, updater(field)); + }); } } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs index 5263cc2e7..e48a4fefc 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs @@ -6,26 +6,122 @@ // All rights reserved. // ========================================================================== +using System.Collections.Generic; +using System.Collections.Immutable; +using Newtonsoft.Json.Linq; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json; namespace Squidex.Domain.Apps.Core.Schemas { [TypeName(nameof(StringField))] public sealed class StringFieldProperties : FieldProperties { - public int? MinLength { get; set; } + private int? minLength; + private int? maxLength; + private string pattern; + private string patternMessage; + private string defaultValue; + private ImmutableList allowedValues; + private StringFieldEditor editor; - public int? MaxLength { get; set; } + public int? MinLength + { + get + { + return minLength; + } + set + { + ThrowIfFrozen(); + + minLength = value; + } + } + + public int? MaxLength + { + get + { + return maxLength; + } + set + { + ThrowIfFrozen(); + + maxLength = value; + } + } + + public string DefaultValue + { + get + { + return defaultValue; + } + set + { + ThrowIfFrozen(); + + defaultValue = value; + } + } - public string DefaultValue { get; set; } + public string Pattern + { + get + { + return pattern; + } + set + { + ThrowIfFrozen(); + + pattern = value; + } + } - public string Pattern { get; set; } + public string PatternMessage + { + get + { + return patternMessage; + } + set + { + ThrowIfFrozen(); - public string PatternMessage { get; set; } + patternMessage = value; + } + } - public string[] AllowedValues { get; set; } + public ImmutableList AllowedValues + { + get + { + return allowedValues; + } + set + { + ThrowIfFrozen(); - public StringFieldEditor Editor { get; set; } + allowedValues = value; + } + } + + public StringFieldEditor Editor + { + get + { + return editor; + } + set + { + ThrowIfFrozen(); + + editor = value; + } + } public override T Accept(IFieldPropertiesVisitor visitor) { diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs index 9e10e634b..99b48b2d3 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs @@ -13,9 +13,36 @@ namespace Squidex.Domain.Apps.Core.Schemas [TypeName(nameof(TagsField))] public sealed class TagsFieldProperties : FieldProperties { - public int? MinItems { get; set; } + private int? minItems; + private int? maxItems; - public int? MaxItems { get; set; } + public int? MinItems + { + get + { + return minItems; + } + set + { + ThrowIfFrozen(); + + minItems = value; + } + } + + public int? MaxItems + { + get + { + return maxItems; + } + set + { + ThrowIfFrozen(); + + maxItems = value; + } + } public override T Accept(IFieldPropertiesVisitor visitor) { diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs index 955fcdc74..803ee9062 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs @@ -7,6 +7,7 @@ // ========================================================================== using System.Collections.Generic; +using System.Collections.Immutable; using System.Threading.Tasks; using FluentAssertions; using Newtonsoft.Json.Linq; @@ -73,7 +74,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_errors_if_number_is_not_allowed() { - var sut = new NumberField(1, "my-number", Partitioning.Invariant, new NumberFieldProperties { AllowedValues = new[] { 10d } }); + var sut = new NumberField(1, "my-number", Partitioning.Invariant, new NumberFieldProperties { AllowedValues = ImmutableList.Create(10d) }); await sut.ValidateAsync(CreateValue(20), errors); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs index c1103da56..fa776d68d 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs @@ -7,6 +7,7 @@ // ========================================================================== using System.Collections.Generic; +using System.Collections.Immutable; using System.Threading.Tasks; using FluentAssertions; using Newtonsoft.Json.Linq; @@ -73,7 +74,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_errors_if_string_not_allowed() { - var sut = new StringField(1, "my-string", Partitioning.Invariant, new StringFieldProperties { AllowedValues = new[] { "Foo" } }); + var sut = new StringField(1, "my-string", Partitioning.Invariant, new StringFieldProperties { AllowedValues = ImmutableList.Create("Foo") }); await sut.ValidateAsync(CreateValue("Bar"), errors); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs index ad21aafa0..ce17b80fa 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs @@ -6,6 +6,7 @@ // All rights reserved. // ========================================================================== +using System.Collections.Immutable; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Squidex.Domain.Apps.Core.Apps.Json; @@ -53,45 +54,45 @@ namespace Squidex.Domain.Apps.Core var schema = new Schema("user"); - schema.Publish(); - schema.Update(new SchemaProperties { Hints = "The User" }); + schema = schema.Publish(); + schema = schema.Update(new SchemaProperties { Hints = "The User" }); - schema.AddField(new JsonField(1, "my-json", inv, + schema = schema.AddField(new JsonField(1, "my-json", inv, new JsonFieldProperties())); - schema.AddField(new AssetsField(2, "my-assets", inv, + schema = schema.AddField(new AssetsField(2, "my-assets", inv, new AssetsFieldProperties())); - schema.AddField(new StringField(3, "my-string1", inv, - new StringFieldProperties { Label = "My String1", IsRequired = true, AllowedValues = new[] { "a", "b" } })); + schema = schema.AddField(new StringField(3, "my-string1", inv, + new StringFieldProperties { Label = "My String1", IsRequired = true, AllowedValues = ImmutableList.Create("a", "b") })); - schema.AddField(new StringField(4, "my-string2", inv, + schema = schema.AddField(new StringField(4, "my-string2", inv, new StringFieldProperties { Hints = "My String1" })); - schema.AddField(new NumberField(5, "my-number", inv, + schema = schema.AddField(new NumberField(5, "my-number", inv, new NumberFieldProperties { MinValue = 1, MaxValue = 10 })); - schema.AddField(new BooleanField(6, "my-boolean", inv, + schema = schema.AddField(new BooleanField(6, "my-boolean", inv, new BooleanFieldProperties())); - schema.AddField(new DateTimeField(7, "my-datetime", inv, + schema = schema.AddField(new DateTimeField(7, "my-datetime", inv, new DateTimeFieldProperties { Editor = DateTimeFieldEditor.DateTime })); - schema.AddField(new DateTimeField(8, "my-date", inv, + schema = schema.AddField(new DateTimeField(8, "my-date", inv, new DateTimeFieldProperties { Editor = DateTimeFieldEditor.Date })); - schema.AddField(new GeolocationField(9, "my-geolocation", inv, + schema = schema.AddField(new GeolocationField(9, "my-geolocation", inv, new GeolocationFieldProperties())); - schema.AddField(new ReferencesField(10, "my-references", inv, + schema = schema.AddField(new ReferencesField(10, "my-references", inv, new ReferencesFieldProperties())); - schema.AddField(new TagsField(11, "my-tags", Partitioning.Language, + schema = schema.AddField(new TagsField(11, "my-tags", Partitioning.Language, new TagsFieldProperties())); - schema.FieldsById[7].Hide(); - schema.FieldsById[8].Disable(); - schema.FieldsById[9].Lock(); + schema = schema.HideField(7); + schema = schema.LockField(8); + schema = schema.DisableField(9); return schema; }