diff --git a/src/Squidex.Domain.Apps.Core/ContentEnricher.cs b/src/Squidex.Domain.Apps.Core/ContentEnricher.cs index 2d633ad13..6b0247080 100644 --- a/src/Squidex.Domain.Apps.Core/ContentEnricher.cs +++ b/src/Squidex.Domain.Apps.Core/ContentEnricher.cs @@ -64,7 +64,7 @@ namespace Squidex.Domain.Apps.Core var key = partitionItem.Key; - if (!fieldData.TryGetValue(key, out var value) || value == null || value.Type == JTokenType.Null) + if (!fieldData.TryGetValue(key, out var value) || field.RawProperties.ShouldApplyDefaultValue(value)) { fieldData.AddValue(key, defaultValue); } diff --git a/src/Squidex.Domain.Apps.Core/Schemas/FieldProperties.cs b/src/Squidex.Domain.Apps.Core/Schemas/FieldProperties.cs index 262d8453f..f9785bbbf 100644 --- a/src/Squidex.Domain.Apps.Core/Schemas/FieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core/Schemas/FieldProperties.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using Newtonsoft.Json.Linq; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json; namespace Squidex.Domain.Apps.Core.Schemas { @@ -62,6 +63,11 @@ namespace Squidex.Domain.Apps.Core.Schemas public abstract JToken GetDefaultValue(); + public virtual bool ShouldApplyDefaultValue(JToken value) + { + return value.IsNull(); + } + public void Validate(IList errors) { foreach (var error in ValidateCore()) diff --git a/src/Squidex.Domain.Apps.Core/Schemas/StringFieldProperties.cs b/src/Squidex.Domain.Apps.Core/Schemas/StringFieldProperties.cs index eb70680ac..fe038910d 100644 --- a/src/Squidex.Domain.Apps.Core/Schemas/StringFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core/Schemas/StringFieldProperties.cs @@ -10,6 +10,7 @@ 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 { @@ -127,6 +128,11 @@ namespace Squidex.Domain.Apps.Core.Schemas return DefaultValue; } + public override bool ShouldApplyDefaultValue(JToken value) + { + return value.IsNull() || (value is JValue jValue && Equals(jValue.Value, string.Empty)); + } + protected override IEnumerable ValidateCore() { if (!Editor.IsEnumValue()) diff --git a/src/Squidex.Domain.Apps.Events/Webhooks/WebhookDeleted.cs b/src/Squidex.Domain.Apps.Events/Webhooks/WebhookDeleted.cs index a01d60dc3..a04e86ab6 100644 --- a/src/Squidex.Domain.Apps.Events/Webhooks/WebhookDeleted.cs +++ b/src/Squidex.Domain.Apps.Events/Webhooks/WebhookDeleted.cs @@ -6,12 +6,11 @@ // All rights reserved. // ========================================================================== -using Squidex.Infrastructure; using Squidex.Infrastructure.CQRS.Events; namespace Squidex.Domain.Apps.Events.Webhooks { - [EventType(nameof(WebhookUpdated), 2)] + [EventType(nameof(WebhookDeleted), 2)] public sealed class WebhookDeleted : WebhookEvent { } diff --git a/src/Squidex.Infrastructure/CQRS/Events/NoopEvent.cs b/src/Squidex.Infrastructure/CQRS/Events/NoopEvent.cs index be6c125f0..c70e89334 100644 --- a/src/Squidex.Infrastructure/CQRS/Events/NoopEvent.cs +++ b/src/Squidex.Infrastructure/CQRS/Events/NoopEvent.cs @@ -8,6 +8,7 @@ namespace Squidex.Infrastructure.CQRS.Events { + [TypeName(nameof(NoopEvent))] public sealed class NoopEvent : IEvent { } diff --git a/src/Squidex/Config/Domain/Serializers.cs b/src/Squidex/Config/Domain/Serializers.cs index 59f8c9e5d..aba7c3559 100644 --- a/src/Squidex/Config/Domain/Serializers.cs +++ b/src/Squidex/Config/Domain/Serializers.cs @@ -14,6 +14,7 @@ using NodaTime; using NodaTime.Serialization.JsonNet; using Squidex.Domain.Apps.Events; using Squidex.Infrastructure; +using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.Json; namespace Squidex.Config.Domain @@ -51,6 +52,7 @@ namespace Squidex.Config.Domain static Serializers() { TypeNameRegistry.Map(typeof(SquidexEvent).GetTypeInfo().Assembly); + TypeNameRegistry.Map(typeof(NoopEvent).GetTypeInfo().Assembly); } private static JsonSerializerSettings CreateSettings() diff --git a/src/Squidex/Docs/schemabody.md b/src/Squidex/Docs/schemabody.md index bf97dd0de..57a6e9d40 100644 --- a/src/Squidex/Docs/schemabody.md +++ b/src/Squidex/Docs/schemabody.md @@ -4,4 +4,4 @@ Please note that each field is an object with one entry per language. If the field is not localizable you must use iv (Invariant Language) as a key. When you change the field to be localizable the value will become the value for the master language, depending what the master language is at this point of time. -Read more about it at: https://docs.squidex.io/04-guides/01-api.html \ No newline at end of file +Read more about it at: https://docs.squidex.io/04-guides/02-api.html \ No newline at end of file diff --git a/src/Squidex/Docs/schemaquery.md b/src/Squidex/Docs/schemaquery.md index aa78298b9..1642bd400 100644 --- a/src/Squidex/Docs/schemaquery.md +++ b/src/Squidex/Docs/schemaquery.md @@ -8,4 +8,4 @@ We support the following query options. * **$filter**: The $filter query option allows clients to filter a collection of resources that are addressed by a request URL. * **$orderby**: The $orderby query option allows clients to request resources in a particular order. -Read more about it at: https://docs.squidex.io/04-guides/01-api.html +Read more about it at: https://docs.squidex.io/04-guides/02-api.html diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts index f38b8cc3f..44affcfc2 100644 --- a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts @@ -156,6 +156,16 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit { }); } + public showField(field: FieldDto) { + this.appNameOnce() + .switchMap(app => this.schemasService.showField(app, this.schema.name, field.fieldId, this.schema.version)).retry(2) + .subscribe(() => { + this.updateSchema(this.schema.updateField(field.show(), this.authService.user!.token)); + }, error => { + this.notifyError(error); + }); + } + public hideField(field: FieldDto) { this.appNameOnce() .switchMap(app => this.schemasService.hideField(app, this.schema.name, field.fieldId, this.schema.version)).retry(2) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/ContentEnrichmentTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/ContentEnrichmentTests.cs index 35ed1e728..c50f0bc42 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/ContentEnrichmentTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/ContentEnrichmentTests.cs @@ -18,32 +18,30 @@ namespace Squidex.Domain.Apps.Core { public class ContentEnrichmentTests { + private static readonly Instant Now = Instant.FromUnixTimeSeconds(SystemClock.Instance.GetCurrentInstant().ToUnixTimeSeconds()); private readonly LanguagesConfig languagesConfig = LanguagesConfig.Create(Language.DE, Language.EN); + private readonly Schema schema = + Schema.Create("my-schema", new SchemaProperties()) + .AddOrUpdateField(new JsonField(1, "my-json", Partitioning.Invariant, + new JsonFieldProperties())) + .AddOrUpdateField(new StringField(2, "my-string", Partitioning.Language, + new StringFieldProperties { DefaultValue = "en-string" })) + .AddOrUpdateField(new NumberField(3, "my-number", Partitioning.Invariant, + new NumberFieldProperties { DefaultValue = 123 })) + .AddOrUpdateField(new AssetsField(4, "my-assets", Partitioning.Invariant, + new AssetsFieldProperties())) + .AddOrUpdateField(new BooleanField(5, "my-boolean", Partitioning.Invariant, + new BooleanFieldProperties { DefaultValue = true })) + .AddOrUpdateField(new DateTimeField(6, "my-datetime", Partitioning.Invariant, + new DateTimeFieldProperties { DefaultValue = Now })) + .AddOrUpdateField(new ReferencesField(7, "my-references", Partitioning.Invariant, + new ReferencesFieldProperties { SchemaId = Guid.NewGuid() })) + .AddOrUpdateField(new GeolocationField(8, "my-geolocation", Partitioning.Invariant, + new GeolocationFieldProperties())); [Fact] private void Should_enrich_with_default_values() { - var now = Instant.FromUnixTimeSeconds(SystemClock.Instance.GetCurrentInstant().ToUnixTimeSeconds()); - - var schema = - Schema.Create("my-schema", new SchemaProperties()) - .AddOrUpdateField(new JsonField(1, "my-json", Partitioning.Invariant, - new JsonFieldProperties())) - .AddOrUpdateField(new StringField(2, "my-string", Partitioning.Language, - new StringFieldProperties { DefaultValue = "en-string" })) - .AddOrUpdateField(new NumberField(3, "my-number", Partitioning.Invariant, - new NumberFieldProperties { DefaultValue = 123 })) - .AddOrUpdateField(new AssetsField(4, "my-assets", Partitioning.Invariant, - new AssetsFieldProperties())) - .AddOrUpdateField(new BooleanField(5, "my-boolean", Partitioning.Invariant, - new BooleanFieldProperties { DefaultValue = true })) - .AddOrUpdateField(new DateTimeField(6, "my-datetime", Partitioning.Invariant, - new DateTimeFieldProperties { DefaultValue = now })) - .AddOrUpdateField(new ReferencesField(7, "my-references", Partitioning.Invariant, - new ReferencesFieldProperties { SchemaId = Guid.NewGuid() })) - .AddOrUpdateField(new GeolocationField(8, "my-geolocation", Partitioning.Invariant, - new GeolocationFieldProperties())); - var data = new NamedContentData() .AddField("my-string", @@ -60,9 +58,29 @@ namespace Squidex.Domain.Apps.Core Assert.Equal("de-string", (string)data["my-string"]["de"]); Assert.Equal("en-string", (string)data["my-string"]["en"]); - Assert.Equal(now, InstantPattern.General.Parse((string)data["my-datetime"]["iv"]).Value); + Assert.Equal(Now, InstantPattern.General.Parse((string)data["my-datetime"]["iv"]).Value); Assert.Equal(true, (bool)data["my-boolean"]["iv"]); } + + [Fact] + private void Should_also_enrich_with_default_values_when_string_is_empty() + { + var now = Instant.FromUnixTimeSeconds(SystemClock.Instance.GetCurrentInstant().ToUnixTimeSeconds()); + + var data = + new NamedContentData() + .AddField("my-string", + new ContentFieldData() + .AddValue("de", string.Empty)) + .AddField("my-number", + new ContentFieldData() + .AddValue("iv", 456)); + + data.Enrich(schema, languagesConfig.ToResolver()); + + Assert.Equal("en-string", (string)data["my-string"]["de"]); + Assert.Equal("en-string", (string)data["my-string"]["en"]); + } } }