Browse Source

Simplify schema builders and add missing field builders.

pull/768/head
Sebastian 4 years ago
parent
commit
e64619ea7c
  1. 21
      backend/extensions/Squidex.Extensions/Samples/Middleware/TemplateInstance.cs
  2. 21
      backend/extensions/Squidex.Extensions/Samples/Middleware/TemplateMiddleware.cs
  3. 84
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/ArrayFieldBuilder.cs
  4. 37
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/AssetFieldBuilder.cs
  5. 17
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/BooleanFieldBuilder.cs
  6. 20
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/ComponentFieldBuilder.cs
  7. 20
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/ComponentsFieldBuilder.cs
  8. 17
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/DateTimeFieldBuilder.cs
  9. 51
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/FieldBuilder.cs
  10. 7
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/JsonFieldBuilder.cs
  11. 7
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/NumberFieldBuilder.cs
  12. 18
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/ReferencesFieldBuilder.cs
  13. 76
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/SchemaBuilder.cs
  14. 73
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/StringFieldBuilder.cs
  15. 17
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/TagsFieldBuilder.cs
  16. 20
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/UIFieldBuilder.cs
  17. 21
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateBlog.cs
  18. 70
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateProfile.cs
  19. 62
      backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs

21
backend/extensions/Squidex.Extensions/Samples/Middleware/TemplateInstance.cs

@ -6,6 +6,7 @@
// ========================================================================== // ==========================================================================
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Apps.Templates; using Squidex.Domain.Apps.Entities.Apps.Templates;
using Squidex.Domain.Apps.Entities.Apps.Templates.Builders; using Squidex.Domain.Apps.Entities.Apps.Templates.Builders;
@ -20,16 +21,26 @@ namespace Squidex.Extensions.Samples.Middleware
var schema = var schema =
SchemaBuilder.Create("Blogs") SchemaBuilder.Create("Blogs")
.AddString("Title", f => f .AddString("Title", f => f
.Length(100) .Properties(p => p with
{
MaxLength = 100
})
.Required()) .Required())
.AddString("Slug", f => f .AddString("Slug", f => f
.Length(100) .Properties(p => p with
{
MaxLength = 100
})
.Required() .Required()
.Disabled()) .Disabled())
.AddString("Text", f => f .AddString("Text", f => f
.Length(1000) .Properties(p => p with
.Required() {
.AsRichText()) Editor = StringFieldEditor.RichText,
MaxLength = 1000,
MinLength = 200
})
.Required())
.Build(); .Build();
return publish(schema); return publish(schema);

21
backend/extensions/Squidex.Extensions/Samples/Middleware/TemplateMiddleware.cs

@ -7,6 +7,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities; using Squidex.Domain.Apps.Entities;
using Squidex.Domain.Apps.Entities.Apps.Commands; using Squidex.Domain.Apps.Entities.Apps.Commands;
using Squidex.Domain.Apps.Entities.Apps.Templates.Builders; using Squidex.Domain.Apps.Entities.Apps.Templates.Builders;
@ -35,16 +36,26 @@ namespace Squidex.Extensions.Samples.Middleware
var schema = var schema =
SchemaBuilder.Create("Pages") SchemaBuilder.Create("Pages")
.AddString("Title", f => f .AddString("Title", f => f
.Length(100) .Properties(p => p with
{
MaxLength = 100
})
.Required()) .Required())
.AddString("Slug", f => f .AddString("Slug", f => f
.Length(100) .Properties(p => p with
{
MaxLength = 100
})
.Required() .Required()
.Disabled()) .Disabled())
.AddString("Text", f => f .AddString("Text", f => f
.Length(1000) .Properties(p => p with
.Required() {
.AsRichText()) Editor = StringFieldEditor.RichText,
MaxLength = 1000,
MinLength = 200
})
.Required())
.Build(); .Build();
await publish(schema); await publish(schema);

84
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/ArrayFieldBuilder.cs

