Browse Source

Optin to GraphQL enum. (#849)

pull/850/head
Sebastian Stehle 4 years ago
committed by GitHub
parent
commit
be7c7a6218
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      backend/i18n/frontend_en.json
  2. 2
      backend/i18n/frontend_it.json
  3. 2
      backend/i18n/frontend_nl.json
  4. 2
      backend/i18n/frontend_zh.json
  5. 2
      backend/i18n/source/frontend_en.json
  6. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs
  7. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs
  8. 6
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs
  9. 25
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs
  10. 29
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs
  11. 23
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs
  12. 60
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/Names.cs
  13. 50
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs
  14. 15
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Extensions.cs
  15. 5
      backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs
  16. 5
      backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs
  17. 13
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLMutationTests.cs
  18. 44
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestContent.cs
  19. 32
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestSchemas.cs
  20. 15
      frontend/src/app/features/schemas/pages/schema/fields/types/string-ui.component.html
  21. 17
      frontend/src/app/features/schemas/pages/schema/fields/types/tags-ui.component.html
  22. 2
      frontend/src/app/shared/services/schemas.types.ts
  23. 2
      frontend/src/app/shared/state/schemas.forms.ts

2
backend/i18n/frontend_en.json

@ -787,6 +787,8 @@
"schemas.export.recreateFields": "Recreate fields",
"schemas.export.synchronize": "Synchronize",
"schemas.field.allowedValues": "Allowed Values",
"schemas.field.createEnum": "Generate GraphQL Enum.",
"schemas.field.createEnumHint": "Check this checkbox to create a GraphQL enumeration for this field.",
"schemas.field.defaultValue": "Default Value",
"schemas.field.defaultValues": "Default Values",
"schemas.field.defaultValuesHint": "Set the default value per language and override the default value property, if defined. Only use it if really needed.",

2
backend/i18n/frontend_it.json

@ -787,6 +787,8 @@
"schemas.export.recreateFields": "Ricrea i campi",
"schemas.export.synchronize": "Sincronizza",
"schemas.field.allowedValues": "Valori consentiti",
"schemas.field.createEnum": "Generate GraphQL Enum.",
"schemas.field.createEnumHint": "Check this checkbox to create a GraphQL enumeration for this field.",
"schemas.field.defaultValue": "Valore predefinito",
"schemas.field.defaultValues": "Valori predefiniti",
"schemas.field.defaultValuesHint": "Imposta il valore predefinito per la lingua e sovrascrivere il valore predefinito, se definito. Usalo solo se davvero necessario.",

2
backend/i18n/frontend_nl.json

@ -787,6 +787,8 @@
"schemas.export.recreateFields": "Velden opnieuw maken",
"schemas.export.synchronize": "Synchroniseren",
"schemas.field.allowedValues": "Toegestane waarden",
"schemas.field.createEnum": "Generate GraphQL Enum.",
"schemas.field.createEnumHint": "Check this checkbox to create a GraphQL enumeration for this field.",
"schemas.field.defaultValue": "Standaardwaarde",
"schemas.field.defaultValues": "Standaardwaardes",
"schemas.field.defaultValuesHint": "Stel de standaardwaarde per taal in en overschrijf de standaardwaarde-eigenschap, indien gedefinieerd. Gebruik het alleen als het echt nodig is.",

2
backend/i18n/frontend_zh.json

@ -787,6 +787,8 @@
"schemas.export.recreateFields": "重新创建字段",
"schemas.export.synchronize": "同步",
"schemas.field.allowedValues": "允许的值",
"schemas.field.createEnum": "Generate GraphQL Enum.",
"schemas.field.createEnumHint": "Check this checkbox to create a GraphQL enumeration for this field.",
"schemas.field.defaultValue": "Default Value",
"schemas.field.defaultValues": "默认值",
"schemas.field.defaultValuesHint": "设置每种语言的默认值并覆盖默认值属性(如果已定义)。仅在真正需要时才使用它。",

2
backend/i18n/source/frontend_en.json

@ -787,6 +787,8 @@
"schemas.export.recreateFields": "Recreate fields",
"schemas.export.synchronize": "Synchronize",
"schemas.field.allowedValues": "Allowed Values",
"schemas.field.createEnum": "Generate GraphQL Enum.",
"schemas.field.createEnumHint": "Check this checkbox to create a GraphQL enumeration for this field.",
"schemas.field.defaultValue": "Default Value",
"schemas.field.defaultValues": "Default Values",
"schemas.field.defaultValuesHint": "Set the default value per language and override the default value property, if defined. Only use it if really needed.",

2
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs

@ -39,6 +39,8 @@ namespace Squidex.Domain.Apps.Core.Schemas
public bool InlineEditable { get; init; }
public bool CreateEnum { get; init; }
public StringContentType ContentType { get; init; }
public StringFieldEditor Editor { get; init; }

2
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs

@ -21,6 +21,8 @@ namespace Squidex.Domain.Apps.Core.Schemas
public int? MaxItems { get; init; }
public bool CreateEnum { get; init; }
public TagsFieldEditor Editor { get; init; }
public TagsFieldNormalization Normalization { get; init; }

6
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs

@ -24,7 +24,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
private readonly Dictionary<SchemaInfo, ComponentGraphType> componentTypes = new Dictionary<SchemaInfo, ComponentGraphType>(ReferenceEqualityComparer.Instance);
private readonly Dictionary<SchemaInfo, ContentGraphType> contentTypes = new Dictionary<SchemaInfo, ContentGraphType>(ReferenceEqualityComparer.Instance);
private readonly Dictionary<SchemaInfo, ContentResultGraphType> contentResultTypes = new Dictionary<SchemaInfo, ContentResultGraphType>(ReferenceEqualityComparer.Instance);
private readonly Dictionary<string, EnumerationGraphType> enumTypes = new Dictionary<string, EnumerationGraphType>();
private readonly Dictionary<string, EnumerationGraphType?> enumTypes = new Dictionary<string, EnumerationGraphType?>();
private readonly FieldVisitor fieldVisitor;
private readonly FieldInputVisitor fieldInputVisitor;
private readonly PartitionResolver partitionResolver;
@ -151,9 +151,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
return componentTypes.GetOrDefault(schema);
}
public EnumerationGraphType GetEnumeration<T>(string name, IEnumerable<T> values)
public EnumerationGraphType? GetEnumeration(string name, IEnumerable<string> values)
{
return enumTypes.GetOrAdd(name, x => new FieldEnumType<T>(name, values));
return enumTypes.GetOrAdd(name, x => FieldEnumType.TryCreate(name, values));
}
public IEnumerable<KeyValuePair<SchemaInfo, ContentGraphType>> GetAllContentTypes()

