From 91de60fd160d4c831c2743042eda21ad9ce039db Mon Sep 17 00:00:00 2001 From: Tatjana Dehler Date: Thu, 29 Nov 2018 15:51:34 +0100 Subject: [PATCH] mgr/dashboard: move config option types to their own class Move the config option types information into their own class to reuse them easily in other components. Signed-off-by: Tatjana Dehler --- .../configuration-form.component.spec.ts | 118 ---------- .../configuration-form.component.ts | 129 +---------- .../configuration-form.types.spec.ts | 215 ++++++++++++++++++ .../configuration-form.types.ts | 120 ++++++++++ .../frontend/src/locale/messages.xlf | 106 --------- 5 files changed, 346 insertions(+), 342 deletions(-) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.types.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.types.ts diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.spec.ts index d411d6724d2..a80f9bd85a3 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.spec.ts @@ -41,124 +41,6 @@ describe('ConfigurationFormComponent', () => { expect(component).toBeTruthy(); }); - describe('getType', () => { - it('should return uint type', () => { - const ret = component.getType('uint'); - expect(ret).toBeTruthy(); - expect(ret.name).toBe('uint'); - expect(ret.inputType).toBe('number'); - expect(ret.humanReadable).toBe('Positive integer value'); - expect(ret.defaultMin).toBe(0); - expect(ret.patternHelpText).toBe('The entered value needs to be a positive number.'); - expect(ret.isNumberType).toBe(true); - expect(ret.allowsNegative).toBe(false); - }); - - it('should return int type', () => { - const ret = component.getType('int'); - expect(ret).toBeTruthy(); - expect(ret.name).toBe('int'); - expect(ret.inputType).toBe('number'); - expect(ret.humanReadable).toBe('Integer value'); - expect(ret.defaultMin).toBeUndefined(); - expect(ret.patternHelpText).toBe('The entered value needs to be a number.'); - expect(ret.isNumberType).toBe(true); - expect(ret.allowsNegative).toBe(true); - }); - - it('should return size type', () => { - const ret = component.getType('size'); - expect(ret).toBeTruthy(); - expect(ret.name).toBe('size'); - expect(ret.inputType).toBe('number'); - expect(ret.humanReadable).toBe('Positive integer value (size)'); - expect(ret.defaultMin).toBe(0); - expect(ret.patternHelpText).toBe('The entered value needs to be a positive number.'); - expect(ret.isNumberType).toBe(true); - expect(ret.allowsNegative).toBe(false); - }); - - it('should return secs type', () => { - const ret = component.getType('secs'); - expect(ret).toBeTruthy(); - expect(ret.name).toBe('secs'); - expect(ret.inputType).toBe('number'); - expect(ret.humanReadable).toBe('Positive integer value (secs)'); - expect(ret.defaultMin).toBe(1); - expect(ret.patternHelpText).toBe('The entered value needs to be a positive number.'); - expect(ret.isNumberType).toBe(true); - expect(ret.allowsNegative).toBe(false); - }); - - it('should return float type', () => { - const ret = component.getType('float'); - expect(ret).toBeTruthy(); - expect(ret.name).toBe('float'); - expect(ret.inputType).toBe('number'); - expect(ret.humanReadable).toBe('Decimal value'); - expect(ret.defaultMin).toBeUndefined(); - expect(ret.patternHelpText).toBe('The entered value needs to be a number or decimal.'); - expect(ret.isNumberType).toBe(true); - expect(ret.allowsNegative).toBe(true); - }); - - it('should return str type', () => { - const ret = component.getType('str'); - expect(ret).toBeTruthy(); - expect(ret.name).toBe('str'); - expect(ret.inputType).toBe('text'); - expect(ret.humanReadable).toBe('Text'); - expect(ret.defaultMin).toBeUndefined(); - expect(ret.patternHelpText).toBeUndefined(); - expect(ret.isNumberType).toBe(false); - expect(ret.allowsNegative).toBeUndefined(); - }); - - it('should return addr type', () => { - const ret = component.getType('addr'); - expect(ret).toBeTruthy(); - expect(ret.name).toBe('addr'); - expect(ret.inputType).toBe('text'); - expect(ret.humanReadable).toBe('IPv4 or IPv6 address'); - expect(ret.defaultMin).toBeUndefined(); - expect(ret.patternHelpText).toBe('The entered value needs to be a valid IP address.'); - expect(ret.isNumberType).toBe(false); - expect(ret.allowsNegative).toBeUndefined(); - }); - - it('should return uuid type', () => { - const ret = component.getType('uuid'); - expect(ret).toBeTruthy(); - expect(ret.name).toBe('uuid'); - expect(ret.inputType).toBe('text'); - expect(ret.humanReadable).toBe('UUID'); - expect(ret.defaultMin).toBeUndefined(); - expect(ret.patternHelpText).toBe( - 'The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8' - ); - expect(ret.isNumberType).toBe(false); - expect(ret.allowsNegative).toBeUndefined(); - }); - - it('should return bool type', () => { - const ret = component.getType('bool'); - expect(ret).toBeTruthy(); - expect(ret.name).toBe('bool'); - expect(ret.inputType).toBe('checkbox'); - expect(ret.humanReadable).toBe('Boolean value'); - expect(ret.defaultMin).toBeUndefined(); - expect(ret.patternHelpText).toBeUndefined(); - expect(ret.isNumberType).toBe(false); - expect(ret.allowsNegative).toBeUndefined(); - }); - - it('should throw an error for unknown type', () => { - expect(() => - component.getType('unknown').toThrowError('Found unknown type "unknown" for config option.') - ); - }); - }); - describe('getValidators', () => { it('should return a validator for types float, addr and uuid', () => { const types = ['float', 'addr', 'uuid']; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts index 87b94e5e832..460f7eaf8ee 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; +import { FormControl, FormGroup, ValidatorFn } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { I18n } from '@ngx-translate/i18n-polyfill'; @@ -8,10 +8,10 @@ import * as _ from 'lodash'; import { ConfigurationService } from '../../../../shared/api/configuration.service'; import { NotificationType } from '../../../../shared/enum/notification-type.enum'; import { CdFormGroup } from '../../../../shared/forms/cd-form-group'; -import { CdValidators } from '../../../../shared/forms/cd-validators'; import { NotificationService } from '../../../../shared/services/notification.service'; import { ConfigFormCreateRequestModel } from './configuration-form-create-request.model'; import { ConfigFormModel } from './configuration-form.model'; +import { ConfigOptionTypes } from './configuration-form.types'; @Component({ selector: 'cd-configuration-form', @@ -66,127 +66,20 @@ export class ConfigurationFormComponent implements OnInit { }); } - getType(type: string): any { - const knownTypes = [ - { - name: 'uint', - inputType: 'number', - humanReadable: this.i18n('Positive integer value'), - defaultMin: 0, - patternHelpText: this.i18n('The entered value needs to be a positive number.'), - isNumberType: true, - allowsNegative: false - }, - { - name: 'int', - inputType: 'number', - humanReadable: this.i18n('Integer value'), - patternHelpText: this.i18n('The entered value needs to be a number.'), - isNumberType: true, - allowsNegative: true - }, - { - name: 'size', - inputType: 'number', - humanReadable: this.i18n('Positive integer value (size)'), - defaultMin: 0, - patternHelpText: this.i18n('The entered value needs to be a positive number.'), - isNumberType: true, - allowsNegative: false - }, - { - name: 'secs', - inputType: 'number', - humanReadable: this.i18n('Positive integer value (secs)'), - defaultMin: 1, - patternHelpText: this.i18n('The entered value needs to be a positive number.'), - isNumberType: true, - allowsNegative: false - }, - { - name: 'float', - inputType: 'number', - humanReadable: this.i18n('Decimal value'), - patternHelpText: this.i18n('The entered value needs to be a number or decimal.'), - isNumberType: true, - allowsNegative: true - }, - { - name: 'str', - inputType: 'text', - humanReadable: this.i18n('Text'), - isNumberType: false - }, - { - name: 'addr', - inputType: 'text', - humanReadable: this.i18n('IPv4 or IPv6 address'), - patternHelpText: this.i18n('The entered value needs to be a valid IP address.'), - isNumberType: false - }, - { - name: 'uuid', - inputType: 'text', - humanReadable: this.i18n('UUID'), - patternHelpText: this.i18n( - 'The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8' - ), - isNumberType: false - }, - { - name: 'bool', - inputType: 'checkbox', - humanReadable: this.i18n('Boolean value'), - isNumberType: false - } - ]; - - let currentType = null; - - knownTypes.forEach((knownType) => { - if (knownType.name === type) { - currentType = knownType; - } - }); - - if (currentType !== null) { - return currentType; - } - - throw new Error('Found unknown type "' + type + '" for config option.'); - } - getValidators(configOption: any): ValidatorFn[] { - const typeParams = this.getType(configOption.type); - this.patternHelpText = typeParams.patternHelpText; - - if (typeParams.isNumberType) { - const validators = []; - - if (configOption.max && configOption.max !== '') { - this.maxValue = configOption.max; - validators.push(Validators.max(configOption.max)); - } + const typeValidators = ConfigOptionTypes.getTypeValidators(configOption); + if (typeValidators) { + this.patternHelpText = typeValidators.patternHelpText; - if ('min' in configOption && configOption.min !== '') { - this.minValue = configOption.min; - validators.push(Validators.min(configOption.min)); - } else if ('defaultMin' in typeParams) { - this.minValue = typeParams.defaultMin; - validators.push(Validators.min(typeParams.defaultMin)); + if ('max' in typeValidators && typeValidators.max !== '') { + this.maxValue = typeValidators.max; } - if (configOption.type === 'float') { - validators.push(CdValidators.decimalNumber()); - } else { - validators.push(CdValidators.number(typeParams.allowsNegative)); + if ('min' in typeValidators && typeValidators.min !== '') { + this.minValue = typeValidators.min; } - return validators; - } else if (configOption.type === 'addr') { - return [CdValidators.ip()]; - } else if (configOption.type === 'uuid') { - return [CdValidators.uuid()]; + return typeValidators.validators; } } @@ -250,7 +143,7 @@ export class ConfigurationFormComponent implements OnInit { .setValidators(validators); }); - const currentType = this.getType(response.type); + const currentType = ConfigOptionTypes.getType(response.type); this.type = currentType.name; this.inputType = currentType.inputType; this.humanReadableType = currentType.humanReadable; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.types.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.types.spec.ts new file mode 100644 index 00000000000..d5fa623af90 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.types.spec.ts @@ -0,0 +1,215 @@ +import { ConfigFormModel } from './configuration-form.model'; +import { ConfigOptionTypes } from './configuration-form.types'; + +describe('ConfigOptionTypes', () => { + describe('getType', () => { + it('should return uint type', () => { + const ret = ConfigOptionTypes.getType('uint'); + expect(ret).toBeTruthy(); + expect(ret.name).toBe('uint'); + expect(ret.inputType).toBe('number'); + expect(ret.humanReadable).toBe('Unsigned integer value'); + expect(ret.defaultMin).toBe(0); + expect(ret.patternHelpText).toBe('The entered value needs to be an unsigned number.'); + expect(ret.isNumberType).toBe(true); + expect(ret.allowsNegative).toBe(false); + }); + + it('should return int type', () => { + const ret = ConfigOptionTypes.getType('int'); + expect(ret).toBeTruthy(); + expect(ret.name).toBe('int'); + expect(ret.inputType).toBe('number'); + expect(ret.humanReadable).toBe('Integer value'); + expect(ret.defaultMin).toBeUndefined(); + expect(ret.patternHelpText).toBe('The entered value needs to be a number.'); + expect(ret.isNumberType).toBe(true); + expect(ret.allowsNegative).toBe(true); + }); + + it('should return size type', () => { + const ret = ConfigOptionTypes.getType('size'); + expect(ret).toBeTruthy(); + expect(ret.name).toBe('size'); + expect(ret.inputType).toBe('number'); + expect(ret.humanReadable).toBe('Unsigned integer value (>=16bit)'); + expect(ret.defaultMin).toBe(0); + expect(ret.patternHelpText).toBe('The entered value needs to be a unsigned number.'); + expect(ret.isNumberType).toBe(true); + expect(ret.allowsNegative).toBe(false); + }); + + it('should return secs type', () => { + const ret = ConfigOptionTypes.getType('secs'); + expect(ret).toBeTruthy(); + expect(ret.name).toBe('secs'); + expect(ret.inputType).toBe('number'); + expect(ret.humanReadable).toBe('Number of seconds'); + expect(ret.defaultMin).toBe(1); + expect(ret.patternHelpText).toBe('The entered value needs to be a number >= 1.'); + expect(ret.isNumberType).toBe(true); + expect(ret.allowsNegative).toBe(false); + }); + + it('should return float type', () => { + const ret = ConfigOptionTypes.getType('float'); + expect(ret).toBeTruthy(); + expect(ret.name).toBe('float'); + expect(ret.inputType).toBe('number'); + expect(ret.humanReadable).toBe('Double value'); + expect(ret.defaultMin).toBeUndefined(); + expect(ret.patternHelpText).toBe('The entered value needs to be a number or decimal.'); + expect(ret.isNumberType).toBe(true); + expect(ret.allowsNegative).toBe(true); + }); + + it('should return str type', () => { + const ret = ConfigOptionTypes.getType('str'); + expect(ret).toBeTruthy(); + expect(ret.name).toBe('str'); + expect(ret.inputType).toBe('text'); + expect(ret.humanReadable).toBe('Text'); + expect(ret.defaultMin).toBeUndefined(); + expect(ret.patternHelpText).toBeUndefined(); + expect(ret.isNumberType).toBe(false); + expect(ret.allowsNegative).toBeUndefined(); + }); + + it('should return addr type', () => { + const ret = ConfigOptionTypes.getType('addr'); + expect(ret).toBeTruthy(); + expect(ret.name).toBe('addr'); + expect(ret.inputType).toBe('text'); + expect(ret.humanReadable).toBe('IPv4 or IPv6 address'); + expect(ret.defaultMin).toBeUndefined(); + expect(ret.patternHelpText).toBe('The entered value needs to be a valid IP address.'); + expect(ret.isNumberType).toBe(false); + expect(ret.allowsNegative).toBeUndefined(); + }); + + it('should return uuid type', () => { + const ret = ConfigOptionTypes.getType('uuid'); + expect(ret).toBeTruthy(); + expect(ret.name).toBe('uuid'); + expect(ret.inputType).toBe('text'); + expect(ret.humanReadable).toBe('UUID'); + expect(ret.defaultMin).toBeUndefined(); + expect(ret.patternHelpText).toBe( + 'The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8' + ); + expect(ret.isNumberType).toBe(false); + expect(ret.allowsNegative).toBeUndefined(); + }); + + it('should return bool type', () => { + const ret = ConfigOptionTypes.getType('bool'); + expect(ret).toBeTruthy(); + expect(ret.name).toBe('bool'); + expect(ret.inputType).toBe('checkbox'); + expect(ret.humanReadable).toBe('Boolean value'); + expect(ret.defaultMin).toBeUndefined(); + expect(ret.patternHelpText).toBeUndefined(); + expect(ret.isNumberType).toBe(false); + expect(ret.allowsNegative).toBeUndefined(); + }); + + it('should throw an error for unknown type', () => { + expect(() => ConfigOptionTypes.getType('unknown')).toThrowError( + 'Found unknown type "unknown" for config option.' + ); + }); + }); + + describe('getTypeValidators', () => { + it('should return two validators for type uint, secs and size', () => { + const types = ['uint', 'size', 'secs']; + + types.forEach((valType) => { + const configOption = new ConfigFormModel(); + configOption.type = valType; + + const ret = ConfigOptionTypes.getTypeValidators(configOption); + expect(ret).toBeTruthy(); + expect(ret.validators.length).toBe(2); + }); + }); + + it('should return a validator for types float, int, addr and uuid', () => { + const types = ['float', 'int', 'addr', 'uuid']; + + types.forEach((valType) => { + const configOption = new ConfigFormModel(); + configOption.type = valType; + + const ret = ConfigOptionTypes.getTypeValidators(configOption); + expect(ret).toBeTruthy(); + expect(ret.validators.length).toBe(1); + }); + }); + + it('should return undefined for type bool and str', () => { + const types = ['str', 'bool']; + + types.forEach((valType) => { + const configOption = new ConfigFormModel(); + configOption.type = valType; + + const ret = ConfigOptionTypes.getTypeValidators(configOption); + expect(ret).toBeUndefined(); + }); + }); + + it('should return a pattern and a min validator', () => { + const configOption = new ConfigFormModel(); + configOption.type = 'int'; + configOption.min = 2; + + const ret = ConfigOptionTypes.getTypeValidators(configOption); + expect(ret).toBeTruthy(); + expect(ret.validators.length).toBe(2); + expect(ret.min).toBe(2); + expect(ret.max).toBeUndefined(); + }); + + it('should return a pattern and a max validator', () => { + const configOption = new ConfigFormModel(); + configOption.type = 'int'; + configOption.max = 5; + + const ret = ConfigOptionTypes.getTypeValidators(configOption); + expect(ret).toBeTruthy(); + expect(ret.validators.length).toBe(2); + expect(ret.min).toBeUndefined(); + expect(ret.max).toBe(5); + }); + + it('should return multiple validators', () => { + const configOption = new ConfigFormModel(); + configOption.type = 'float'; + configOption.max = 5.2; + configOption.min = 1.5; + + const ret = ConfigOptionTypes.getTypeValidators(configOption); + expect(ret).toBeTruthy(); + expect(ret.validators.length).toBe(3); + expect(ret.min).toBe(1.5); + expect(ret.max).toBe(5.2); + }); + + it( + 'should return a pattern help text for type uint, int, size, secs, ' + 'float, addr and uuid', + () => { + const types = ['uint', 'int', 'size', 'secs', 'float', 'addr', 'uuid']; + + types.forEach((valType) => { + const configOption = new ConfigFormModel(); + configOption.type = valType; + + const ret = ConfigOptionTypes.getTypeValidators(configOption); + expect(ret).toBeTruthy(); + expect(ret.patternHelpText).toBeDefined(); + }); + } + ); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.types.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.types.ts new file mode 100644 index 00000000000..ed8a3b7adc4 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/configuration/configuration-form/configuration-form.types.ts @@ -0,0 +1,120 @@ +import { Validators } from '@angular/forms'; +import { CdValidators } from '../../../../shared/forms/cd-validators'; +import { ConfigFormModel } from './configuration-form.model'; + +import * as _ from 'lodash'; + +export class ConfigOptionTypes { + // TODO: I18N + private static knownTypes: Array = [ + { + name: 'uint', + inputType: 'number', + humanReadable: 'Unsigned integer value', + defaultMin: 0, + patternHelpText: 'The entered value needs to be an unsigned number.', + isNumberType: true, + allowsNegative: false + }, + { + name: 'int', + inputType: 'number', + humanReadable: 'Integer value', + patternHelpText: 'The entered value needs to be a number.', + isNumberType: true, + allowsNegative: true + }, + { + name: 'size', + inputType: 'number', + humanReadable: 'Unsigned integer value (>=16bit)', + defaultMin: 0, + patternHelpText: 'The entered value needs to be a unsigned number.', + isNumberType: true, + allowsNegative: false + }, + { + name: 'secs', + inputType: 'number', + humanReadable: 'Number of seconds', + defaultMin: 1, + patternHelpText: 'The entered value needs to be a number >= 1.', + isNumberType: true, + allowsNegative: false + }, + { + name: 'float', + inputType: 'number', + humanReadable: 'Double value', + patternHelpText: 'The entered value needs to be a number or decimal.', + isNumberType: true, + allowsNegative: true + }, + { name: 'str', inputType: 'text', humanReadable: 'Text', isNumberType: false }, + { + name: 'addr', + inputType: 'text', + humanReadable: 'IPv4 or IPv6 address', + patternHelpText: 'The entered value needs to be a valid IP address.', + isNumberType: false + }, + { + name: 'uuid', + inputType: 'text', + humanReadable: 'UUID', + patternHelpText: + 'The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8', + isNumberType: false + }, + { name: 'bool', inputType: 'checkbox', humanReadable: 'Boolean value', isNumberType: false } + ]; + + public static getType(type: string): any { + const currentType = _.find(this.knownTypes, (t) => { + return t.name === type; + }); + + if (currentType !== undefined) { + return currentType; + } + + throw new Error('Found unknown type "' + type + '" for config option.'); + } + + public static getTypeValidators(configOption: ConfigFormModel): any { + const typeParams = ConfigOptionTypes.getType(configOption.type); + + if (typeParams.name === 'bool' || typeParams.name === 'str') { + return; + } + + const typeValidators = { validators: [], patternHelpText: typeParams.patternHelpText }; + + if (typeParams.isNumberType) { + if (configOption.max && configOption.max !== '') { + typeValidators['max'] = configOption.max; + typeValidators.validators.push(Validators.max(configOption.max)); + } + + if (configOption.min && configOption.min !== '') { + typeValidators['min'] = configOption.min; + typeValidators.validators.push(Validators.min(configOption.min)); + } else if ('defaultMin' in typeParams) { + typeValidators['min'] = typeParams.defaultMin; + typeValidators.validators.push(Validators.min(typeParams.defaultMin)); + } + + if (configOption.type === 'float') { + typeValidators.validators.push(CdValidators.decimalNumber()); + } else { + typeValidators.validators.push(CdValidators.number(typeParams.allowsNegative)); + } + } else if (configOption.type === 'addr') { + typeValidators.validators = [CdValidators.ip()]; + } else if (configOption.type === 'uuid') { + typeValidators.validators = [CdValidators.uuid()]; + } + + return typeValidators; + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf index d6c8808f42c..021d0741585 100644 --- a/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf +++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf @@ -3644,112 +3644,6 @@ 1 - - Positive integer value - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - The entered value needs to be a positive number. - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - Integer value - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - The entered value needs to be a number. - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - Positive integer value (size) - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - Positive integer value (secs) - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - Decimal value - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - The entered value needs to be a number or decimal. - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - Text - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - IPv4 or IPv6 address - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - The entered value needs to be a valid IP address. - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - UUID - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8 - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - - - Boolean value - - src/app/ceph/cluster/configuration/configuration-form/configuration-form.component.ts - 1 - - Config option has been updated. -- 2.39.5