Skip to content

Commit

Permalink
Create a new widget for decimal type (#9335)
Browse files Browse the repository at this point in the history
* [AAE-19481] Create a new widget for decimal type

* update

* CR

* unit for decimal widgets

* added test for positibe validator

* added decimal validator tests

* cr
  • Loading branch information
BSekula committed Feb 15, 2024
1 parent 300d46d commit 16005ef
Show file tree
Hide file tree
Showing 19 changed files with 533 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,9 @@ export class CardViewItemDispatcherComponent implements OnChanges {
this.loaded = true;
}

Object.keys(changes)
.map((changeName) => [changeName, changes[changeName]])
.forEach(([inputParamName, simpleChange]: [string, SimpleChange]) => {
this.componentReference.instance[inputParamName] = simpleChange.currentValue;
Object.entries(changes)
.forEach(([changeName, change]: [string, SimpleChange]) => {
this.componentReference.instance[changeName] = change.currentValue;
});

this.proxy('ngOnChanges', changes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@ export interface CardViewTextItemProperties extends CardViewItemProperties {
pipes?: CardViewTextItemPipeProperty[];
clickCallBack?: any;
}

export interface CardViewIntItemProperties extends CardViewTextItemProperties {
allowOnlyPositiveNumbers?: boolean;
}

export interface CardViewFloatItemProperties extends CardViewTextItemProperties {
precision?: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export abstract class CardViewBaseItemModel<T = any> {
if (props?.constraints?.length ?? 0) {
for (const constraint of props.constraints) {
if (constraint.type !== 'LIST') {
this.validators.push(validatorsMap[constraint.type.toLowerCase()](constraint.parameters));
const validatorFactory = validatorsMap[constraint.type.toLowerCase()];
this.validators.push(validatorFactory(constraint.parameters));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class CardViewFloatItemModel extends CardViewTextItemModel implements Car
super(cardViewTextItemProperties);

this.validators.push(new CardViewItemFloatValidator());

if (cardViewTextItemProperties.value && !cardViewTextItemProperties.multivalued) {
this.value = parseFloat(cardViewTextItemProperties.value);
}
Expand Down
17 changes: 11 additions & 6 deletions lib/core/src/lib/card-view/models/card-view-intitem.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,24 @@
import { CardViewItem } from '../interfaces/card-view-item.interface';
import { DynamicComponentModel } from '../../common/services/dynamic-component-mapper.service';
import { CardViewTextItemModel } from './card-view-textitem.model';
import { CardViewTextItemProperties } from '../interfaces/card-view.interfaces';
import { CardViewItemIntValidator } from '../validators/card-view.validators';
import { CardViewIntItemProperties } from '../interfaces/card-view.interfaces';
import { CardViewItemIntValidator, CardViewItemPositiveIntValidator } from '../validators/card-view.validators';

export class CardViewIntItemModel extends CardViewTextItemModel implements CardViewItem, DynamicComponentModel {
type: string = 'int';
inputType: string = 'number';

constructor(cardViewTextItemProperties: CardViewTextItemProperties) {
super(cardViewTextItemProperties);
constructor(cardViewIntItemProperties: CardViewIntItemProperties) {
super(cardViewIntItemProperties);

this.validators.push(new CardViewItemIntValidator());
if (cardViewTextItemProperties.value && !cardViewTextItemProperties.multivalued) {
this.value = parseInt(cardViewTextItemProperties.value, 10);

if (cardViewIntItemProperties.allowOnlyPositiveNumbers) {
this.validators.push(new CardViewItemPositiveIntValidator());
}

if (cardViewIntItemProperties.value && !cardViewIntItemProperties.multivalued) {
this.value = parseInt(cardViewIntItemProperties.value, 10);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*!
* @license
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { CardViewItemPositiveIntValidator } from './card-view-item-only-positive-int.validator';

describe('CardViewItemPositiveIntValidator', () => {
let validator: CardViewItemPositiveIntValidator;

beforeEach(() => {
validator = new CardViewItemPositiveIntValidator();
});

it('should return false for invalid integer value', () => {
expect(validator.isValid('a')).toBeFalse();
});

it('should return false for negative value', () => {
expect(validator.isValid(-1)).toBeFalse();
});

it('should return true for positive value', () => {
expect(validator.isValid(1)).toBeTrue();
});

it('should return true for empty value', () => {
expect(validator.isValid('')).toBeTrue();
});

it('should work for negative string value', () => {
expect(validator.isValid('-1')).toBeFalse();
});

it('should work for positive string value', () => {
expect(validator.isValid('1')).toBeTrue();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*!
* @license
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { CardViewItemValidator } from '../interfaces/card-view.interfaces';

export class CardViewItemPositiveIntValidator implements CardViewItemValidator {
message = 'CORE.CARDVIEW.VALIDATORS.ONLY_POSITIVE_NUMBER';

isValid(value: any | any[]): boolean {
if (Array.isArray(value)) {
return value.every(this.isPositiveNumber);
}

const valueIsNotSet = value === '';

return valueIsNotSet ||
(
!isNaN(value) &&
this.isPositiveNumber(value)
);
}

private isPositiveNumber(value: any): boolean {
return parseInt(value, 10) >= 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

export * from './card-view-item-int.validator';
export * from './card-view-item-only-positive-int.validator';
export * from './card-view-item-float.validator';
export * from './card-view-item-match.valiator';
export * from './card-view-item-minmax.valiator';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class FormFieldTypes {
static TEXT: string = 'text';
static STRING: string = 'string';
static INTEGER: string = 'integer';
static DECIMAL: string = 'bigdecimal';
static MULTILINE_TEXT: string = 'multi-line-text';
static DROPDOWN: string = 'dropdown';
static HYPERLINK: string = 'hyperlink';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import {
MinDateTimeFieldValidator,
MaxDateFieldValidator,
MinDateFieldValidator,
DateTimeFieldValidator
DateTimeFieldValidator,
DecimalFieldValidator
} from './form-field-validator';
import { FormFieldModel } from './form-field.model';
import { FormModel } from './form.model';
Expand Down Expand Up @@ -1117,4 +1118,73 @@ describe('FormFieldValidator', () => {
expect(validator.validate(field)).toBeFalse();
});
});

describe('DecimalFieldValidator', () => {
let decimalValidator: DecimalFieldValidator;

beforeEach(() => {
decimalValidator = new DecimalFieldValidator();
});

it('should validate decimal with correct precision', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DECIMAL,
value: 1.22,
precision: 2
});

expect(decimalValidator.validate(field)).toBeTrue();
});

it('should return true when value is of lower precision', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DECIMAL,
value: 1.2,
precision: 2
});

expect(decimalValidator.validate(field)).toBeTrue();
});

it('should return false when value is of higher precision', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DECIMAL,
value: 1.22,
precision: 1
});

expect(decimalValidator.validate(field)).toBeFalse();
});

it('should validate decimal of wrong precision when value is of type string', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DECIMAL,
value: '1.22',
precision: 1
});

expect(decimalValidator.validate(field)).toBeFalse();
});

it('should return false, when value is a negative number and of correct precission', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DECIMAL,
value: -1.22,
precision: 1
});

expect(decimalValidator.validate(field)).toBeFalse();
});

it('should return true, when value is a positive number and of correct precission', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DECIMAL,
value: -1.22,
precision: 3
});

expect(decimalValidator.validate(field)).toBeTrue();
});

});
});
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export class RequiredFieldValidator implements FormFieldValidator {
FormFieldTypes.DYNAMIC_TABLE,
FormFieldTypes.DATE,
FormFieldTypes.DATETIME,
FormFieldTypes.ATTACH_FOLDER
FormFieldTypes.ATTACH_FOLDER,
FormFieldTypes.DECIMAL
];