@ -13,96 +13,134 @@ using Squidex.Text;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{ {
public class ArrayFieldBuilder : FieldBuilder<ArrayFieldBuilder> public sealed class ArrayFieldBuilder : FieldBuilder<ArrayFieldBuilder, ArrayFieldProperties>
{ {
private UpsertSchemaField TypedField private UpsertSchemaField TypedField
{ {
get => (UpsertSchemaField)Field; get => (UpsertSchemaField)Field;
} }
public ArrayFieldBuilder(UpsertSchemaField field, CreateSchema schema) public ArrayFieldBuilder(UpsertSchemaField field, ArrayFieldProperties properties, CreateSchema schema)
: base(field, schema) : base(field, properties, schema)
{ {
} }
public ArrayFieldBuilder AddAssets(string name, Action<AssetFieldBuilder> configure) public ArrayFieldBuilder AddAssets(string name, Action<AssetFieldBuilder> configure)
{ {
var field = AddField<AssetsFieldProperties>(name); var (field, properties) = AddField<AssetsFieldProperties>(name);
configure(new AssetFieldBuilder(field, Schema)); configure(new AssetFieldBuilder(field, properties, Schema));
return this; return this;
} }
public ArrayFieldBuilder AddBoolean(string name, Action<BooleanFieldBuilder> configure) public ArrayFieldBuilder AddBoolean(string name, Action<BooleanFieldBuilder> configure)
{ {
var field = AddField<BooleanFieldProperties>(name); var (field, properties) = AddField<BooleanFieldProperties>(name);
configure(new BooleanFieldBuilder(field, Schema)); configure(new BooleanFieldBuilder(field, properties, Schema));
return this; return this;
} }
public ArrayFieldBuilder AddDateTime(string name, Action<DateTimeFieldBuilder> configure) public ArrayFieldBuilder AddDateTime(string name, Action<DateTimeFieldBuilder> configure)
{ {
var field = AddField<DateTimeFieldProperties>(name); var (field, properties) = AddField<DateTimeFieldProperties>(name);
configure(new DateTimeFieldBuilder(field, Schema)); configure(new DateTimeFieldBuilder(field, properties, Schema));
return this;
}
public ArrayFieldBuilder AddComponent(string name, Action<ComponentFieldBuilder> configure)
{
var (field, properties) = AddField<ComponentFieldProperties>(name);
configure(new ComponentFieldBuilder(field, properties, Schema));
return this;
}
public ArrayFieldBuilder AddComponents(string name, Action<ComponentsFieldBuilder> configure)
{
var (field, properties) = AddField<ComponentsFieldProperties>(name);
configure(new ComponentsFieldBuilder(field, properties, Schema));
return this; return this;
} }
public ArrayFieldBuilder AddJson(string name, Action<JsonFieldBuilder> configure) public ArrayFieldBuilder AddJson(string name, Action<JsonFieldBuilder> configure)
{ {
var field = AddField<JsonFieldProperties>(name); var (field, properties) = AddField<JsonFieldProperties>(name);
configure(new JsonFieldBuilder(field, Schema)); configure(new JsonFieldBuilder(field, properties, Schema));
return this; return this;
} }
public ArrayFieldBuilder AddNumber(string name, Action<NumberFieldBuilder> configure) public ArrayFieldBuilder AddNumber(string name, Action<NumberFieldBuilder> configure)
{ {
var field = AddField<NumberFieldProperties>(name); var (field, properties) = AddField<NumberFieldProperties>(name);
configure(new NumberFieldBuilder(field, Schema)); configure(new NumberFieldBuilder(field, properties, Schema));
return this; return this;
} }
public ArrayFieldBuilder AddReferences(string name, Action<ReferencesFieldBuilder> configure) public ArrayFieldBuilder AddReferences(string name, Action<ReferencesFieldBuilder> configure)
{ {
var field = AddField<ReferencesFieldProperties>(name); var (field, properties) = AddField<ReferencesFieldProperties>(name);
configure(new ReferencesFieldBuilder(field, Schema)); configure(new ReferencesFieldBuilder(field, properties, Schema));
return this; return this;
} }
public ArrayFieldBuilder AddString(string name, Action<StringFieldBuilder> configure) public ArrayFieldBuilder AddString(string name, Action<StringFieldBuilder> configure)
{ {
var field = AddField<StringFieldProperties>(name); var (field, properties) = AddField<StringFieldProperties>(name);
configure(new StringFieldBuilder(field, Schema)); configure(new StringFieldBuilder(field, properties, Schema));
return this; return this;
} }
private UpsertSchemaNestedField AddField<T>(string name) where T : FieldProperties, new() public ArrayFieldBuilder AddTags(string name, Action<TagsFieldBuilder> configure)
{ {
var nestedField = new UpsertSchemaNestedField var (field, properties) = AddField<TagsFieldProperties>(name);
configure(new TagsFieldBuilder(field, properties, Schema));
return this;
}
public ArrayFieldBuilder AddUI(string name, Action<UIFieldBuilder> configure)
{ {
Name = name.ToCamelCase(), var (field, properties) = AddField<UIFieldProperties>(name);
Properties = new T
configure(new UIFieldBuilder(field, properties, Schema));
return this;
}
private (UpsertSchemaNestedField, T) AddField<T>(string name) where T : FieldProperties, new()
{
var properties = new T
{ {
Label = name Label = name
} };
var nestedField = new UpsertSchemaNestedField
{
Name = name.ToCamelCase(),
Properties = properties
}; };
TypedField.Nested ??= Array.Empty<UpsertSchemaNestedField>(); TypedField.Nested ??= Array.Empty<UpsertSchemaNestedField>();
TypedField.Nested = TypedField.Nested.Union(new[] { nestedField }).ToArray(); TypedField.Nested = TypedField.Nested.Union(new[] { nestedField }).ToArray();
return nestedField; return (nestedField, properties);
} }
} }
} }

