mirror of https://github.com/Squidex/squidex.git
18 changed files with 401 additions and 13 deletions
@ -0,0 +1,89 @@ |
|||
// ==========================================================================
|
|||
// GeolocationField.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Microsoft.OData.Edm; |
|||
using Newtonsoft.Json.Linq; |
|||
using NJsonSchema; |
|||
using Squidex.Core.Schemas.Validators; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Core.Schemas |
|||
{ |
|||
public sealed class GeolocationField : Field<GeolocationFieldProperties> |
|||
{ |
|||
public GeolocationField(long id, string name, GeolocationFieldProperties properties) |
|||
: base(id, name, properties) |
|||
{ |
|||
} |
|||
|
|||
protected override IEnumerable<IValidator> CreateValidators() |
|||
{ |
|||
if (Properties.IsRequired) |
|||
{ |
|||
yield return new RequiredValidator(); |
|||
} |
|||
} |
|||
|
|||
protected override object ConvertValue(JToken value) |
|||
{ |
|||
var geolocation = (JObject)value; |
|||
|
|||
foreach (var property in geolocation.Properties()) |
|||
{ |
|||
if (!string.Equals(property.Name, "latitude", StringComparison.OrdinalIgnoreCase) && |
|||
!string.Equals(property.Name, "longitude", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
throw new InvalidCastException("Geolocation can only have latitude and longitude property."); |
|||
} |
|||
} |
|||
|
|||
var lat = (double)geolocation["latitude"]; |
|||
var lon = (double)geolocation["longitude"]; |
|||
|
|||
Guard.Between(lat, -90, 90, "latitude"); |
|||
Guard.Between(lon, -180, 180, "longitude"); |
|||
|
|||
return value; |
|||
} |
|||
|
|||
protected override void PrepareJsonSchema(JsonProperty jsonProperty, Func<string, JsonSchema4, JsonSchema4> schemaResolver) |
|||
{ |
|||
jsonProperty.Type = JsonObjectType.Object; |
|||
|
|||
var geolocationSchema = new JsonSchema4(); |
|||
|
|||
geolocationSchema.Properties.Add("latitude", new JsonProperty |
|||
{ |
|||
Type = JsonObjectType.Number, |
|||
Minimum = -90, |
|||
Maximum = 90, |
|||
IsRequired = true |
|||
}); |
|||
geolocationSchema.Properties.Add("longitude", new JsonProperty |
|||
{ |
|||
Type = JsonObjectType.Number, |
|||
Minimum = -180, |
|||
Maximum = 180, |
|||
IsRequired = true |
|||
}); |
|||
|
|||
geolocationSchema.AllowAdditionalProperties = false; |
|||
|
|||
var schemaReference = schemaResolver("GeolocationDto", geolocationSchema); |
|||
|
|||
jsonProperty.SchemaReference = schemaReference; |
|||
} |
|||
|
|||
protected override IEdmTypeReference CreateEdmType() |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
// ==========================================================================
|
|||
// GeolocationFieldEditor.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
namespace Squidex.Core.Schemas |
|||
{ |
|||
public enum GeolocationFieldEditor |
|||
{ |
|||
Map |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
// ==========================================================================
|
|||
// GeolocationFieldProperties.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using Newtonsoft.Json.Linq; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Core.Schemas |
|||
{ |
|||
[TypeName("GeolocationField")] |
|||
public sealed class GeolocationFieldProperties : FieldProperties |
|||
{ |
|||
private GeolocationFieldEditor editor; |
|||
|
|||
public GeolocationFieldEditor Editor |
|||
{ |
|||
get { return editor; } |
|||
set |
|||
{ |
|||
ThrowIfFrozen(); |
|||
|
|||
editor = value; |
|||
} |
|||
} |
|||
|
|||
public override JToken GetDefaultValue() |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
protected override IEnumerable<ValidationError> ValidateCore() |
|||
{ |
|||
if (!Editor.IsEnumValue()) |
|||
{ |
|||
yield return new ValidationError("Editor ist not a valid value", nameof(Editor)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
// ==========================================================================
|
|||
// GeolocationFieldPropertiesDto.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
using NJsonSchema.Annotations; |
|||
using Squidex.Core.Schemas; |
|||
using Squidex.Infrastructure.Reflection; |
|||
|
|||
namespace Squidex.Controllers.Api.Schemas.Models |
|||
{ |
|||
[JsonSchema("Geolocation")] |
|||
public sealed class GeolocationFieldPropertiesDto : FieldPropertiesDto |
|||
{ |
|||
/// <summary>
|
|||
/// The default value for the field value.
|
|||
/// </summary>
|
|||
public bool? DefaultValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The editor that is used to manage this field.
|
|||
/// </summary>
|
|||
[JsonConverter(typeof(StringEnumConverter))] |
|||
public GeolocationFieldEditor Editor { get; set; } |
|||
|
|||
public override FieldProperties ToProperties() |
|||
{ |
|||
var result = SimpleMapper.Map(this, new GeolocationFieldProperties()); |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
// ==========================================================================
|
|||
// GeolocationFieldTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using FluentAssertions; |
|||
using Newtonsoft.Json.Linq; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Core.Schemas |
|||
{ |
|||
public class GeolocationFieldTests |
|||
{ |
|||
private readonly List<string> errors = new List<string>(); |
|||
|
|||
[Fact] |
|||
public void Should_instantiate_field() |
|||
{ |
|||
var sut = new GeolocationField(1, "my-geolocation", new GeolocationFieldProperties()); |
|||
|
|||
Assert.Equal("my-geolocation", sut.Name); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_clone_object() |
|||
{ |
|||
var sut = new GeolocationField(1, "my-geolocation", new GeolocationFieldProperties()); |
|||
|
|||
Assert.NotEqual(sut, sut.Enable()); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_error_if_geolocation_is_valid() |
|||
{ |
|||
var sut = new GeolocationField(1, "my-geolocation", new GeolocationFieldProperties { Label = "my-geolocation" }); |
|||
|
|||
var geolocation = new JObject( |
|||
new JProperty("latitude", 0), |
|||
new JProperty("longitude", 0)); |
|||
|
|||
await sut.ValidateAsync(CreateValue(geolocation), errors); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_add_errors_if_geolocation_has_invalid_properties() |
|||
{ |
|||
var sut = new GeolocationField(1, "my-geolocation", new GeolocationFieldProperties { Label = "my-geolocation", IsRequired = true }); |
|||
|
|||
var geolocation = new JObject( |
|||
new JProperty("latitude", 200), |
|||
new JProperty("longitude", 0)); |
|||
|
|||
await sut.ValidateAsync(CreateValue(geolocation), errors); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new[] { "my-geolocation is not a valid value" }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_add_errors_if_geolocation_has_too_many_properties() |
|||
{ |
|||
var sut = new GeolocationField(1, "my-geolocation", new GeolocationFieldProperties { Label = "my-geolocation", IsRequired = true }); |
|||
|
|||
var geolocation = new JObject( |
|||
new JProperty("invalid", 0), |
|||
new JProperty("latitude", 0), |
|||
new JProperty("longitude", 0)); |
|||
|
|||
await sut.ValidateAsync(CreateValue(geolocation), errors); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new[] { "my-geolocation is not a valid value" }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_add_errors_if_geolocation_is_required() |
|||
{ |
|||
var sut = new GeolocationField(1, "my-geolocation", new GeolocationFieldProperties { Label = "my-geolocation", IsRequired = true }); |
|||
|
|||
await sut.ValidateAsync(CreateValue(JValue.CreateNull()), errors); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new[] { "my-geolocation is required" }); |
|||
} |
|||
|
|||
private static JToken CreateValue(JToken v) |
|||
{ |
|||
return v; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
// ==========================================================================
|
|||
// GeolocationFieldTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using FluentAssertions; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Core.Schemas |
|||
{ |
|||
public class GeolocationFieldPropertiesTests |
|||
{ |
|||
private readonly List<ValidationError> errors = new List<ValidationError>(); |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_editor_is_not_valid() |
|||
{ |
|||
var sut = new GeolocationFieldProperties { Editor = (GeolocationFieldEditor)123 }; |
|||
|
|||
sut.Validate(errors); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Editor ist not a valid value", "Editor") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_set_or_freeze_sut() |
|||
{ |
|||
var sut = new GeolocationFieldProperties(); |
|||
|
|||
foreach (var property in sut.GetType().GetRuntimeProperties().Where(x => x.Name != "IsFrozen")) |
|||
{ |
|||
var value = |
|||
property.PropertyType.GetTypeInfo().IsValueType ? |
|||
Activator.CreateInstance(property.PropertyType) : |
|||
null; |
|||
|
|||
property.SetValue(sut, value); |
|||
|
|||
var result = property.GetValue(sut); |
|||
|
|||
Assert.Equal(value, result); |
|||
} |
|||
|
|||
sut.Freeze(); |
|||
|
|||
foreach (var property in sut.GetType().GetRuntimeProperties().Where(x => x.Name != "IsFrozen")) |
|||
{ |
|||
var value = |
|||
property.PropertyType.GetTypeInfo().IsValueType ? |
|||
Activator.CreateInstance(property.PropertyType) : |
|||
null; |
|||
|
|||
Assert.Throws<InvalidOperationException>(() => |
|||
{ |
|||
try |
|||
{ |
|||
property.SetValue(sut, value); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
throw ex.InnerException; |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue