Browse Source

Validation fixed for array control.

pull/428/head
Sebastian Stehle 6 years ago
parent
commit
70353d199b
  1. 1
      src/Squidex/app/features/schemas/declarations.ts
  2. 2
      src/Squidex/app/features/schemas/module.ts
  3. 3
      src/Squidex/app/features/schemas/pages/schema/forms/field-form-validation.component.ts
  4. 2
      src/Squidex/app/features/schemas/pages/schema/forms/field-form.component.ts
  5. 25
      src/Squidex/app/features/schemas/pages/schema/types/array-validation.component.html
  6. 16
      src/Squidex/app/features/schemas/pages/schema/types/array-validation.component.scss
  7. 44
      src/Squidex/app/features/schemas/pages/schema/types/array-validation.component.ts
  8. 2
      src/Squidex/app/features/schemas/pages/schema/types/assets-ui.component.html
  9. 2
      src/Squidex/app/features/schemas/pages/schema/types/geolocation-validation.component.html
  10. 2
      src/Squidex/app/features/schemas/pages/schema/types/json-validation.component.html
  11. 148
      src/Squidex/app/shared/state/contents.forms.ts

1
src/Squidex/app/features/schemas/declarations.ts

@ -5,6 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/ */
export * from './pages/schema/types/array-validation.component';
export * from './pages/schema/types/assets-ui.component'; export * from './pages/schema/types/assets-ui.component';
export * from './pages/schema/types/assets-validation.component'; export * from './pages/schema/types/assets-validation.component';
export * from './pages/schema/types/boolean-ui.component'; export * from './pages/schema/types/boolean-ui.component';

2
src/Squidex/app/features/schemas/module.ts