37
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/AssetFieldBuilder.cs

@ -5,47 +5,16 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using Squidex.Domain.Apps.Core.Assets;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas.Commands; using Squidex.Domain.Apps.Entities.Schemas.Commands;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{ {
public class AssetFieldBuilder : FieldBuilder<AssetFieldBuilder> public sealed class AssetFieldBuilder : FieldBuilder<AssetFieldBuilder, AssetsFieldProperties>
{ {
public AssetFieldBuilder(UpsertSchemaFieldBase field, CreateSchema schema) public AssetFieldBuilder(UpsertSchemaFieldBase field, AssetsFieldProperties properties, CreateSchema schema)
: base(field, schema) : base(field, properties, schema)
{ {
} }
public AssetFieldBuilder MustBeImage()
{
Properties<AssetsFieldProperties>(p => p with
{
ExpectedType = AssetType.Image
});
return this;
}
public AssetFieldBuilder MustBe(AssetType type)
{
Properties<AssetsFieldProperties>(p => p with
{
ExpectedType = type
});
return this;
}
public AssetFieldBuilder RequireSingle()
{
Properties<AssetsFieldProperties>(p => p with
{
MaxItems = 1
});
return this;
}
} }
} }

17
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/BooleanFieldBuilder.cs

@ -10,22 +10,11 @@ using Squidex.Domain.Apps.Entities.Schemas.Commands;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{ {
public class BooleanFieldBuilder : FieldBuilder<BooleanFieldBuilder> public sealed class BooleanFieldBuilder : FieldBuilder<BooleanFieldBuilder, BooleanFieldProperties>
{ {
public BooleanFieldBuilder(UpsertSchemaFieldBase field, CreateSchema schema) public BooleanFieldBuilder(UpsertSchemaFieldBase field, BooleanFieldProperties properties, CreateSchema schema)
: base(field, schema) : base(field, properties, schema)
{ {
} }
public BooleanFieldBuilder AsToggle()
{
Properties<BooleanFieldProperties>(p => p with
{
Editor = BooleanFieldEditor.Toggle,
EditorUrl = null
});
return this;
}
} }
} }

20
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/ComponentFieldBuilder.cs

@ -0,0 +1,20 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas.Commands;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{
public sealed class ComponentFieldBuilder : FieldBuilder<ComponentFieldBuilder, ComponentFieldProperties>
{
public ComponentFieldBuilder(UpsertSchemaFieldBase field, ComponentFieldProperties properties, CreateSchema schema)
: base(field, properties, schema)
{
}
}
}

20
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/ComponentsFieldBuilder.cs

@ -0,0 +1,20 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas.Commands;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{
public sealed class ComponentsFieldBuilder : FieldBuilder<ComponentsFieldBuilder, ComponentsFieldProperties>
{
public ComponentsFieldBuilder(UpsertSchemaFieldBase field, ComponentsFieldProperties properties, CreateSchema schema)
: base(field, properties, schema)
{
}
}
}

17
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/DateTimeFieldBuilder.cs

@ -10,22 +10,11 @@ using Squidex.Domain.Apps.Entities.Schemas.Commands;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{ {
public class DateTimeFieldBuilder : FieldBuilder<DateTimeFieldBuilder> public sealed class DateTimeFieldBuilder : FieldBuilder<DateTimeFieldBuilder, DateTimeFieldProperties>
{ {
public DateTimeFieldBuilder(UpsertSchemaFieldBase field, CreateSchema schema) public DateTimeFieldBuilder(UpsertSchemaFieldBase field, DateTimeFieldProperties properties, CreateSchema schema)
: base(field, schema) : base(field, properties, schema)
{ {
} }
public DateTimeFieldBuilder AsDateTime()
{
Properties<DateTimeFieldProperties>(p => p with
{
Editor = DateTimeFieldEditor.DateTime,
EditorUrl = null
});
return this;
}
} }
} }

51
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/FieldBuilder.cs

