Browse Source

Immutable schemas.

pull/169/head
Sebastian Stehle 8 years ago
parent
commit
c73972cb6b
  1. 33
      src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs
  2. 33
      src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs
  3. 79
      src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs
  4. 45
      src/Squidex.Domain.Apps.Core.Model/Schemas/Field.cs
  5. 46
      src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs
  6. 14
      src/Squidex.Domain.Apps.Core.Model/Schemas/Field{T}.cs
  7. 18
      src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs
  8. 22
      src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs
  9. 2
      src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs
  10. 35
      src/Squidex.Domain.Apps.Core.Model/Schemas/NamedElementPropertiesBase.cs
  11. 79
      src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs
  12. 48
      src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs
  13. 165
      src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs
  14. 110
      src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs
  15. 31
      src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs
  16. 3
      tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs
  17. 3
      tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs
  18. 35
      tests/Squidex.Domain.Apps.Core.Tests/TestData.cs

33
src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs

@ -6,6 +6,8 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas
@ -13,9 +15,36 @@ namespace Squidex.Domain.Apps.Core.Schemas
[TypeName(nameof(AssetsField))] [TypeName(nameof(AssetsField))]
public sealed class AssetsFieldProperties : FieldProperties 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<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T>(IFieldPropertiesVisitor<T> visitor)
{ {

33
src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs

@ -6,6 +6,8 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas
@ -13,9 +15,36 @@ namespace Squidex.Domain.Apps.Core.Schemas
[TypeName(nameof(BooleanField))] [TypeName(nameof(BooleanField))]
public sealed class BooleanFieldProperties : FieldProperties 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<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T>(IFieldPropertiesVisitor<T> visitor)
{ {

79
src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs

@ -6,6 +6,9 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using NodaTime; using NodaTime;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -14,15 +17,81 @@ namespace Squidex.Domain.Apps.Core.Schemas
[TypeName(nameof(DateTimeField))] [TypeName(nameof(DateTimeField))]
public sealed class DateTimeFieldProperties : FieldProperties 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<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T>(IFieldPropertiesVisitor<T> visitor)
{ {

45
src/Squidex.Domain.Apps.Core.Model/Schemas/Field.cs

@ -6,11 +6,12 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Diagnostics.Contracts;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas
{ {
public abstract class Field public abstract class Field : Cloneable<Field>
{ {
private readonly long fieldId; private readonly long fieldId;
private readonly Partitioning partitioning; private readonly Partitioning partitioning;
@ -63,32 +64,52 @@ namespace Squidex.Domain.Apps.Core.Schemas
this.partitioning = partitioning; this.partitioning = partitioning;
} }
public void Lock() [Pure]
public Field Lock()
{ {
isLocked = true; return Clone<Field>(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<T>(IFieldVisitor<T> visitor); public abstract T Accept<T>(IFieldVisitor<T> visitor);
} }

46
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 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<T>(IFieldPropertiesVisitor<T> visitor); public abstract T Accept<T>(IFieldPropertiesVisitor<T> visitor);
} }

14
src/Squidex.Domain.Apps.Core.Model/Schemas/Field{T}.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// Field_Generic.cs // Field{T}.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
@ -7,7 +7,9 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Diagnostics.Contracts;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas
{ {
public abstract class Field<T> : Field where T : FieldProperties, new() public abstract class Field<T> : Field where T : FieldProperties, new()
@ -30,13 +32,19 @@ namespace Squidex.Domain.Apps.Core.Schemas
Guard.NotNull(properties, nameof(properties)); Guard.NotNull(properties, nameof(properties));
this.properties = properties; this.properties = properties;
this.properties.Freeze();
} }
public override void Update(FieldProperties newProperties) [Pure]
public override Field Update(FieldProperties newProperties)
{ {
var typedProperties = ValidateProperties(newProperties); var typedProperties = ValidateProperties(newProperties);
properties = typedProperties; return Clone<Field>(clone =>
{
properties = typedProperties;
properties.Freeze();
});
} }
private T ValidateProperties(FieldProperties newProperties) private T ValidateProperties(FieldProperties newProperties)

18
src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs

@ -6,6 +6,8 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas
@ -13,7 +15,21 @@ namespace Squidex.Domain.Apps.Core.Schemas
[TypeName(nameof(GeolocationField))] [TypeName(nameof(GeolocationField))]
public sealed class GeolocationFieldProperties : FieldProperties 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<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T>(IFieldPropertiesVisitor<T> visitor)
{ {

22
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) public Schema ToSchema(FieldRegistry fieldRegistry)
{ {
var schema = new Schema(Name); var fields = new List<Field>();
if (Fields != null) if (Fields != null)
{ {
@ -66,34 +66,24 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json
if (fieldModel.IsDisabled) if (fieldModel.IsDisabled)
{ {
field.Disable(); field = field.Disable();
} }
if (fieldModel.IsLocked) if (fieldModel.IsLocked)
{ {
field.Lock(); field = field.Lock();
} }
if (fieldModel.IsHidden) if (fieldModel.IsHidden)
{ {
field.Hide(); field = field.Hide();
} }
schema.AddField(field); fields.Add(field);
} }
} }
if (IsPublished) return new Schema(Name, fields, Properties, IsPublished);
{
schema.Publish();
}
if (Properties != null)
{
schema.Update(Properties);
}
return schema;
} }
} }
} }

2
src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs

@ -6,6 +6,8 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas

35
src/Squidex.Domain.Apps.Core.Model/Schemas/NamedElementPropertiesBase.cs

@ -6,12 +6,41 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas 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;
}
}
} }
} }