@ -16,6 +16,7 @@ import {
} from '@app/shared'; } from '@app/shared';
import { import {
ArrayValidationComponent,
AssetsUIComponent, AssetsUIComponent,
AssetsValidationComponent, AssetsValidationComponent,
BooleanUIComponent, BooleanUIComponent,
@ -81,6 +82,7 @@ const routes: Routes = [
SchemaMustExistGuard SchemaMustExistGuard
], ],
declarations: [ declarations: [
ArrayValidationComponent,
AssetsUIComponent, AssetsUIComponent,
AssetsValidationComponent, AssetsValidationComponent,
BooleanUIComponent, BooleanUIComponent,

3
src/Squidex/app/features/schemas/pages/schema/forms/field-form-validation.component.ts

@ -14,6 +14,9 @@ import { FieldDto, PatternDto } from '@app/shared';
selector: 'sqx-field-form-validation', selector: 'sqx-field-form-validation',
template: ` template: `
<ng-container [ngSwitch]="field.rawProperties.fieldType"> <ng-container [ngSwitch]="field.rawProperties.fieldType">
<ng-container *ngSwitchCase="'Array'">
<sqx-array-validation [editForm]="editForm" [field]="field" [properties]="field.rawProperties"></sqx-array-validation>
</ng-container>
<ng-container *ngSwitchCase="'Assets'"> <ng-container *ngSwitchCase="'Assets'">
<sqx-assets-validation [editForm]="editForm" [field]="field" [properties]="field.rawProperties"></sqx-assets-validation> <sqx-assets-validation [editForm]="editForm" [field]="field" [properties]="field.rawProperties"></sqx-assets-validation>
</ng-container> </ng-container>

2
src/Squidex/app/features/schemas/pages/schema/forms/field-form.component.ts

@ -21,7 +21,7 @@ import { FieldDto, PatternDto } from '@app/shared';
<li class="nav-item" [class.hidden]="!field.properties.isContentField"> <li class="nav-item" [class.hidden]="!field.properties.isContentField">
<a class="nav-link" (click)="selectTab(1)" [class.active]="selectedTab === 1">Validation</a> <a class="nav-link" (click)="selectTab(1)" [class.active]="selectedTab === 1">Validation</a>
</li> </li>
<li class="nav-item" [class.hidden]="!field.properties.isContentField"> <li class="nav-item" [class.hidden]="!field.properties.isContentField || field.properties.fieldType === 'Array'">
<a class="nav-link" (click)="selectTab(2)" [class.active]="selectedTab === 2">Editing</a> <a class="nav-link" (click)="selectTab(2)" [class.active]="selectedTab === 2">Editing</a>
</li> </li>
</ul> </ul>

25
src/Squidex/app/features/schemas/pages/schema/types/array-validation.component.html

@ -0,0 +1,25 @@
<div [formGroup]="editForm">
<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}}_fieldRequired" formControlName="isRequired" />
<label class="form-check-label" for="{{field.fieldId}}_fieldRequired">
Required
</label>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-3 col-form-label">Items</label>
<div class="col-3 minmax-col">
<input type="number" class="form-control" formControlName="minItems" placeholder="Min Items" />
<label class="col-form-label minmax-label">-</label>
</div>
<div class="col-3">
<input type="number" class="form-control" formControlName="maxItems" placeholder="Max Items" />
</div>
</div>
</div>

16
src/Squidex/app/features/schemas/pages/schema/types/array-validation.component.scss

@ -0,0 +1,16 @@
@import '_vars';
@import '_mixins';
.minmax {
&-col {
position: relative;
}
&-label {
@include absolute(0, -.2rem, auto, auto);
}
}
.form-group {
margin-top: .5rem;
}

44
src/Squidex/app/features/schemas/pages/schema/types/array-validation.component.ts

@ -0,0 +1,44 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { Component, Input, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import {
ArrayFieldPropertiesDto,
FieldDto,
SchemaTagConverter
} from '@app/shared';
@Component({
selector: 'sqx-array-validation',
styleUrls: ['array-validation.component.scss'],
templateUrl: 'array-validation.component.html'
})
export class ArrayValidationComponent implements OnInit {
@Input()
public editForm: FormGroup;
@Input()
public field: FieldDto;
@Input()
public properties: ArrayFieldPropertiesDto;
constructor(
public readonly schemasSource: SchemaTagConverter
) {
}
public ngOnInit() {
this.editForm.setControl('maxItems',
new FormControl(this.properties.maxItems));
this.editForm.setControl('minItems',
new FormControl(this.properties.minItems));
}
}

2
src/Squidex/app/features/schemas/pages/schema/types/assets-ui.component.html

@ -1,6 +1,6 @@
<div [formGroup]="editForm"> <div [formGroup]="editForm">
<div class="form-group row" *ngIf="field.properties.isContentField"> <div class="form-group row">
<div class="col-9 offset-3"> <div class="col-9 offset-3">
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="{{field.fieldId}}_fieldResolveImage" formControlName="resolveImage" /> <input class="form-check-input" type="checkbox" id="{{field.fieldId}}_fieldResolveImage" formControlName="resolveImage" />

2
src/Squidex/app/features/schemas/pages/schema/types/geolocation-validation.component.html

@ -1,6 +1,6 @@
<div [formGroup]="editForm"> <div [formGroup]="editForm">
<div class="form-group row"> <div class="form-group row">
<div class="col-9"> <div class="col-9 offset-3">
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="{{field.fieldId}}_fieldRequired" formControlName="isRequired" /> <input class="form-check-input" type="checkbox" id="{{field.fieldId}}_fieldRequired" formControlName="isRequired" />
<label class="form-check-label" for="{{field.fieldId}}_fieldRequired"> <label class="form-check-label" for="{{field.fieldId}}_fieldRequired">

2
src/Squidex/app/features/schemas/pages/schema/types/json-validation.component.html

@ -1,6 +1,6 @@
<div [formGroup]="editForm"> <div [formGroup]="editForm">
<div class="form-group row"> <div class="form-group row">
<div class="col-9"> <div class="col-9 offset-3">
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="{{field.fieldId}}_fieldRequired" formControlName="isRequired" /> <input class="form-check-input" type="checkbox" id="{{field.fieldId}}_fieldRequired" formControlName="isRequired" />
<label class="form-check-label" for="{{field.fieldId}}_fieldRequired"> <label class="form-check-label" for="{{field.fieldId}}_fieldRequired">

148
src/Squidex/app/shared/state/contents.forms.ts

@ -137,20 +137,6 @@ export class FieldFormatter implements FieldPropertiesVisitor<FieldValue> {
return field.properties.accept(new FieldFormatter(value, allowHtml)); return field.properties.accept(new FieldFormatter(value, allowHtml));
} }
public visitDateTime(properties: DateTimeFieldPropertiesDto): FieldValue {
try {
const parsed = DateTime.parseISO_UTC(this.value);
if (properties.editor === 'Date') {
return parsed.toUTCStringFormat('YYYY-MM-DD');
} else {
return parsed.toUTCStringFormat('YYYY-MM-DD HH:mm:ss');
}
} catch (ex) {
return this.value;
}
}
public visitArray(_: ArrayFieldPropertiesDto): string { public visitArray(_: ArrayFieldPropertiesDto): string {
if (this.value.length) { if (this.value.length) {
return `${this.value.length} Item(s)`; return `${this.value.length} Item(s)`;
@ -167,24 +153,22 @@ export class FieldFormatter implements FieldPropertiesVisitor<FieldValue> {
} }
} }
public visitReferences(_: ReferencesFieldPropertiesDto): string { public visitBoolean(_: BooleanFieldPropertiesDto): string {
if (this.value.length) { return this.value ? 'Yes' : 'No';
return `${this.value.length} Reference(s)`;
} else {
return '0 References';
}
} }
public visitTags(_: TagsFieldPropertiesDto): string { public visitDateTime(properties: DateTimeFieldPropertiesDto): FieldValue {
if (this.value.length) { try {
return this.value.join(', '); const parsed = DateTime.parseISO_UTC(this.value);
} else {
return '';
}
}
public visitBoolean(_: BooleanFieldPropertiesDto): string { if (properties.editor === 'Date') {
return this.value ? 'Yes' : 'No'; return parsed.toUTCStringFormat('YYYY-MM-DD');
} else {
return parsed.toUTCStringFormat('YYYY-MM-DD HH:mm:ss');
}
} catch (ex) {
return this.value;
}
} }
public visitGeolocation(_: GeolocationFieldPropertiesDto): string { public visitGeolocation(_: GeolocationFieldPropertiesDto): string {
@ -212,10 +196,26 @@ export class FieldFormatter implements FieldPropertiesVisitor<FieldValue> {
return `${this.value}`; return `${this.value}`;
} }
public visitReferences(_: ReferencesFieldPropertiesDto): string {
if (this.value.length) {
return `${this.value.length} Reference(s)`;
} else {
return '0 References';
}
}
public visitString(_: StringFieldPropertiesDto): any { public visitString(_: StringFieldPropertiesDto): any {
return this.value; return this.value;
} }
public visitTags(_: TagsFieldPropertiesDto): string {
if (this.value.length) {
return this.value.join(', ');
} else {
return '';
}
}
public visitUI(_: UIFieldPropertiesDto): any { public visitUI(_: UIFieldPropertiesDto): any {
return ''; return '';
} }
@ -237,35 +237,49 @@ export class FieldsValidators implements FieldPropertiesVisitor<ReadonlyArray<Va
return validators; return validators;
} }
public visitNumber(properties: NumberFieldPropertiesDto): ReadonlyArray<ValidatorFn> { public visitArray(properties: ArrayFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
const validators: ValidatorFn[] = [ const validators: ValidatorFn[] = [
ValidatorsEx.between(properties.minValue, properties.maxValue) ValidatorsEx.betweenLength(properties.minItems, properties.maxItems)
]; ];
if (properties.allowedValues && properties.allowedValues.length > 0) { return validators;
const values: ReadonlyArray<(number | null)> = properties.allowedValues; }
if (properties.isRequired && !this.isOptional) { public visitAssets(properties: AssetsFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
validators.push(ValidatorsEx.validValues(values)); const validators: ValidatorFn[] = [
} else { ValidatorsEx.betweenLength(properties.minItems, properties.maxItems)
validators.push(ValidatorsEx.validValues(values.concat([null]))); ];
}
if (!properties.allowDuplicates) {
validators.push(ValidatorsEx.uniqueStrings());
} }
return validators; return validators;
} }
public visitString(properties: StringFieldPropertiesDto): ReadonlyArray<ValidatorFn> { public visitBoolean(_: BooleanFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
return [];
}
public visitDateTime(_: DateTimeFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
return [];
}
public visitGeolocation(_: GeolocationFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
return [];
}
public visitJson(_: JsonFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
return [];
}
public visitNumber(properties: NumberFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
const validators: ValidatorFn[] = [ const validators: ValidatorFn[] = [
ValidatorsEx.betweenLength(properties.minLength, properties.maxLength) ValidatorsEx.between(properties.minValue, properties.maxValue)
]; ];
if (properties.pattern && properties.pattern.length > 0) {
validators.push(ValidatorsEx.pattern(properties.pattern, properties.patternMessage));
}
if (properties.allowedValues && properties.allowedValues.length > 0) { if (properties.allowedValues && properties.allowedValues.length > 0) {
const values: ReadonlyArray<string | null> = properties.allowedValues; const values: ReadonlyArray<(number | null)> = properties.allowedValues;
if (properties.isRequired && !this.isOptional) { if (properties.isRequired && !this.isOptional) {
validators.push(ValidatorsEx.validValues(values)); validators.push(ValidatorsEx.validValues(values));
@ -277,15 +291,7 @@ export class FieldsValidators implements FieldPropertiesVisitor<ReadonlyArray<Va
return validators; return validators;
} }
public visitArray(properties: ArrayFieldPropertiesDto): ReadonlyArray<ValidatorFn> { public visitReferences(properties: ReferencesFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
const validators: ValidatorFn[] = [
ValidatorsEx.betweenLength(properties.minItems, properties.maxItems)
];
return validators;
}
public visitAssets(properties: AssetsFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
const validators: ValidatorFn[] = [ const validators: ValidatorFn[] = [
ValidatorsEx.betweenLength(properties.minItems, properties.maxItems) ValidatorsEx.betweenLength(properties.minItems, properties.maxItems)
]; ];
@ -297,13 +303,23 @@ export class FieldsValidators implements FieldPropertiesVisitor<ReadonlyArray<Va
return validators; return validators;
} }
public visitReferences(properties: ReferencesFieldPropertiesDto): ReadonlyArray<ValidatorFn> { public visitString(properties: StringFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
const validators: ValidatorFn[] = [ const validators: ValidatorFn[] = [
ValidatorsEx.betweenLength(properties.minItems, properties.maxItems) ValidatorsEx.betweenLength(properties.minLength, properties.maxLength)
]; ];
if (!properties.allowDuplicates) { if (properties.pattern && properties.pattern.length > 0) {
validators.push(ValidatorsEx.uniqueStrings()); validators.push(ValidatorsEx.pattern(properties.pattern, properties.patternMessage));
}
if (properties.allowedValues && properties.allowedValues.length > 0) {
const values: ReadonlyArray<string | null> = properties.allowedValues;
if (properties.isRequired && !this.isOptional) {
validators.push(ValidatorsEx.validValues(values));
} else {
validators.push(ValidatorsEx.validValues(values.concat([null])));
}
} }
return validators; return validators;
@ -323,22 +339,6 @@ export class FieldsValidators implements FieldPropertiesVisitor<ReadonlyArray<Va
return validators; return validators;
} }
public visitBoolean(_: BooleanFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
return [];
}
public visitDateTime(_: DateTimeFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
return [];
}
public visitGeolocation(_: GeolocationFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
return [];
}
public visitJson(_: JsonFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
return [];
}
public visitUI(_: UIFieldPropertiesDto): ReadonlyArray<ValidatorFn> { public visitUI(_: UIFieldPropertiesDto): ReadonlyArray<ValidatorFn> {
return []; return [];
} }

Loading…
Cancel
Save