@ -15,59 +15,68 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
public abstract class FieldBuilder public abstract class FieldBuilder
{ {
protected UpsertSchemaFieldBase Field { get; init; } protected UpsertSchemaFieldBase Field { get; init; }
protected CreateSchema Schema { get; init; } protected CreateSchema Schema { get; init; }
} }
public abstract class FieldBuilder<T> : FieldBuilder public abstract class FieldBuilder<T, TProperties> : FieldBuilder where T : FieldBuilder where TProperties : FieldProperties
where T : FieldBuilder
{ {
protected FieldBuilder(UpsertSchemaFieldBase field, CreateSchema schema) private TProperties properties;
protected FieldBuilder(UpsertSchemaFieldBase field, TProperties properties, CreateSchema schema)
{ {
this.properties = properties;
Field = field; Field = field;
Schema = schema; Schema = schema;
} }
public T Label(string? label) public T Localizable()
{
if (Field is UpsertSchemaField localizableField)
{ {
Field.Properties = Field.Properties with { Label = label }; localizableField.Partitioning = Partitioning.Language.Key;
}
return (T)(object)this; return (T)(object)this;
} }
public T Hints(string? hints) public T Disabled(bool isDisabled = true)
{ {
Field.Properties = Field.Properties with { Hints = hints }; Field.IsDisabled = isDisabled;
return (T)(object)this; return (T)(object)this;
} }
public T Localizable() public T Hidden(bool isHidden = true)
{
if (Field is UpsertSchemaField localizableField)
{ {
localizableField.Partitioning = Partitioning.Language.Key; Field.IsHidden = isHidden;
}
return (T)(object)this; return (T)(object)this;
} }
public T Disabled() public T Label(string? label)
{ {
Field.IsDisabled = true; return Properties(x => x with { Label = label });
return (T)(object)this;
} }
public T Required() public T Hints(string? hints)
{ {
Field.Properties = Field.Properties with { IsRequired = true }; return Properties(x => x with { Hints = hints });
}
return (T)(object)this; public T Required(bool isRequired = true)
{
return Properties(x => x with { IsRequired = isRequired });
} }
protected void Properties<TProperties>(Func<TProperties, TProperties> updater) where TProperties : FieldProperties public T Properties(Func<TProperties, TProperties> updater)
{ {
Field.Properties = updater((TProperties)Field.Properties); properties = updater(properties);
Field.Properties = properties;
return (T)(object)this;
} }
public T ShowInList() public T ShowInList()

7
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/JsonFieldBuilder.cs

@ -5,14 +5,15 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas.Commands; using Squidex.Domain.Apps.Entities.Schemas.Commands;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{ {
public class JsonFieldBuilder : FieldBuilder<JsonFieldBuilder> public sealed class JsonFieldBuilder : FieldBuilder<JsonFieldBuilder, JsonFieldProperties>
{ {
public JsonFieldBuilder(UpsertSchemaFieldBase field, CreateSchema schema) public JsonFieldBuilder(UpsertSchemaFieldBase field, JsonFieldProperties properties, CreateSchema schema)
: base(field, schema) : base(field, properties, schema)
{ {
} }
} }

7
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/NumberFieldBuilder.cs

@ -5,14 +5,15 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas.Commands; using Squidex.Domain.Apps.Entities.Schemas.Commands;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{ {
public class NumberFieldBuilder : FieldBuilder<NumberFieldBuilder> public sealed class NumberFieldBuilder : FieldBuilder<NumberFieldBuilder, NumberFieldProperties>
{ {
public NumberFieldBuilder(UpsertSchemaFieldBase field, CreateSchema schema) public NumberFieldBuilder(UpsertSchemaFieldBase field, NumberFieldProperties properties, CreateSchema schema)
: base(field, schema) : base(field, properties, schema)
{ {
} }
} }

18
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/ReferencesFieldBuilder.cs

@ -7,26 +7,14 @@
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas.Commands; using Squidex.Domain.Apps.Entities.Schemas.Commands;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Collections;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{ {
public class ReferencesFieldBuilder : FieldBuilder<ReferencesFieldBuilder> public sealed class ReferencesFieldBuilder : FieldBuilder<ReferencesFieldBuilder, ReferencesFieldProperties>
{ {
public ReferencesFieldBuilder(UpsertSchemaFieldBase field, CreateSchema schema) public ReferencesFieldBuilder(UpsertSchemaFieldBase field, ReferencesFieldProperties properties, CreateSchema schema)
: base(field, schema) : base(field, properties, schema)
{ {
} }
public ReferencesFieldBuilder WithSchemaId(DomainId id)
{
Properties<ReferencesFieldProperties>(p => p with
{
SchemaIds = ImmutableList.Create(id)
});
return this;
}
} }
} }

76
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/SchemaBuilder.cs

@ -67,96 +67,122 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
return this; return this;
} }
public SchemaBuilder AddArray(string name, Action<ArrayFieldBuilder> configure)
{
var (field, properties) = AddField<ArrayFieldProperties>(name);
configure(new ArrayFieldBuilder(field, properties, command));
return this;
}
public SchemaBuilder AddAssets(string name, Action<AssetFieldBuilder> configure) public SchemaBuilder AddAssets(string name, Action<AssetFieldBuilder> configure)
{ {
var field = AddField<AssetsFieldProperties>(name); var (field, properties) = AddField<AssetsFieldProperties>(name);
configure(new AssetFieldBuilder(field, command)); configure(new AssetFieldBuilder(field, properties, command));
return this; return this;
} }
public SchemaBuilder AddBoolean(string name, Action<BooleanFieldBuilder> configure) public SchemaBuilder AddBoolean(string name, Action<BooleanFieldBuilder> configure)
{ {
var field = AddField<BooleanFieldProperties>(name); var (field, properties) = AddField<BooleanFieldProperties>(name);
configure(new BooleanFieldBuilder(field, command)); configure(new BooleanFieldBuilder(field, properties, command));
return this;
}
public SchemaBuilder AddComponent(string name, Action<ComponentFieldBuilder> configure)
{
var (field, properties) = AddField<ComponentFieldProperties>(name);
configure(new ComponentFieldBuilder(field, properties, command));
return this;
}
public SchemaBuilder AddComponents(string name, Action<ComponentsFieldBuilder> configure)
{
var (field, properties) = AddField<ComponentsFieldProperties>(name);
configure(new ComponentsFieldBuilder(field, properties, command));
return this; return this;
} }
public SchemaBuilder AddDateTime(string name, Action<DateTimeFieldBuilder> configure) public SchemaBuilder AddDateTime(string name, Action<DateTimeFieldBuilder> configure)
{ {
var field = AddField<DateTimeFieldProperties>(name); var (field, properties) = AddField<DateTimeFieldProperties>(name);
configure(new DateTimeFieldBuilder(field, command)); configure(new DateTimeFieldBuilder(field, properties, command));
return this; return this;
} }
public SchemaBuilder AddJson(string name, Action<JsonFieldBuilder> configure) public SchemaBuilder AddJson(string name, Action<JsonFieldBuilder> configure)
{ {
var field = AddField<JsonFieldProperties>(name); var (field, properties) = AddField<JsonFieldProperties>(name);
configure(new JsonFieldBuilder(field, command)); configure(new JsonFieldBuilder(field, properties, command));
return this; return this;
} }
public SchemaBuilder AddNumber(string name, Action<NumberFieldBuilder> configure) public SchemaBuilder AddNumber(string name, Action<NumberFieldBuilder> configure)
{ {
var field = AddField<NumberFieldProperties>(name); var (field, properties) = AddField<NumberFieldProperties>(name);
configure(new NumberFieldBuilder(field, command)); configure(new NumberFieldBuilder(field, properties, command));
return this; return this;
} }
public SchemaBuilder AddReferences(string name, Action<ReferencesFieldBuilder> configure) public SchemaBuilder AddReferences(string name, Action<ReferencesFieldBuilder> configure)
{ {
var field = AddField<ReferencesFieldProperties>(name); var (field, properties) = AddField<ReferencesFieldProperties>(name);
configure(new ReferencesFieldBuilder(field, command)); configure(new ReferencesFieldBuilder(field, properties, command));
return this; return this;
} }
public SchemaBuilder AddString(string name, Action<StringFieldBuilder> configure) public SchemaBuilder AddString(string name, Action<StringFieldBuilder> configure)
{ {
var field = AddField<StringFieldProperties>(name); var (field, properties) = AddField<StringFieldProperties>(name);
configure(new StringFieldBuilder(field, command)); configure(new StringFieldBuilder(field, properties, command));
return this; return this;
} }
public SchemaBuilder AddTags(string name, Action<TagsFieldBuilder> configure) public SchemaBuilder AddTags(string name, Action<TagsFieldBuilder> configure)
{ {
var field = AddField<TagsFieldProperties>(name); var (field, properties) = AddField<TagsFieldProperties>(name);
configure(new TagsFieldBuilder(field, command)); configure(new TagsFieldBuilder(field, properties, command));
return this; return this;
} }
public SchemaBuilder AddArray(string name, Action<ArrayFieldBuilder> configure) public SchemaBuilder AddUI(string name, Action<UIFieldBuilder> configure)
{ {
var field = AddField<ArrayFieldProperties>(name); var (field, properties) = AddField<UIFieldProperties>(name);
configure(new ArrayFieldBuilder(field, command)); configure(new UIFieldBuilder(field, properties, command));
return this; return this;
} }
private UpsertSchemaField AddField<T>(string name) where T : FieldProperties, new() private (UpsertSchemaField, T) AddField<T>(string name) where T : FieldProperties, new()
{ {
var properties = new T { Label = name };
var field = new UpsertSchemaField var field = new UpsertSchemaField
{ {
Name = name.ToCamelCase(), Name = name.ToCamelCase(),
Properties = new T Properties = properties,
{
Label = name
}
}; };
if (command.Fields == null) if (command.Fields == null)
@ -168,7 +194,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
command.Fields = command.Fields.Union(Enumerable.Repeat(field, 1)).ToArray(); command.Fields = command.Fields.Union(Enumerable.Repeat(field, 1)).ToArray();
} }
return field; return (field, properties);
} }
public CreateSchema Build() public CreateSchema Build()

73
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/StringFieldBuilder.cs

@ -7,81 +7,14 @@
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas.Commands; using Squidex.Domain.Apps.Entities.Schemas.Commands;
using Squidex.Infrastructure.Collections;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{ {
public class StringFieldBuilder : FieldBuilder<StringFieldBuilder> public sealed class StringFieldBuilder : FieldBuilder<StringFieldBuilder, StringFieldProperties>
{ {
public StringFieldBuilder(UpsertSchemaFieldBase field, CreateSchema schema) public StringFieldBuilder(UpsertSchemaFieldBase field, StringFieldProperties properties, CreateSchema schema)
: base(field, schema) : base(field, properties, schema)
{ {
} }
public StringFieldBuilder AsTextArea()
{
Properties<StringFieldProperties>(p => p with
{
EditorUrl = null,
Editor = StringFieldEditor.TextArea
});
return this;
}
public StringFieldBuilder AsRichText()
{
Properties<StringFieldProperties>(p => p with
{
EditorUrl = null,
Editor = StringFieldEditor.RichText
});
return this;
}
public StringFieldBuilder AsDropDown(params string[] values)
{
Properties<StringFieldProperties>(p => p with
{
AllowedValues = ImmutableList.Create(values),
EditorUrl = null,
Editor = StringFieldEditor.Dropdown
});
return this;
}
public StringFieldBuilder Unique()
{
Properties<StringFieldProperties>(p => p with
{
IsUnique = true
});
return this;
}
public StringFieldBuilder Pattern(string pattern, string? message = null)
{
Properties<StringFieldProperties>(p => p with
{
Pattern = pattern,
PatternMessage = message
});
return this;
}
public StringFieldBuilder Length(int maxLength, int minLength = 0)
{
Properties<StringFieldProperties>(p => p with
{
MaxLength = maxLength,
MinLength = minLength
});
return this;
}
} }
} }

17
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/TagsFieldBuilder.cs

@ -7,25 +7,14 @@
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas.Commands; using Squidex.Domain.Apps.Entities.Schemas.Commands;
using Squidex.Infrastructure.Collections;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{ {
public class TagsFieldBuilder : FieldBuilder<TagsFieldBuilder> public sealed class TagsFieldBuilder : FieldBuilder<TagsFieldBuilder, TagsFieldProperties>
{ {
public TagsFieldBuilder(UpsertSchemaField field, CreateSchema schema) public TagsFieldBuilder(UpsertSchemaFieldBase field, TagsFieldProperties properties, CreateSchema schema)
: base(field, schema) : base(field, properties, schema)
{ {
} }
public TagsFieldBuilder WithAllowedValues(params string[] values)
{
Properties<TagsFieldProperties>(p => p with
{
AllowedValues = ImmutableList.Create(values)
});
return this;
}
} }
} }

20
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/UIFieldBuilder.cs

@ -0,0 +1,20 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas.Commands;
namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders
{
public sealed class UIFieldBuilder : FieldBuilder<UIFieldBuilder, UIFieldProperties>
{
public UIFieldBuilder(UpsertSchemaFieldBase field, UIFieldProperties properties, CreateSchema schema)
: base(field, properties, schema)
{
}
}
}

21
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateBlog.cs

@ -7,6 +7,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Apps.Templates.Builders; using Squidex.Domain.Apps.Entities.Apps.Templates.Builders;
using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Domain.Apps.Entities.Contents.Commands;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -67,12 +68,18 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
var schema = var schema =
SchemaBuilder.Create("Posts") SchemaBuilder.Create("Posts")
.AddString("Title", f => f .AddString("Title", f => f
.Length(100) .Properties(p => p with
{
MaxLength = 100
})
.Required() .Required()
.ShowInList() .ShowInList()
.Hints("The title of the post.")) .Hints("The title of the post."))
.AddString("Text", f => f .AddString("Text", f => f
.AsRichText() .Properties(p => p with
{
Editor = StringFieldEditor.RichText
})
.Required() .Required()
.Hints("The text of the post.")) .Hints("The text of the post."))
.AddString("Slug", f => f .AddString("Slug", f => f
@ -92,12 +99,18 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
var schema = var schema =
SchemaBuilder.Create("Pages") SchemaBuilder.Create("Pages")
.AddString("Title", f => f .AddString("Title", f => f
.Length(100) .Properties(p => p with
{
MaxLength = 100
})
.Required() .Required()
.ShowInList() .ShowInList()
.Hints("The title of the page.")) .Hints("The title of the page."))
.AddString("Text", f => f .AddString("Text", f => f
.AsRichText() .Properties(p => p with
{
Editor = StringFieldEditor.RichText
})
.Required() .Required()
.Hints("The text of the page.")) .Hints("The text of the page."))
.AddString("Slug", f => f .AddString("Slug", f => f

70
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateProfile.cs

@ -6,10 +6,13 @@
// ========================================================================== // ==========================================================================
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Assets;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Apps.Templates.Builders; using Squidex.Domain.Apps.Entities.Apps.Templates.Builders;
using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Domain.Apps.Entities.Contents.Commands;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Collections;
namespace Squidex.Domain.Apps.Entities.Apps.Templates namespace Squidex.Domain.Apps.Entities.Apps.Templates
{ {
@ -64,17 +67,31 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
.ShowInList() .ShowInList()
.Hints("Your last name.")) .Hints("Your last name."))
.AddAssets("Image", f => f .AddAssets("Image", f => f
.MustBeImage() .Properties(p => p with
{
ExpectedType = AssetType.Image,
MaxItems = 1,
MinItems = 1
})
.Hints("Your profile image.")) .Hints("Your profile image."))
.AddString("Profession", f => f .AddString("Profession", f => f
.AsTextArea() .Properties(p => p with
{
Editor = StringFieldEditor.TextArea
})
.Required() .Required()
.Hints("Describe your profession.")) .Hints("Describe your profession."))
.AddString("Summary", f => f .AddString("Summary", f => f
.AsTextArea() .Properties(p => p with
{
Editor = StringFieldEditor.TextArea
})
.Hints("Write a short summary about yourself.")) .Hints("Write a short summary about yourself."))
.AddString("Legal Terms", f => f .AddString("Legal Terms", f => f
.AsTextArea() .Properties(p => p with
{
Editor = StringFieldEditor.TextArea
})
.Hints("The terms to fulfill legal requirements.")) .Hints("The terms to fulfill legal requirements."))
.AddString("Github Link", f => f .AddString("Github Link", f => f
.Hints("An optional link to your Github account.")) .Hints("An optional link to your Github account."))
@ -102,15 +119,23 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
.ShowInList() .ShowInList()
.Hints("The name of your project.")) .Hints("The name of your project."))
.AddString("Description", f => f .AddString("Description", f => f
.AsTextArea() .Properties(p => p with
{
Editor = StringFieldEditor.TextArea
})
.Required() .Required()
.Hints("Describe your project.")) .Hints("Describe your project."))
.AddAssets("Image", f => f .AddAssets("Image", f => f
.MustBeImage() .Properties(p => p with
{
ExpectedType = AssetType.Image,
MaxItems = 1,
MinItems = 1
})
.Required() .Required()
.Hints("An image or screenshot for your project.")) .Hints("An image or screenshot for your project."))
.AddString("Label", f => f .AddString("Label", f => f
.AsTextArea() .Properties(p => p with { Editor = StringFieldEditor.TextArea })
.Hints("An optional label to categorize your project, e.g. 'Open Source'.")) .Hints("An optional label to categorize your project, e.g. 'Open Source'."))
.AddString("Link", f => f .AddString("Link", f => f
.Hints("An optional link to your project.")) .Hints("An optional link to your project."))
@ -136,7 +161,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
.ShowInList() .ShowInList()
.Hints("The company or organization you worked for.")) .Hints("The company or organization you worked for."))
.AddAssets("Logo", f => f .AddAssets("Logo", f => f
.MustBeImage() .Properties(p => p with
{
ExpectedType = AssetType.Image,
MaxItems = 1,
MinItems = 1
})
.Hints("The logo of the company or organization you worked for.")) .Hints("The logo of the company or organization you worked for."))
.AddDateTime("From", f => f .AddDateTime("From", f => f
.Required() .Required()
@ -163,7 +193,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
.ShowInList() .ShowInList()
.Hints("The school or university.")) .Hints("The school or university."))
.AddAssets("Logo", f => f .AddAssets("Logo", f => f
.MustBeImage() .Properties(p => p with
{
ExpectedType = AssetType.Image,
MaxItems = 1,
MinItems = 1
})
.Hints("The logo of the school or university.")) .Hints("The logo of the school or university."))
.AddDateTime("From", f => f .AddDateTime("From", f => f
.Required() .Required()
@ -186,7 +221,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
.ShowInList() .ShowInList()
.Hints("The name or title of your publication.")) .Hints("The name or title of your publication."))
.AddAssets("Cover", f => f .AddAssets("Cover", f => f
.MustBeImage() .Properties(p => p with
{
ExpectedType = AssetType.Image,
MaxItems = 1,
MinItems = 1
})
.Hints("The cover of your publication.")) .Hints("The cover of your publication."))
.AddString("Description", f => f .AddString("Description", f => f
.Hints("Describe the content of your publication.")) .Hints("Describe the content of your publication."))
@ -208,7 +248,15 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
.ShowInList() .ShowInList()
.Hints("The name of the skill.")) .Hints("The name of the skill."))
.AddString("Experience", f => f .AddString("Experience", f => f
.AsDropDown("Beginner", "Advanced", "Professional", "Expert") .Properties(p => p with
{
AllowedValues = ImmutableList.Create(
"Beginner",
"Advanced",
"Professional",
"Expert"),
Editor = StringFieldEditor.Dropdown,
})
.Required() .Required()
.ShowInList() .ShowInList()
.Hints("The level of experience.")) .Hints("The level of experience."))

