From 4e0e641002a5efe83e7071eb444ef788fdcf53e1 Mon Sep 17 00:00:00 2001 From: GabrielMeyer Date: Mon, 17 Jun 2019 16:40:23 +0200 Subject: [PATCH] Form validations The system validates the input of the users. In most cases, if a form is invalid, the user has no chance to save his changes. --- .../head-bar/head-bar.component.html | 2 +- .../components/head-bar/head-bar.component.ts | 6 ++++ .../shared/validators/custom-validators.ts | 19 +++++++++++ .../item-info-dialog.component.html | 3 +- .../item-info-dialog.component.ts | 3 +- .../assignment-detail.component.html | 10 ++++-- .../assignment-detail.component.ts | 12 +++---- ...motion-comment-section-list.component.html | 34 ++++++++++--------- .../motion-detail.component.html | 4 ++- .../workflow-detail.component.html | 1 + .../workflow-list.component.html | 4 +-- .../tag-list/tag-list.component.html | 1 + .../topic-detail/topic-detail.component.html | 1 + .../user-detail/user-detail.component.html | 1 + 14 files changed, 70 insertions(+), 31 deletions(-) create mode 100644 client/src/app/shared/validators/custom-validators.ts diff --git a/client/src/app/shared/components/head-bar/head-bar.component.html b/client/src/app/shared/components/head-bar/head-bar.component.html index 724f64388..442df3bb1 100644 --- a/client/src/app/shared/components/head-bar/head-bar.component.html +++ b/client/src/app/shared/components/head-bar/head-bar.component.html @@ -49,7 +49,7 @@ - + diff --git a/client/src/app/shared/components/head-bar/head-bar.component.ts b/client/src/app/shared/components/head-bar/head-bar.component.ts index 4011cb75d..8c0352bde 100644 --- a/client/src/app/shared/components/head-bar/head-bar.component.ts +++ b/client/src/app/shared/components/head-bar/head-bar.component.ts @@ -71,6 +71,12 @@ export class HeadBarComponent { @Input() public editMode = false; + /** + * The save button can manually be disabled. + */ + @Input() + public isSaveButtonEnabled = true; + /** * Determine multiSelect mode: changed interactions and head bar */ diff --git a/client/src/app/shared/validators/custom-validators.ts b/client/src/app/shared/validators/custom-validators.ts new file mode 100644 index 000000000..1bb858a05 --- /dev/null +++ b/client/src/app/shared/validators/custom-validators.ts @@ -0,0 +1,19 @@ +import { ValidatorFn, FormGroup, ValidationErrors } from '@angular/forms'; + +/** + * Constant to validate a `duration` field. + * + * `([0-9]+)` looks for a number with any length to the `:` (optional).\n + * + * `([0-5][0-9]?)?`: The user can optionally enter a number for minutes/seconds (0 - 59) + * + * Afterwards the duration can be specified as hours or minutes (via `[h|m]?` - optional). Defaults to `h`. + * + * @param control The form-control to validate + * + * @returns {ValidationErrors | null} Null, if the input is correct, `ValidationErrors` otherwise. + */ +export const durationValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => { + const regExp = /^\s*([0-9]+)(:)?([0-5][0-9]?)?\s*[h|m]?$/g; + return regExp.test(control.value) || control.value === '' ? null : { valid: false }; +}; diff --git a/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.html b/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.html index b99c789bb..0aee2a67b 100644 --- a/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.html +++ b/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.html @@ -13,6 +13,7 @@ + Your input does not match the following structure 'hh:mm'... @@ -34,6 +35,6 @@
- +
diff --git a/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.ts b/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.ts index 39e410f66..952862279 100644 --- a/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.ts +++ b/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.ts @@ -5,6 +5,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { ViewItem } from '../../models/view-item'; import { ItemVisibilityChoices } from 'app/shared/models/agenda/item'; import { DurationService } from 'app/core/ui-services/duration.service'; +import { durationValidator } from 'app/shared/validators/custom-validators'; /** * Dialog component to change agenda item details @@ -42,7 +43,7 @@ export class ItemInfoDialogComponent { ) { this.agendaInfoForm = this.formBuilder.group({ type: [''], - durationText: [''], + durationText: ['', durationValidator], item_number: [''], comment: [''] }); diff --git a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html index 3b18effee..ebe9b0a34 100644 --- a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html +++ b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html @@ -3,6 +3,7 @@ mainButtonIcon="edit" [nav]="false" [editMode]="editAssignment" + [isSaveButtonEnabled]="assignmentForm.valid" (mainEvent)="setEditMode(!editAssignment)" (saveEvent)="saveAssignment()" > @@ -242,16 +243,16 @@ formControlName="title" [value]="assignmentCopy.title || ''" /> + {{ 'The title is required' | translate }} -

{{ 'Description' | translate }}:

+

{{ 'Description' | translate }}:

@@ -292,8 +293,11 @@ matInput placeholder="{{ 'Number of persons to be elected' | translate }}" formControlName="open_posts" - [value]="assignmentCopy.assignment.open_posts || null" + type="number" + required /> + {{ 'This field is required' | translate }} + {{ 'The number has to be greater than "0" ' | translate }} diff --git a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts index 91bdac37a..62b8cb289 100644 --- a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts +++ b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup } from '@angular/forms'; -import { MatSnackBar } from '@angular/material/snack-bar'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { MatSnackBar } from '@angular/material'; import { Router, ActivatedRoute } from '@angular/router'; import { Title, DomSanitizer, SafeHtml } from '@angular/platform-browser'; @@ -196,10 +196,10 @@ export class AssignmentDetailComponent extends BaseViewComponent implements OnIn phase: null, tags_id: [], attachments_id: [], - title: '', - description: '', - poll_description_default: '', - open_posts: 0, + title: ['', Validators.required], + description: [''], + poll_description_default: [''], + open_posts: [1, [Validators.required, Validators.min(1)]], agenda_create: [''], agenda_parent_id: [], agenda_type: [''] diff --git a/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.html b/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.html index a59978015..0aa69809f 100644 --- a/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.html +++ b/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.html @@ -13,9 +13,9 @@

- + Required - +

@@ -39,7 +39,7 @@ - -