25
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs

@ -6,29 +6,30 @@
// ==========================================================================
using GraphQL.Types;
using Squidex.Text;
using GraphQL.Utilities;
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
{
public sealed class FieldEnumType<T> : EnumerationGraphType
public sealed class FieldEnumType : EnumerationGraphType
{
public FieldEnumType(string name, IEnumerable<T> values)
public FieldEnumType(string name, IEnumerable<string> values)
{
Name = name;
// Avoid conflicts with duplicate names.
var names = new Names();
foreach (var value in values)
{
if (!Equals(value, null))
{
// Get rid of special characters.
var valueName = value.ToString()!.Slugify().ToPascalCase();
AddValue(names[valueName], null, value);
AddValue(value, null, value);
}
}
public static FieldEnumType? TryCreate(string name, IEnumerable<string> values)
{
if (!values.All(x => x.IsValidName(NamedElement.EnumValue)) || !values.Any())
{
return null;
}
return new FieldEnumType(name, values);
}
}
}

29
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs

@ -76,34 +76,41 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
public IGraphType? Visit(IField<NumberFieldProperties> field, FieldInfo args)
{
if (field.Properties?.AllowedValues?.Count > 0)
{
return builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues);
}
return AllTypes.Float;
}
public IGraphType? Visit(IField<StringFieldProperties> field, FieldInfo args)
{
if (field.Properties?.AllowedValues?.Count > 0)
var type = AllTypes.String;
if (field.Properties?.AllowedValues?.Count > 0 && field.Properties.CreateEnum)
{
var @enum = builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues);
if (@enum != null)
{
return builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues);
type = @enum;
}
}
return AllTypes.String;
return type;
}
public IGraphType? Visit(IField<TagsFieldProperties> field, FieldInfo args)
{
if (field.Properties?.AllowedValues?.Count > 0)
var type = AllTypes.Strings;
if (field.Properties?.AllowedValues?.Count > 0 && field.Properties.CreateEnum)
{
var @enum = builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues);
return new ListGraphType(new NonNullGraphType(@enum));
if (@enum != null)
{
type = new ListGraphType(new NonNullGraphType(@enum));
}
}
return AllTypes.Strings;
return type;
}
public IGraphType? Visit(IField<UIFieldProperties> field, FieldInfo args)

