]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Move validators into forms directory 22644/head
authorStephan Müller <smueller@suse.com>
Fri, 22 Jun 2018 11:35:35 +0000 (13:35 +0200)
committerStephan Müller <smueller@suse.com>
Tue, 3 Jul 2018 15:42:32 +0000 (17:42 +0200)
Now that 'forms' directory exists, the validators are moved to
it. Angular also does this with it's validators ('@angular/forms').

Signed-off-by: Stephan Müller <smueller@suse.com>
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-s3-key-modal/rgw-user-s3-key-modal.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-subuser-modal/rgw-user-subuser-modal.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/validators/cd-validators.spec.ts [deleted file]
src/pybind/mgr/dashboard/frontend/src/app/shared/validators/cd-validators.ts [deleted file]

index bfed5882a32e5fd63fed58ee04713db297e7b764..fb79e8bfe79644809839530bcdc39bece824bb63 100644 (file)
@@ -9,8 +9,8 @@ import { forkJoin as observableForkJoin, Observable } from 'rxjs';
 import { RgwUserService } from '../../../shared/api/rgw-user.service';
 import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
 import { CdFormGroup } from '../../../shared/forms/cd-form-group';
+import { CdValidators, isEmptyInputValue } from '../../../shared/forms/cd-validators';
 import { FormatterService } from '../../../shared/services/formatter.service';
-import { CdValidators, isEmptyInputValue } from '../../../shared/validators/cd-validators';
 import { RgwUserCapability } from '../models/rgw-user-capability';
 import { RgwUserS3Key } from '../models/rgw-user-s3-key';
 import { RgwUserSubuser } from '../models/rgw-user-subuser';
index 7514eada1e5ab3853a2c1f7a6b7abdaeba8a5521..3741581973f024faf357b535d304fc41534fe67d 100644 (file)
@@ -6,7 +6,7 @@ import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
 
 import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
 import { CdFormGroup } from '../../../shared/forms/cd-form-group';
-import { CdValidators } from '../../../shared/validators/cd-validators';
+import { CdValidators } from '../../../shared/forms/cd-validators';
 import { RgwUserS3Key } from '../models/rgw-user-s3-key';
 
 @Component({
index 0da588a02427e2ecee3f14e721714f6968e1a2dc..8f5b427bd78f722866853ef737cea33e01ab1030 100644 (file)
@@ -6,7 +6,7 @@ import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
 
 import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
 import { CdFormGroup } from '../../../shared/forms/cd-form-group';
-import { CdValidators, isEmptyInputValue } from '../../../shared/validators/cd-validators';
+import { CdValidators, isEmptyInputValue } from '../../../shared/forms/cd-validators';
 import { RgwUserSubuser } from '../models/rgw-user-subuser';
 
 @Component({
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.spec.ts
new file mode 100644 (file)
index 0000000..fb68297
--- /dev/null
@@ -0,0 +1,171 @@
+import { FormControl, FormGroup } from '@angular/forms';
+
+import { CdValidators } from './cd-validators';
+
+describe('CdValidators', () => {
+  describe('email', () => {
+    it('should not error on an empty email address', () => {
+      const control = new FormControl('');
+      expect(CdValidators.email(control)).toBeNull();
+    });
+
+    it('should not error on valid email address', () => {
+      const control = new FormControl('dashboard@ceph.com');
+      expect(CdValidators.email(control)).toBeNull();
+    });
+
+    it('should error on invalid email address', () => {
+      const control = new FormControl('xyz');
+      expect(CdValidators.email(control)).toEqual({ email: true });
+    });
+  });
+
+  describe('requiredIf', () => {
+    let form: FormGroup;
+
+    beforeEach(() => {
+      form = new FormGroup({
+        x: new FormControl(true),
+        y: new FormControl('abc'),
+        z: new FormControl('')
+      });
+    });
+
+    it('should not error because all conditions are fulfilled', () => {
+      form.get('z').setValue('zyx');
+      const validatorFn = CdValidators.requiredIf({
+        x: true,
+        y: 'abc'
+      });
+      expect(validatorFn(form.controls['z'])).toBeNull();
+    });
+
+    it('should not error because of unmet prerequisites', () => {
+      // Define prereqs that do not match the current values of the form fields.
+      const validatorFn = CdValidators.requiredIf({
+        x: false,
+        y: 'xyz'
+      });
+      // The validator must succeed because the prereqs do not match, so the
+      // validation of the 'z' control will be skipped.
+      expect(validatorFn(form.controls['z'])).toBeNull();
+    });
+
+    it('should error because of an empty value', () => {
+      // Define prereqs that force the validator to validate the value of
+      // the 'z' control.
+      const validatorFn = CdValidators.requiredIf({
+        x: true,
+        y: 'abc'
+      });
+      // The validator must fail because the value of control 'z' is empty.
+      expect(validatorFn(form.controls['z'])).toEqual({ required: true });
+    });
+
+    it('should not error because of unsuccessful condition', () => {
+      form.get('z').setValue('zyx');
+      // Define prereqs that force the validator to validate the value of
+      // the 'z' control.
+      const validatorFn = CdValidators.requiredIf(
+        {
+          x: true,
+          z: 'zyx'
+        },
+        () => false
+      );
+      expect(validatorFn(form.controls['z'])).toBeNull();
+    });
+
+    it('should error because of successful condition', () => {
+      const conditionFn = (value) => {
+        return value === 'abc';
+      };
+      // Define prereqs that force the validator to validate the value of
+      // the 'y' control.
+      const validatorFn = CdValidators.requiredIf(
+        {
+          x: true,
+          z: ''
+        },
+        conditionFn
+      );
+      expect(validatorFn(form.controls['y'])).toEqual({ required: true });
+    });
+  });
+
+  describe('custom validation', () => {
+    let form: FormGroup;
+
+    beforeEach(() => {
+      form = new FormGroup({
+        x: new FormControl(3, CdValidators.custom('odd', (x) => x % 2 === 1)),
+        y: new FormControl(
+          5,
+          CdValidators.custom('not-dividable-by-x', (y) => {
+            const x = (form && form.get('x').value) || 1;
+            return y % x !== 0;
+          })
+        )
+      });
+    });
+
+    it('should test error and valid condition for odd x', () => {
+      const x = form.get('x');
+      x.updateValueAndValidity();
+      expect(x.hasError('odd')).toBeTruthy();
+      x.setValue(4);
+      expect(x.valid).toBeTruthy();
+    });
+
+    it('should test error and valid condition for y if its dividable by x', () => {
+      const y = form.get('y');
+      y.updateValueAndValidity();
+      expect(y.hasError('not-dividable-by-x')).toBeTruthy();
+      y.setValue(6);
+      y.updateValueAndValidity();
+      expect(y.valid).toBeTruthy();
+    });
+  });
+
+  describe('validate if condition', () => {
+    let form: FormGroup;
+
+    beforeEach(() => {
+      form = new FormGroup({
+        x: new FormControl(3),
+        y: new FormControl(5)
+      });
+      CdValidators.validateIf(form.get('x'), () => ((form && form.get('y').value) || 0) > 10, [
+        CdValidators.custom('min', (x) => x < 7),
+        CdValidators.custom('max', (x) => x > 12)
+      ]);
+    });
+
+    it('should test min error', () => {
+      const x = form.get('x');
+      const y = form.get('y');
+      expect(x.valid).toBeTruthy();
+      y.setValue(11);
+      x.updateValueAndValidity();
+      expect(x.hasError('min')).toBeTruthy();
+    });
+
+    it('should test max error', () => {
+      const x = form.get('x');
+      const y = form.get('y');
+      expect(x.valid).toBeTruthy();
+      y.setValue(11);
+      x.setValue(13);
+      expect(x.hasError('max')).toBeTruthy();
+    });
+
+    it('should test valid number with validation', () => {
+      const x = form.get('x');
+      const y = form.get('y');
+      expect(x.valid).toBeTruthy();
+      y.setValue(11);
+      x.setValue(12);
+      expect(x.valid).toBeTruthy();
+    });
+  });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/forms/cd-validators.ts
new file mode 100644 (file)
index 0000000..875e183
--- /dev/null
@@ -0,0 +1,99 @@
+import { AbstractControl, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
+
+import * as _ from 'lodash';
+
+export function isEmptyInputValue(value: any): boolean {
+  return value == null || value.length === 0;
+}
+
+export class CdValidators {
+  /**
+   * Validator that performs email validation. In contrast to the Angular
+   * email validator an empty email will not be handled as invalid.
+   */
+  static email(control: AbstractControl): ValidationErrors | null {
+    // Exit immediately if value is empty.
+    if (isEmptyInputValue(control.value)) {
+      return null;
+    }
+    return Validators.email(control);
+  }
+
+  /**
+   * Validator that requires controls to fulfill the specified condition if
+   * the specified prerequisites matches. If the prerequisites are fulfilled,
+   * then the given function is executed and if it succeeds, the 'required'
+   * validation error will be returned, otherwise null.
+   * @param {Object} prerequisites An object containing the prerequisites.
+   *   ### Example
+   *   ```typescript
+   *   {
+   *     'generate_key': true,
+   *     'username': 'Max Mustermann'
+   *   }
+   *   ```
+   *   Only if all prerequisites are fulfilled, then the validation of the
+   *   control will be triggered.
+   * @param {Function | undefined} condition The function to be executed when all
+   *   prerequisites are fulfilled. If not set, then the {@link isEmptyInputValue}
+   *   function will be used by default. The control's value is used as function
+   *   argument. The function must return true to set the validation error.
+   * @return {ValidatorFn} Returns the validator function.
+   */
+  static requiredIf(prerequisites: Object, condition?: Function | undefined): ValidatorFn {
+    return (control: AbstractControl): ValidationErrors | null => {
+      // Check if all prerequisites matches.
+      if (
+        !Object.keys(prerequisites).every((key) => {
+          return control.parent && control.parent.get(key).value === prerequisites[key];
+        })
+      ) {
+        return null;
+      }
+      const success = _.isFunction(condition)
+        ? condition.call(condition, control.value)
+        : isEmptyInputValue(control.value);
+      return success ? { required: true } : null;
+    };
+  }
+
+  /**
+   * Custom validation by passing a name for the error and a function as error condition.
+   *
+   * @param {string} error
+   * @param {Function} condition - a truthy return value will trigger the error
+   * @returns {ValidatorFn}
+   */
+  static custom(error: string, condition: Function): ValidatorFn {
+    return (control: AbstractControl): { [key: string]: any } => {
+      const value = condition.call(this, control.value);
+      if (value) {
+        return { [error]: value };
+      }
+      return null;
+    };
+  }
+
+  /**
+   * Validate form control if condition is true with validators.
+   *
+   * @param {AbstractControl} formControl
+   * @param {Function} condition
+   * @param {ValidatorFn[]} validators
+   */
+  static validateIf(
+    formControl: AbstractControl,
+    condition: Function,
+    validators: ValidatorFn[]
+  ) {
+    formControl.setValidators((control: AbstractControl): {
+      [key: string]: any;
+    } => {
+      const value = condition.call(this);
+      if (value) {
+        return Validators.compose(validators)(control);
+      }
+      return null;
+    });
+  }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/validators/cd-validators.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/validators/cd-validators.spec.ts
deleted file mode 100644 (file)
index fb68297..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-import { FormControl, FormGroup } from '@angular/forms';
-
-import { CdValidators } from './cd-validators';
-
-describe('CdValidators', () => {
-  describe('email', () => {
-    it('should not error on an empty email address', () => {
-      const control = new FormControl('');
-      expect(CdValidators.email(control)).toBeNull();
-    });
-
-    it('should not error on valid email address', () => {
-      const control = new FormControl('dashboard@ceph.com');
-      expect(CdValidators.email(control)).toBeNull();
-    });
-
-    it('should error on invalid email address', () => {
-      const control = new FormControl('xyz');
-      expect(CdValidators.email(control)).toEqual({ email: true });
-    });
-  });
-
-  describe('requiredIf', () => {
-    let form: FormGroup;
-
-    beforeEach(() => {
-      form = new FormGroup({
-        x: new FormControl(true),
-        y: new FormControl('abc'),
-        z: new FormControl('')
-      });
-    });
-
-    it('should not error because all conditions are fulfilled', () => {
-      form.get('z').setValue('zyx');
-      const validatorFn = CdValidators.requiredIf({
-        x: true,
-        y: 'abc'
-      });
-      expect(validatorFn(form.controls['z'])).toBeNull();
-    });
-
-    it('should not error because of unmet prerequisites', () => {
-      // Define prereqs that do not match the current values of the form fields.
-      const validatorFn = CdValidators.requiredIf({
-        x: false,
-        y: 'xyz'
-      });
-      // The validator must succeed because the prereqs do not match, so the
-      // validation of the 'z' control will be skipped.
-      expect(validatorFn(form.controls['z'])).toBeNull();
-    });
-
-    it('should error because of an empty value', () => {
-      // Define prereqs that force the validator to validate the value of
-      // the 'z' control.
-      const validatorFn = CdValidators.requiredIf({
-        x: true,
-        y: 'abc'
-      });
-      // The validator must fail because the value of control 'z' is empty.
-      expect(validatorFn(form.controls['z'])).toEqual({ required: true });
-    });
-
-    it('should not error because of unsuccessful condition', () => {
-      form.get('z').setValue('zyx');
-      // Define prereqs that force the validator to validate the value of
-      // the 'z' control.
-      const validatorFn = CdValidators.requiredIf(
-        {
-          x: true,
-          z: 'zyx'
-        },
-        () => false
-      );
-      expect(validatorFn(form.controls['z'])).toBeNull();
-    });
-
-    it('should error because of successful condition', () => {
-      const conditionFn = (value) => {
-        return value === 'abc';
-      };
-      // Define prereqs that force the validator to validate the value of
-      // the 'y' control.
-      const validatorFn = CdValidators.requiredIf(
-        {
-          x: true,
-          z: ''
-        },
-        conditionFn
-      );
-      expect(validatorFn(form.controls['y'])).toEqual({ required: true });
-    });
-  });
-
-  describe('custom validation', () => {
-    let form: FormGroup;
-
-    beforeEach(() => {
-      form = new FormGroup({
-        x: new FormControl(3, CdValidators.custom('odd', (x) => x % 2 === 1)),
-        y: new FormControl(
-          5,
-          CdValidators.custom('not-dividable-by-x', (y) => {
-            const x = (form && form.get('x').value) || 1;
-            return y % x !== 0;
-          })
-        )
-      });
-    });
-
-    it('should test error and valid condition for odd x', () => {
-      const x = form.get('x');
-      x.updateValueAndValidity();
-      expect(x.hasError('odd')).toBeTruthy();
-      x.setValue(4);
-      expect(x.valid).toBeTruthy();
-    });
-
-    it('should test error and valid condition for y if its dividable by x', () => {
-      const y = form.get('y');
-      y.updateValueAndValidity();
-      expect(y.hasError('not-dividable-by-x')).toBeTruthy();
-      y.setValue(6);
-      y.updateValueAndValidity();
-      expect(y.valid).toBeTruthy();
-    });
-  });
-
-  describe('validate if condition', () => {
-    let form: FormGroup;
-
-    beforeEach(() => {
-      form = new FormGroup({
-        x: new FormControl(3),
-        y: new FormControl(5)
-      });
-      CdValidators.validateIf(form.get('x'), () => ((form && form.get('y').value) || 0) > 10, [
-        CdValidators.custom('min', (x) => x < 7),
-        CdValidators.custom('max', (x) => x > 12)
-      ]);
-    });
-
-    it('should test min error', () => {
-      const x = form.get('x');
-      const y = form.get('y');
-      expect(x.valid).toBeTruthy();
-      y.setValue(11);
-      x.updateValueAndValidity();
-      expect(x.hasError('min')).toBeTruthy();
-    });
-
-    it('should test max error', () => {
-      const x = form.get('x');
-      const y = form.get('y');
-      expect(x.valid).toBeTruthy();
-      y.setValue(11);
-      x.setValue(13);
-      expect(x.hasError('max')).toBeTruthy();
-    });
-
-    it('should test valid number with validation', () => {
-      const x = form.get('x');
-      const y = form.get('y');
-      expect(x.valid).toBeTruthy();
-      y.setValue(11);
-      x.setValue(12);
-      expect(x.valid).toBeTruthy();
-    });
-  });
-});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/validators/cd-validators.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/validators/cd-validators.ts
deleted file mode 100644 (file)
index 875e183..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-import { AbstractControl, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
-
-import * as _ from 'lodash';
-
-export function isEmptyInputValue(value: any): boolean {
-  return value == null || value.length === 0;
-}
-
-export class CdValidators {
-  /**
-   * Validator that performs email validation. In contrast to the Angular
-   * email validator an empty email will not be handled as invalid.
-   */
-  static email(control: AbstractControl): ValidationErrors | null {
-    // Exit immediately if value is empty.
-    if (isEmptyInputValue(control.value)) {
-      return null;
-    }
-    return Validators.email(control);
-  }
-
-  /**
-   * Validator that requires controls to fulfill the specified condition if
-   * the specified prerequisites matches. If the prerequisites are fulfilled,
-   * then the given function is executed and if it succeeds, the 'required'
-   * validation error will be returned, otherwise null.
-   * @param {Object} prerequisites An object containing the prerequisites.
-   *   ### Example
-   *   ```typescript
-   *   {
-   *     'generate_key': true,
-   *     'username': 'Max Mustermann'
-   *   }
-   *   ```
-   *   Only if all prerequisites are fulfilled, then the validation of the
-   *   control will be triggered.
-   * @param {Function | undefined} condition The function to be executed when all
-   *   prerequisites are fulfilled. If not set, then the {@link isEmptyInputValue}
-   *   function will be used by default. The control's value is used as function
-   *   argument. The function must return true to set the validation error.
-   * @return {ValidatorFn} Returns the validator function.
-   */
-  static requiredIf(prerequisites: Object, condition?: Function | undefined): ValidatorFn {
-    return (control: AbstractControl): ValidationErrors | null => {
-      // Check if all prerequisites matches.
-      if (
-        !Object.keys(prerequisites).every((key) => {
-          return control.parent && control.parent.get(key).value === prerequisites[key];
-        })
-      ) {
-        return null;
-      }
-      const success = _.isFunction(condition)
-        ? condition.call(condition, control.value)
-        : isEmptyInputValue(control.value);
-      return success ? { required: true } : null;
-    };
-  }
-
-  /**
-   * Custom validation by passing a name for the error and a function as error condition.
-   *
-   * @param {string} error
-   * @param {Function} condition - a truthy return value will trigger the error
-   * @returns {ValidatorFn}
-   */
-  static custom(error: string, condition: Function): ValidatorFn {
-    return (control: AbstractControl): { [key: string]: any } => {
-      const value = condition.call(this, control.value);
-      if (value) {
-        return { [error]: value };
-      }
-      return null;
-    };
-  }
-
-  /**
-   * Validate form control if condition is true with validators.
-   *
-   * @param {AbstractControl} formControl
-   * @param {Function} condition
-   * @param {ValidatorFn[]} validators
-   */
-  static validateIf(
-    formControl: AbstractControl,
-    condition: Function,
-    validators: ValidatorFn[]
-  ) {
-    formControl.setValidators((control: AbstractControl): {
-      [key: string]: any;
-    } => {
-      const value = condition.call(this);
-      if (value) {
-        return Validators.compose(validators)(control);
-      }
-      return null;
-    });
-  }
-}