From: Stephan Müller Date: Fri, 15 Nov 2019 12:27:52 +0000 (+0100) Subject: mgr/dashboard: Add binary min and max validators X-Git-Tag: v15.1.0~488^2~2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=cb638998470afc2c7727aaca1e0e3ead6cdb9f16;p=ceph-ci.git mgr/dashboard: Add binary min and max validators Adds simple validators that resemble the min and max validators for numbers. As a binary size (the string) has first be converted into bytes (the number) to validate against some other number and in case of an error the other number want's to be converted into a size to display, the whole process needs a bunch of conversion, but these validators take care of all that. Fixes: https://tracker.ceph.com/issues/38287 Signed-off-by: Stephan Müller --- 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 index d6b2b004546..06a3a230b6d 100644 --- 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 @@ -526,4 +526,33 @@ describe('CdValidators', () => { expect(validatorFn(form.get('z'))).toEqual({ required: true }); }); }); + + describe('dimmlessBinary validators', () => { + const i18nMock = (a: string, b: { value: string }) => a.replace('{{value}}', b.value); + + beforeEach(() => { + form = new CdFormGroup({ + x: new FormControl('2 KiB', [CdValidators.binaryMin(1024), CdValidators.binaryMax(3072)]) + }); + formHelper = new FormHelper(form); + }); + + it('should not raise exception an exception for valid change', () => { + formHelper.expectValidChange('x', '2.5 KiB'); + }); + + it('should not raise minimum error', () => { + formHelper.expectErrorChange('x', '0.5 KiB', 'binaryMin'); + expect(form.get('x').getError('binaryMin')(i18nMock)).toBe( + 'Size has to be at least 1 KiB or more' + ); + }); + + it('should not raise maximum error', () => { + formHelper.expectErrorChange('x', '4 KiB', 'binaryMax'); + expect(form.get('x').getError('binaryMax')(i18nMock)).toBe( + 'Size has to be at most 3 KiB or less' + ); + }); + }); }); 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 index 9a83753e942..11533f7d60a 100644 --- 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 @@ -6,10 +6,14 @@ import { Validators } from '@angular/forms'; +import { I18n } from '@ngx-translate/i18n-polyfill'; import * as _ from 'lodash'; import { Observable, of as observableOf, timer as observableTimer } from 'rxjs'; import { map, switchMapTo, take } from 'rxjs/operators'; +import { DimlessBinaryPipe } from '../pipes/dimless-binary.pipe'; +import { FormatterService } from '../services/formatter.service'; + export function isEmptyInputValue(value: any): boolean { return value == null || value.length === 0; } @@ -321,4 +325,44 @@ export class CdValidators { return { invalidUuid: 'This is not a valid UUID' }; }; } + + /** + * A simple minimum validator vor cd-binary inputs. + * + * To use the validation message pass I18n into the function as it cannot + * be called in a static one. + */ + static binaryMin(bytes: number): ValidatorFn { + return (control: AbstractControl): { [key: string]: (i18n: I18n) => string } | null => { + const formatterService = new FormatterService(); + const currentBytes = new FormatterService().toBytes(control.value); + if (bytes <= currentBytes) { + return null; + } + const value = new DimlessBinaryPipe(formatterService).transform(bytes); + return { + binaryMin: (i18n: I18n) => i18n(`Size has to be at least {{value}} or more`, { value }) + }; + }; + } + + /** + * A simple maximum validator vor cd-binary inputs. + * + * To use the validation message pass I18n into the function as it cannot + * be called in a static one. + */ + static binaryMax(bytes: number): ValidatorFn { + return (control: AbstractControl): { [key: string]: (i18n: I18n) => string } | null => { + const formatterService = new FormatterService(); + const currentBytes = formatterService.toBytes(control.value); + if (bytes >= currentBytes) { + return null; + } + const value = new DimlessBinaryPipe(formatterService).transform(bytes); + return { + binaryMax: (i18n: I18n) => i18n(`Size has to be at most {{value}} or less`, { value }) + }; + }; + } }