62
backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs

@ -24,6 +24,8 @@ using Squidex.Log;
using Squidex.Shared.Identity; using Squidex.Shared.Identity;
using Squidex.Shared.Users; using Squidex.Shared.Users;
#pragma warning disable MA0073 // Avoid comparison with bool constant
namespace Squidex.Domain.Apps.Entities.History namespace Squidex.Domain.Apps.Entities.History
{ {
public class NotifoService : IUserEvents public class NotifoService : IUserEvents
@ -167,32 +169,16 @@ namespace Squidex.Domain.Apps.Entities.History
var maxAge = now - MaxAge; var maxAge = now - MaxAge;
var batches = events var batches = events
.Where(x => !x.AppEvent.Headers.Restored()) .Where(x => x.AppEvent.Headers.Restored() == false)
.Where(x => IsNewer(x.AppEvent.Headers, maxAge)) .Where(x => x.AppEvent.Headers.Timestamp() > maxAge)
.Where(x => IsComment(x.AppEvent.Payload) || x.HistoryEvent != null) .SelectMany(x => CreateRequests(x.AppEvent, x.HistoryEvent))
.Batch(50); .Batch(50);
foreach (var batch in batches) foreach (var batch in batches)
{ {
var requests = new List<PublishDto>();
foreach (var @event in batch)
{
var payload = @event.AppEvent.Payload;
if (payload is CommentCreated comment && IsComment(payload))
{
AddMentions(requests, comment);
}
else if (@event.HistoryEvent != null)
{
AddHistoryEvent(requests, @event.HistoryEvent, payload);
}
}
var request = new PublishManyDto var request = new PublishManyDto
{ {
Requests = requests Requests = batch.ToList()
}; };
await client.Events.PostEventsAsync(options.AppId, request); await client.Events.PostEventsAsync(options.AppId, request);
@ -269,7 +255,22 @@ namespace Squidex.Domain.Apps.Entities.History
} }
} }
private void AddHistoryEvent(List<PublishDto> requests, HistoryEvent historyEvent, AppEvent payload) private IEnumerable<PublishDto> CreateRequests(Envelope<AppEvent> appEvent, HistoryEvent? historyEvent)
{
if (appEvent.Payload is CommentCreated comment && comment.Mentions?.Length > 0)
{
foreach (var userId in comment.Mentions)
{
yield return CreateMentionRequest(comment, userId);
}
}
else if (historyEvent != null)
{
yield return CreateHistoryRequest(historyEvent, appEvent.Payload);
}
}
private PublishDto CreateHistoryRequest(HistoryEvent historyEvent, AppEvent payload)
{ {
var publishRequest = new PublishDto var publishRequest = new PublishDto
{ {
@ -295,12 +296,10 @@ namespace Squidex.Domain.Apps.Entities.History
SetUser(payload, publishRequest); SetUser(payload, publishRequest);
SetTopic(payload, publishRequest, historyEvent); SetTopic(payload, publishRequest, historyEvent);
requests.Add(publishRequest); return publishRequest;
} }
private static void AddMentions(List<PublishDto> requests, CommentCreated comment) private static PublishDto CreateMentionRequest(CommentCreated comment, string userId)
{
foreach (var userId in comment.Mentions!)
{ {
var publishRequest = new PublishDto var publishRequest = new PublishDto
{ {
@ -324,18 +323,7 @@ namespace Squidex.Domain.Apps.Entities.History
SetUser(comment, publishRequest); SetUser(comment, publishRequest);
requests.Add(publishRequest); return publishRequest;
}
}
private static bool IsNewer(EnvelopeHeaders headers, Instant maxAge)
{
return headers.Timestamp() > maxAge;
}
private static bool IsComment(AppEvent appEvent)
{
return appEvent is CommentCreated comment && comment.Mentions?.Length > 0;
} }
private static void SetUser(AppEvent appEvent, PublishDto publishRequest) private static void SetUser(AppEvent appEvent, PublishDto publishRequest)

Loading…
Cancel
Save