isSupported(field: FormFieldModel): boolean {
Expand Down Expand Up @@ -431,6 +432,7 @@ export class MinValueFieldValidator implements FormFieldValidator {

private supportedTypes = [
FormFieldTypes.NUMBER,
FormFieldTypes.DECIMAL,
FormFieldTypes.AMOUNT
];

Expand Down Expand Up @@ -461,6 +463,7 @@ export class MaxValueFieldValidator implements FormFieldValidator {

private supportedTypes = [
FormFieldTypes.NUMBER,
FormFieldTypes.DECIMAL,
FormFieldTypes.AMOUNT
];

Expand Down Expand Up @@ -553,6 +556,50 @@ export class FixedValueFieldValidator implements FormFieldValidator {
}
}

export class DecimalFieldValidator implements FormFieldValidator {

private supportedTypes = [
FormFieldTypes.DECIMAL
];

isSupported(field: FormFieldModel): boolean {
return field && this.supportedTypes.indexOf(field.type) > -1 && !!field.value;
}

validate(field: FormFieldModel): boolean {
const shouldValidateField = this.isSupported(field) && field.isVisible;

if (!shouldValidateField) {
return true;
}

const precision = field.precision;
const fieldValue = field.value;

if (!isNumberValue(fieldValue)) {
field.validationSummary.message = 'FORM.FIELD.VALIDATOR.INVALID_DECIMAL_NUMBER';
return false;
}

const value = typeof fieldValue === 'string' ? fieldValue : fieldValue.toString();
const valueParts = value.split('.');
const decimalPart = valueParts[1];

if (decimalPart === undefined) {
return true;
}

if (decimalPart.length > precision) {
field.validationSummary.message = 'FORM.FIELD.VALIDATOR.INVALID_DECIMAL_PRECISION';
field.validationSummary.attributes.set('precision', precision.toString());

return false;
}

return true;
}
}

export const FORM_FIELD_VALIDATORS = [
new RequiredFieldValidator(),
new NumberFieldValidator(),
Expand All @@ -567,5 +614,6 @@ export const FORM_FIELD_VALIDATORS = [
new MaxDateFieldValidator(),
new FixedValueFieldValidator(),
new MinDateTimeFieldValidator(),
new MaxDateTimeFieldValidator()
new MaxDateTimeFieldValidator(),
new DecimalFieldValidator()
];
12 changes: 10 additions & 2 deletions lib/core/src/lib/form/components/widgets/core/form-field.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export class FormFieldModel extends FormWidgetModel {
maxValue: string;
maxDateRangeValue: number = 0;
minDateRangeValue: number = 0;
precision: number;
dynamicDateRangeSelection: boolean;
regexPattern: string;
options: FormFieldOption[] = [];
Expand Down Expand Up @@ -100,8 +101,10 @@ export class FormFieldModel extends FormWidgetModel {
}

set value(v: any) {
this._value = v;
this.updateForm();
if (v !== this._value) {
this._value = v;
this.updateForm();
}
}

get readOnly(): boolean {
Expand Down Expand Up @@ -200,6 +203,7 @@ export class FormFieldModel extends FormWidgetModel {
this.groupsRestriction = json.groupsRestriction?.groups;
this.variableConfig = json.variableConfig;
this.schemaDefinition = json.schemaDefinition;
this.precision = json.precision;

if (json.placeholder && json.placeholder !== '' && json.placeholder !== 'null') {
this.placeholder = json.placeholder;
Expand Down Expand Up @@ -459,6 +463,10 @@ export class FormFieldModel extends FormWidgetModel {
this.form.values[this.id] = this.enableFractions ? parseFloat(this.value) : parseInt(this.value, 10);
break;
}
case FormFieldTypes.DECIMAL: {
this.form.values[this.id] = parseFloat(this.value);
break;
};
case FormFieldTypes.BOOLEAN: {
this.form.values[this.id] = this.value !== null && this.value !== undefined ? this.value : false;
break;
Expand Down

0 comments on commit 16005ef

Please sign in to comment.