79
src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs

@ -6,6 +6,9 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using System.Collections.Immutable;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas
@ -13,15 +16,81 @@ namespace Squidex.Domain.Apps.Core.Schemas
[TypeName(nameof(NumberField))] [TypeName(nameof(NumberField))]
public sealed class NumberFieldProperties : FieldProperties public sealed class NumberFieldProperties : FieldProperties
{ {
public double? MaxValue { get; set; } private double? maxValue;
private double? minValue;
private double? defaultValue;
private ImmutableList<double> 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<double> 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<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T>(IFieldPropertiesVisitor<T> visitor)
{ {

48
src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs

@ -7,6 +7,8 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas
@ -14,11 +16,51 @@ namespace Squidex.Domain.Apps.Core.Schemas
[TypeName(nameof(ReferencesField))] [TypeName(nameof(ReferencesField))]
public sealed class ReferencesFieldProperties : FieldProperties 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<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T>(IFieldPropertiesVisitor<T> visitor)
{ {

165
src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs

@ -8,17 +8,19 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using System.Linq; using System.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas
{ {
public sealed class Schema public sealed class Schema : Cloneable<Schema>
{ {
private readonly string name; private readonly string name;
private readonly List<Field> fieldsOrdered = new List<Field>(); private ImmutableList<Field> fieldsOrdered = ImmutableList<Field>.Empty;
private readonly Dictionary<long, Field> fieldsById = new Dictionary<long, Field>(); private ImmutableDictionary<long, Field> fieldsById = ImmutableDictionary<long, Field>.Empty;
private readonly Dictionary<string, Field> fieldsByName = new Dictionary<string, Field>(); private ImmutableDictionary<string, Field> fieldsByName = ImmutableDictionary<string, Field>.Empty;
private SchemaProperties properties = new SchemaProperties(); private SchemaProperties properties = new SchemaProperties();
private bool isPublished; private bool isPublished;
@ -52,43 +54,132 @@ namespace Squidex.Domain.Apps.Core.Schemas
get { return properties; } get { return properties; }
} }
public void Publish() public Schema(string name)
{ {
isPublished = true; Guard.NotNullOrEmpty(name, nameof(name));
}
public void Unpublish() this.name = name;
{
isPublished = false;
} }
public Schema(string name) public Schema(string name, IEnumerable<Field> fields, SchemaProperties properties, bool isPublished)
: this(name)
{ {
Guard.NotNullOrEmpty(name, nameof(name)); Guard.NotNullOrEmpty(name, nameof(name));
this.name = name; this.isPublished = isPublished;
this.properties = properties ?? new SchemaProperties();
this.properties.Freeze();
fieldsOrdered = ImmutableList<Field>.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)); 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)) if (!fieldsById.TryGetValue(fieldId, out var field))
{ {
return; return this;
} }
fieldsById.Remove(fieldId); return Clone(clone =>
fieldsByName.Remove(field.Name); {
fieldsOrdered.Remove(field); clone.fieldsOrdered = fieldsOrdered.Remove(field);
});
} }
public void ReorderFields(List<long> ids) [Pure]
public Schema ReorderFields(List<long> ids)
{ {
Guard.NotNull(ids, nameof(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)); throw new ArgumentException("Ids must cover all fields.", nameof(ids));
} }
var fields = fieldsOrdered.ToList(); return Clone(clone =>
{
fieldsOrdered.Clear(); clone.fieldsOrdered = fieldsOrdered.OrderBy(f => ids.IndexOf(f.Id)).ToImmutableList();
fieldsOrdered.AddRange(fields.OrderBy(f => ids.IndexOf(f.Id))); });
} }
public void AddField(Field field) [Pure]
public Schema AddField(Field field)
{ {
Guard.NotNull(field, nameof(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)); throw new ArgumentException($"A field with name '{field.Name}' already exists.", nameof(field));
} }
fieldsById.Add(field.Id, field); return Clone(clone =>
fieldsByName.Add(field.Name, field); {
fieldsOrdered.Add(field); clone.fieldsOrdered = clone.fieldsOrdered.Add(field);
});
}
[Pure]
public Schema UpdateField(long fieldId, Func<Field, Field> 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));
});
} }
} }
} }

