diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs index 49e4d3c63..7566e6864 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs @@ -33,6 +33,8 @@ namespace Squidex.Domain.Apps.Core.Schemas public int? AspectHeight { get; set; } + public bool AllowDuplicates { get; set; } + public ReadOnlyCollection AllowedExtensions { get; set; } public override T Accept(IFieldPropertiesVisitor visitor) diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs index c6af16a90..632e5b9bf 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs @@ -15,6 +15,8 @@ namespace Squidex.Domain.Apps.Core.Schemas public int? MaxItems { get; set; } + public bool AllowDuplicates { get; set; } + public Guid SchemaId { get; set; } public override T Accept(IFieldPropertiesVisitor visitor) diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs index af7e3e698..ae6351a91 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs @@ -55,6 +55,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent yield return new CollectionValidator(field.Properties.IsRequired, field.Properties.MinItems, field.Properties.MaxItems); } + if (!field.Properties.AllowDuplicates) + { + yield return new UniqueValuesValidator(); + } + yield return new AssetsValidator(field.Properties); } @@ -125,6 +130,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent yield return new CollectionValidator(field.Properties.IsRequired, field.Properties.MinItems, field.Properties.MaxItems); } + if (!field.Properties.AllowDuplicates) + { + yield return new UniqueValuesValidator(); + } + if (field.Properties.SchemaId != Guid.Empty) { yield return new ReferencesValidator(field.Properties.SchemaId); diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/AssetsFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/AssetsFieldPropertiesDto.cs index 30a43fd08..9ef6cff0c 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/AssetsFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/AssetsFieldPropertiesDto.cs @@ -73,6 +73,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// public string[] AllowedExtensions { get; set; } + /// + /// True, if duplicate values are allowed. + /// + public bool AllowDuplicates { get; set; } + public override FieldProperties ToProperties() { var result = SimpleMapper.Map(this, new AssetsFieldProperties()); diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs index 07ee52dc5..8e73ed212 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs @@ -23,6 +23,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// public int? MaxItems { get; set; } + /// + /// True, if duplicate values are allowed. + /// + public bool AllowDuplicates { get; set; } + /// /// The id of the referenced schema. /// diff --git a/src/Squidex/app/features/schemas/pages/schema/types/assets-validation.component.html b/src/Squidex/app/features/schemas/pages/schema/types/assets-validation.component.html index 722b4b726..98c89760d 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/assets-validation.component.html +++ b/src/Squidex/app/features/schemas/pages/schema/types/assets-validation.component.html @@ -94,6 +94,17 @@ + +
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
diff --git a/src/Squidex/app/features/schemas/pages/schema/types/references-validation.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/references-validation.component.ts index a7fcc797f..013a5141e 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/references-validation.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/references-validation.component.ts @@ -31,6 +31,9 @@ export class ReferencesValidationComponent implements OnInit { } public ngOnInit() { + this.editForm.setControl('allowDuplicates', + new FormControl(this.properties.allowDuplicates)); + this.editForm.setControl('maxItems', new FormControl(this.properties.maxItems)); diff --git a/src/Squidex/app/shared/services/schemas.types.ts b/src/Squidex/app/shared/services/schemas.types.ts index ba94c6567..1da787806 100644 --- a/src/Squidex/app/shared/services/schemas.types.ts +++ b/src/Squidex/app/shared/services/schemas.types.ts @@ -169,6 +169,7 @@ export class AssetsFieldPropertiesDto extends FieldPropertiesDto { public readonly maxHeight?: number; public readonly aspectWidth?: number; public readonly aspectHeight?: number; + public readonly allowDuplicates?: boolean; public get isSortable() { return false; @@ -296,6 +297,7 @@ export class ReferencesFieldPropertiesDto extends FieldPropertiesDto { public readonly minItems?: number; public readonly maxItems?: number; public readonly schemaId?: string; + public readonly allowDuplicates?: boolean; public get isSortable() { return false; diff --git a/src/Squidex/app/shared/state/contents.forms.spec.ts b/src/Squidex/app/shared/state/contents.forms.spec.ts index 7f7d11b04..bf7424bf0 100644 --- a/src/Squidex/app/shared/state/contents.forms.spec.ts +++ b/src/Squidex/app/shared/state/contents.forms.spec.ts @@ -145,7 +145,7 @@ describe('AssetsField', () => { const field = createField(new AssetsFieldPropertiesDto({ isRequired: true, minItems: 1, maxItems: 5 })); it('should create validators', () => { - expect(FieldValidatorsFactory.createValidators(field, false).length).toBe(2); + expect(FieldValidatorsFactory.createValidators(field, false).length).toBe(3); }); it('should format to empty string if null', () => { @@ -328,7 +328,7 @@ describe('ReferencesField', () => { const field = createField(new ReferencesFieldPropertiesDto({ isRequired: true, minItems: 1, maxItems: 5 })); it('should create validators', () => { - expect(FieldValidatorsFactory.createValidators(field, false).length).toBe(2); + expect(FieldValidatorsFactory.createValidators(field, false).length).toBe(3); }); it('should format to empty string if null', () => { diff --git a/src/Squidex/app/shared/state/contents.forms.ts b/src/Squidex/app/shared/state/contents.forms.ts index 20c07a9bf..f63e51c53 100644 --- a/src/Squidex/app/shared/state/contents.forms.ts +++ b/src/Squidex/app/shared/state/contents.forms.ts @@ -197,6 +197,10 @@ export class FieldValidatorsFactory implements FieldPropertiesVisitor (object)x.ToString()).ToArray());