23
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs

@ -164,23 +164,21 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
public (IGraphType?, IFieldResolver?, QueryArguments?) Visit(IField<NumberFieldProperties> field, FieldInfo args)
{
var type = AllTypes.Float;
if (field.Properties?.AllowedValues?.Count > 0)
{
type = builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues);
}
return (type, JsonNumber, null);
return (AllTypes.Float, JsonNumber, null);
}
public (IGraphType?, IFieldResolver?, QueryArguments?) Visit(IField<StringFieldProperties> field, FieldInfo args)
{
var type = AllTypes.String;
if (field.Properties?.AllowedValues?.Count > 0)
if (field.Properties?.AllowedValues?.Count > 0 && field.Properties.CreateEnum)
{
var @enum = builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues);
if (@enum != null)
{
type = builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues);
type = @enum;
}
}
return (type, JsonString, null);
@ -190,12 +188,15 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
{
var type = AllTypes.Strings;
if (field.Properties?.AllowedValues?.Count > 0)
if (field.Properties?.AllowedValues?.Count > 0 && field.Properties.CreateEnum)
{
var @enum = builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues);
if (@enum != null)
{
type = new ListGraphType(new NonNullGraphType(@enum));
}
}
return (type, JsonStrings, null);
}

60
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/Names.cs

@ -1,60 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
{
internal sealed class Names
{
// Reserver names that are used for other GraphQL types.
private static readonly HashSet<string> ReservedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Asset",
"AssetResultDto",
"Content",
"Component",
"EntityCreatedResultDto",
"EntitySavedResultDto",
"JsonScalar",
"JsonPrimitive",
"User"
};
private readonly Dictionary<string, int> takenNames = new Dictionary<string, int>();
public string this[string name, bool isEntity = true]
{
get => GetName(name, isEntity);
}
private string GetName(string name, bool isEntity)
{
Guard.NotNullOrEmpty(name);
if (!char.IsLetter(name[0]))
{
name = "gql_" + name;
}
else if (isEntity && ReservedNames.Contains(name))
{
name = $"{name}Entity";
}
// Avoid duplicate names.
if (!takenNames.TryGetValue(name, out var offset))
{
takenNames[name] = 0;
return name;
}
takenNames[name] = ++offset;
// Add + 1 to all offsets for backwards-compatibility.
return $"{name}{offset + 1}";
}
}
}

50
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs

@ -7,6 +7,7 @@
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Text;
#pragma warning disable MA0048 // File name must match type name
@ -154,4 +155,53 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
return new FieldInfo(rootField, typeName, names, parentNames, fieldInfos);
}
}
internal sealed class Names
{
// Reserver names that are used for other GraphQL types.
private static readonly HashSet<string> ReservedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Asset",
"AssetResultDto",
"Content",
"Component",
"EntityCreatedResultDto",
"EntitySavedResultDto",
"JsonScalar",
"JsonPrimitive",
"User"
};
private readonly Dictionary<string, int> takenNames = new Dictionary<string, int>();
public string this[string name, bool isEntity = true]
{
get => GetName(name, isEntity);
}
private string GetName(string name, bool isEntity)
{
Guard.NotNullOrEmpty(name);
if (!char.IsLetter(name[0]))
{
name = "gql_" + name;
}
else if (isEntity && ReservedNames.Contains(name))
{
name = $"{name}Entity";
}
// Avoid duplicate names.
if (!takenNames.TryGetValue(name, out var offset))
{
takenNames[name] = 0;
return name;
}
takenNames[name] = ++offset;
// Add + 1 to all offsets for backwards-compatibility.
return $"{name}{offset + 1}";
}
}
}