110
src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs

@ -6,26 +6,122 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using System.Collections.Immutable;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
namespace Squidex.Domain.Apps.Core.Schemas namespace Squidex.Domain.Apps.Core.Schemas
{ {
[TypeName(nameof(StringField))] [TypeName(nameof(StringField))]
public sealed class StringFieldProperties : FieldProperties 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<string> 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<string> 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<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T>(IFieldPropertiesVisitor<T> visitor)
{ {

31
src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs

@ -13,9 +13,36 @@ namespace Squidex.Domain.Apps.Core.Schemas
[TypeName(nameof(TagsField))] [TypeName(nameof(TagsField))]
public sealed class TagsFieldProperties : FieldProperties 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<T>(IFieldPropertiesVisitor<T> visitor) public override T Accept<T>(IFieldPropertiesVisitor<T> visitor)
{ {

3
tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs

@ -7,6 +7,7 @@
// ========================================================================== // ==========================================================================
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks; using System.Threading.Tasks;
using FluentAssertions; using FluentAssertions;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
@ -73,7 +74,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent
[Fact] [Fact]
public async Task Should_add_errors_if_number_is_not_allowed() 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); await sut.ValidateAsync(CreateValue(20), errors);

3
tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs

@ -7,6 +7,7 @@
// ========================================================================== // ==========================================================================
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks; using System.Threading.Tasks;
using FluentAssertions; using FluentAssertions;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
@ -73,7 +74,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent
[Fact] [Fact]
public async Task Should_add_errors_if_string_not_allowed() 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); await sut.ValidateAsync(CreateValue("Bar"), errors);

35
tests/Squidex.Domain.Apps.Core.Tests/TestData.cs

@ -6,6 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Immutable;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using Squidex.Domain.Apps.Core.Apps.Json; using Squidex.Domain.Apps.Core.Apps.Json;
@ -53,45 +54,45 @@ namespace Squidex.Domain.Apps.Core
var schema = new Schema("user"); var schema = new Schema("user");
schema.Publish(); schema = schema.Publish();
schema.Update(new SchemaProperties { Hints = "The User" }); 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())); new JsonFieldProperties()));
schema.AddField(new AssetsField(2, "my-assets", inv, schema = schema.AddField(new AssetsField(2, "my-assets", inv,
new AssetsFieldProperties())); new AssetsFieldProperties()));
schema.AddField(new StringField(3, "my-string1", inv, schema = schema.AddField(new StringField(3, "my-string1", inv,
new StringFieldProperties { Label = "My String1", IsRequired = true, AllowedValues = new[] { "a", "b" } })); 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" })); 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 })); 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())); new BooleanFieldProperties()));
schema.AddField(new DateTimeField(7, "my-datetime", inv, schema = schema.AddField(new DateTimeField(7, "my-datetime", inv,
new DateTimeFieldProperties { Editor = DateTimeFieldEditor.DateTime })); 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 })); new DateTimeFieldProperties { Editor = DateTimeFieldEditor.Date }));
schema.AddField(new GeolocationField(9, "my-geolocation", inv, schema = schema.AddField(new GeolocationField(9, "my-geolocation", inv,
new GeolocationFieldProperties())); new GeolocationFieldProperties()));
schema.AddField(new ReferencesField(10, "my-references", inv, schema = schema.AddField(new ReferencesField(10, "my-references", inv,
new ReferencesFieldProperties())); new ReferencesFieldProperties()));
schema.AddField(new TagsField(11, "my-tags", Partitioning.Language, schema = schema.AddField(new TagsField(11, "my-tags", Partitioning.Language,
new TagsFieldProperties())); new TagsFieldProperties()));
schema.FieldsById[7].Hide(); schema = schema.HideField(7);
schema.FieldsById[8].Disable(); schema = schema.LockField(8);
schema.FieldsById[9].Lock(); schema = schema.DisableField(9);
return schema; return schema;
} }

Loading…
Cancel
Save