15
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Extensions.cs

@ -7,6 +7,7 @@
using GraphQL;
using GraphQL.Types;
using GraphQL.Utilities;
using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
@ -52,6 +53,20 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
}
}
public static bool IsValidName(this string? name, NamedElement type)
{
try
{
NameValidator.ValidateDefault(name!, type);
return true;
}
catch
{
return false;
}
}
internal static FieldType WithSourceName(this FieldType field, string value)
{
return field.WithMetadata(nameof(SourceName), value);

5
backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs

@ -83,6 +83,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
/// </summary>
public bool InlineEditable { get; set; }
/// <summary>
/// Indicates whether GraphQL Enum should be created.
/// </summary>
public bool CreateEnum { get; init; }
/// <summary>
/// How the string content should be interpreted.
/// </summary>

5
backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs

@ -38,6 +38,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
/// </summary>
public ReadonlyList<string>? AllowedValues { get; set; }
/// <summary>
/// Indicates whether GraphQL Enum should be created.
/// </summary>
public bool CreateEnum { get; init; }
/// <summary>
/// The editor that is used to manage this field.
/// </summary>

13
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLMutationTests.cs

@ -739,9 +739,18 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
var data = TestContent.Input(content, TestSchemas.Ref1.Id, TestSchemas.Ref2.Id);
var dataJson = JsonConvert.SerializeObject(data, Formatting.Indented);
var dataString = Regex.Replace(dataJson, "\"([^\"]+)\":", x => x.Groups[1].Value + ":").Replace(".0", string.Empty, StringComparison.Ordinal);
query = query.Replace("<DATA>", dataString, StringComparison.Ordinal);
// Use Properties without quotes.
dataJson = Regex.Replace(dataJson, "\"([^\"]+)\":", x => x.Groups[1].Value + ":");
// Use pure integer numbers.
dataJson = dataJson.Replace(".0", string.Empty, StringComparison.Ordinal);
// Use enum values whithout quotes.
dataJson = dataJson.Replace("\"EnumA\"", "EnumA", StringComparison.Ordinal);
dataJson = dataJson.Replace("\"EnumB\"", "EnumB", StringComparison.Ordinal);
query = query.Replace("<DATA>", dataJson, StringComparison.Ordinal);
}
return query;

44
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestContent.cs

@ -45,6 +45,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
myString {
iv
}
myStringEnum {
iv
}
myLocalizedString {
de_DE
}
@ -88,6 +91,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
myTags {
iv
}
myTagsEnum {
iv
}
myArray {
iv {
nestedNumber
@ -123,6 +129,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
myJson
myJsonValue: myJson(path: ""value"")
myString
myStringEnum
myLocalizedString
myNumber
myBoolean
@ -146,6 +153,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}
myTags
myTagsEnum
myArray {
nestedNumber
nestedBoolean
@ -164,6 +172,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
.AddField("my-string",
new ContentFieldData()
.AddInvariant(null))
.AddField("my-string-enum",
new ContentFieldData()
.AddInvariant("EnumA"))
.AddField("my-assets",
new ContentFieldData()
.AddInvariant(JsonValue.Array(assetId.ToString())))
@ -179,6 +190,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
.AddField("my-tags",
new ContentFieldData()
.AddInvariant(JsonValue.Array("tag1", "tag2")))
.AddField("my-tags-enum",
new ContentFieldData()
.AddInvariant(JsonValue.Array("EnumA", "EnumB")))
.AddField("my-references",
new ContentFieldData()
.AddInvariant(JsonValue.Array(refId.ToString())))
@ -353,6 +367,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
{
iv = (string?)null,
},
["myStringEnum"] = new
{
iv = "EnumA",
},
["myLocalizedString"] = new
{
de_DE = "de-DE"
@ -409,6 +427,14 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
"tag2"
}
},
["myTagsEnum"] = new
{
iv = new[]
{
"EnumA",
"EnumB"
}
},
["myArray"] = new
{
iv = new[]
@ -476,6 +502,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
{
iv = (string?)null,
},
["myStringEnum"] = new
{
iv = "EnumA",
},
["myLocalizedString"] = new
{
de_DE = "de-DE"
@ -558,6 +588,14 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
"tag2"
}
},
["myTagsEnum"] = new
{
iv = new[]
{
"EnumA",
"EnumB"
}
},
["myArray"] = new
{
iv = new[]
@ -589,6 +627,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
},
["myJsonValue"] = 1,
["myString"] = null,
["myStringEnum"] = "EnumA",
["myLocalizedString"] = "de-DE",
["myNumber"] = 1.0,
["myBoolean"] = true,
@ -641,6 +680,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
"tag1",
"tag2"
},
["myTagsEnum"] = new[]
{
"EnumA",
"EnumB"
},
["myArray"] = new[]
{
new

32
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestSchemas.cs

@ -36,6 +36,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
.Publish()
.AddString(1, "schemaRef2Field", Partitioning.Invariant));
var enums = ReadonlyList.Create("EnumA", "EnumB", "EnumC");
Default = Mocks.Schema(TestApp.DefaultId, DefaultId,
new Schema(DefaultId.Name)
.Publish()
@ -43,34 +45,32 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
new JsonFieldProperties())
.AddString(2, "my-string", Partitioning.Invariant,
new StringFieldProperties())
.AddString(3, "my-localized-string", Partitioning.Language,
.AddString(3, "my-string-enum", Partitioning.Invariant,
new StringFieldProperties { AllowedValues = enums, CreateEnum = true })
.AddString(4, "my-localized-string", Partitioning.Language,
new StringFieldProperties())
.AddString(4, "my-string-enum", Partitioning.Invariant,
new StringFieldProperties { AllowedValues = ReadonlyList.Create("A", "B", "C") })
.AddNumber(5, "my-number", Partitioning.Invariant,
new NumberFieldProperties())
.AddNumber(6, "my-number-enum", Partitioning.Invariant,
new NumberFieldProperties { AllowedValues = ReadonlyList.Create(1.0, 2.0, 3.0) })
.AddAssets(7, "my-assets", Partitioning.Invariant,
.AddAssets(6, "my-assets", Partitioning.Invariant,
new AssetsFieldProperties())
.AddBoolean(8, "my-boolean", Partitioning.Invariant,
.AddBoolean(7, "my-boolean", Partitioning.Invariant,
new BooleanFieldProperties())
.AddDateTime(9, "my-datetime", Partitioning.Invariant,
.AddDateTime(8, "my-datetime", Partitioning.Invariant,
new DateTimeFieldProperties())
.AddReferences(10, "my-references", Partitioning.Invariant,
.AddReferences(9, "my-references", Partitioning.Invariant,
new ReferencesFieldProperties { SchemaId = Ref1Id.Id })
.AddReferences(11, "my-union", Partitioning.Invariant,
.AddReferences(10, "my-union", Partitioning.Invariant,
new ReferencesFieldProperties())
.AddGeolocation(12, "my-geolocation", Partitioning.Invariant,
.AddGeolocation(11, "my-geolocation", Partitioning.Invariant,
new GeolocationFieldProperties())
.AddComponent(13, "my-component", Partitioning.Invariant,
.AddComponent(12, "my-component", Partitioning.Invariant,
new ComponentFieldProperties { SchemaId = Ref1Id.Id })
.AddComponents(14, "my-components", Partitioning.Invariant,
.AddComponents(13, "my-components", Partitioning.Invariant,
new ComponentsFieldProperties { SchemaIds = ReadonlyList.Create(Ref1.Id, Ref2.Id) })
.AddTags(15, "my-tags", Partitioning.Invariant,
.AddTags(14, "my-tags", Partitioning.Invariant,
new TagsFieldProperties())
.AddTags(16, "my-tags-enum", Partitioning.Invariant,
new TagsFieldProperties { AllowedValues = ReadonlyList.Create("A", "B", "C") })
.AddTags(15, "my-tags-enum", Partitioning.Invariant,
new TagsFieldProperties { AllowedValues = enums, CreateEnum = true })
.AddArray(100, "my-array", Partitioning.Invariant, f => f
.AddBoolean(121, "nested-boolean",
new BooleanFieldProperties())

15
frontend/src/app/features/schemas/pages/schema/fields/types/string-ui.component.html

@ -33,6 +33,21 @@
</div>
</div>
<div class="form-group row" [class.hidden]="hideAllowedValues | async">
<div class="col-9 offset-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="{{field.fieldId}}_createEnum" formControlName="createEnum">
<label class="form-check-label" for="{{field.fieldId}}_createEnum">
{{ 'schemas.field.createEnum' | sqxTranslate }}
</label>
</div>
<sqx-form-hint>
{{ 'schemas.field.createEnumHint' | sqxTranslate }}
</sqx-form-hint>
</div>
</div>
<div class="form-group row" [class.hidden]="hideInlineEditable | async">
<div class="col-9 offset-3">
<div class="form-check">

17
frontend/src/app/features/schemas/pages/schema/fields/types/tags-ui.component.html

@ -10,6 +10,7 @@
</sqx-form-hint>
</div>
</div>
<div class="form-group row">
<label class="col-3 col-form-label">{{ 'schemas.field.editor' | sqxTranslate }}</label>
@ -23,6 +24,7 @@
</label>
</div>
</div>
<div class="form-group row">
<label class="col-3 col-form-label">{{ 'schemas.field.allowedValues' | sqxTranslate }}</label>
@ -30,4 +32,19 @@
<sqx-tag-editor formControlName="allowedValues"></sqx-tag-editor>
</div>
</div>
<div class="form-group row">
<div class="col-9 offset-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="{{field.fieldId}}_createEnum" formControlName="createEnum">
<label class="form-check-label" for="{{field.fieldId}}_createEnum">
{{ 'schemas.field.createEnum' | sqxTranslate }}
</label>
</div>
<sqx-form-hint>
{{ 'schemas.field.createEnumHint' | sqxTranslate }}
</sqx-form-hint>
</div>
</div>
</div>

2
frontend/src/app/shared/services/schemas.types.ts

@ -429,6 +429,7 @@ export class StringFieldPropertiesDto extends FieldPropertiesDto {
public readonly fieldType = 'String';
public readonly allowedValues?: ReadonlyArray<string>;
public readonly createEnum: boolean = false;
public readonly defaultValue?: string;
public readonly defaultValues?: DefaultValue<string>;
public readonly editor: StringFieldEditor = 'Input';
@ -466,6 +467,7 @@ export class TagsFieldPropertiesDto extends FieldPropertiesDto {
public readonly fieldType = 'Tags';
public readonly allowedValues?: ReadonlyArray<string>;
public readonly createEnum: boolean = false;
public readonly defaultValue?: ReadonlyArray<string>;
public readonly defaultValues?: DefaultValue<ReadonlyArray<string>>;
public readonly editor: TagsFieldEditor = 'Tags';

2
frontend/src/app/shared/state/schemas.forms.ts

@ -326,6 +326,7 @@ export class EditFieldFormVisitor implements FieldPropertiesVisitor<any> {
public visitString() {
this.config['allowedValues'] = new FormControl(undefined);
this.config['contentType'] = new FormControl(undefined);
this.config['createEnum'] = new FormControl(undefined);
this.config['defaultValue'] = new FormControl(undefined);
this.config['defaultValues'] = new FormControl(undefined);
this.config['folderId'] = new FormControl(undefined);
@ -343,6 +344,7 @@ export class EditFieldFormVisitor implements FieldPropertiesVisitor<any> {
public visitTags() {
this.config['allowedValues'] = new FormControl(undefined);
this.config['createEnum'] = new FormControl(undefined);
this.config['defaultValue'] = new FormControl(undefined);
this.config['defaultValues'] = new FormControl(undefined);
this.config['maxItems'] = new FormControl(undefined);

Loading…
Cancel
Save