diff --git a/frontend/cypress/e2e/check-in.cy.ts b/frontend/cypress/e2e/check-in.cy.ts
index fc1f6a5eee..a20c3011e6 100644
--- a/frontend/cypress/e2e/check-in.cy.ts
+++ b/frontend/cypress/e2e/check-in.cy.ts
@@ -44,6 +44,28 @@ describe('okr check-in', () => {
cy.contains('- A new action on the action-plan');
});
+ it('should show an error message when new check-in value is not numeric', () => {
+ overviewPage
+ .addKeyResult()
+ .fillKeyResultTitle('This key-result will have errors')
+ .withMetricValues(Unit.NUMBER, '21', '51')
+ .submit();
+
+ const detailPage = keyResultDetailPage
+ .visit('Very important keyresult')
+ .createCheckIn()
+ .fillMetricCheckInValue('asdf');
+ cy.contains('Neuer Wert muss eine Zahl sein.');
+
+ detailPage.fillMetricCheckInValue('21. 2');
+ cy.contains('Neuer Wert muss eine Zahl sein.');
+
+ detailPage.fillMetricCheckInValue('123');
+ cy.contains('Neuer Wert muss eine Zahl sein.')
+ .should('not.exist');
+ });
+
+
it('should create check-in metric and assert correct owner', () => {
overviewPage
.addKeyResult()
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index beb9894af1..8a3873b4f3 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -67,7 +67,6 @@ import { CheckInFormComponent } from './components/checkin/check-in-form/check-i
import { ApplicationTopBarComponent } from './components/application-top-bar/application-top-bar.component';
import { A11yModule } from '@angular/cdk/a11y';
import { CustomizationService } from './services/customization.service';
-import { MetricCheckInDirective } from './components/checkin/check-in-form-metric/metric-check-in-directive';
function initOauthFactory(configService: ConfigService, oauthService: OAuthService) {
return async() => {
@@ -122,8 +121,7 @@ export const MY_FORMATS = {
CheckInHistoryDialogComponent,
CheckInFormMetricComponent,
CheckInFormOrdinalComponent,
- CheckInFormComponent,
- MetricCheckInDirective
+ CheckInFormComponent
],
bootstrap: [AppComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
diff --git a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html
index 7ace176202..53f222dc16 100644
--- a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html
+++ b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.html
@@ -8,19 +8,16 @@
{{ generateUnitLabel() }}
-
- {{ getErrorMessage("MUST_BE_NUMBER", "Neuer Wert") }}
-
+
diff --git a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.spec.ts b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.spec.ts
index b59ae70be5..a07fbb3373 100644
--- a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.spec.ts
+++ b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.spec.ts
@@ -10,6 +10,7 @@ import { MatInputModule } from '@angular/material/input';
import { MatRadioModule } from '@angular/material/radio';
import { Unit } from '../../../shared/types/enums/unit';
import { TranslateTestingModule } from 'ngx-translate-testing';
+// @ts-ignore
import * as de from '../../../../assets/i18n/de.json';
describe('CheckInFormComponent', () => {
@@ -36,7 +37,7 @@ describe('CheckInFormComponent', () => {
component.keyResult = keyResultMetric;
component.checkIn = checkInMetric;
component.dialogForm = new FormGroup({
- value: new FormControl('', [Validators.required]),
+ metricValue: new FormControl('', [Validators.required]),
confidence: new FormControl(5, [Validators.required,
Validators.min(1),
Validators.max(10)])
@@ -50,37 +51,87 @@ describe('CheckInFormComponent', () => {
});
it('should format percent correctly', waitForAsync(async() => {
- component.keyResult = { ...keyResultMetric,
- unit: Unit.PERCENT };
+ component.keyResult = {
+ ...keyResultMetric,
+ unit: Unit.PERCENT
+ };
expect(component.generateUnitLabel())
.toEqual('%');
}));
it('should format chf correctly', waitForAsync(async() => {
- component.keyResult = { ...keyResultMetric,
- unit: Unit.CHF };
+ component.keyResult = {
+ ...keyResultMetric,
+ unit: Unit.CHF
+ };
expect(component.generateUnitLabel())
.toEqual('CHF');
}));
it('should format eur correctly', waitForAsync(async() => {
- component.keyResult = { ...keyResultMetric,
- unit: Unit.EUR };
+ component.keyResult = {
+ ...keyResultMetric,
+ unit: Unit.EUR
+ };
expect(component.generateUnitLabel())
.toEqual('EUR');
}));
it('should format fte correctly', waitForAsync(async() => {
- component.keyResult = { ...keyResultMetric,
- unit: Unit.FTE };
+ component.keyResult = {
+ ...keyResultMetric,
+ unit: Unit.FTE
+ };
expect(component.generateUnitLabel())
.toEqual('FTE');
}));
it('should format number correctly', waitForAsync(async() => {
- component.keyResult = { ...keyResultMetric,
- unit: Unit.NUMBER };
+ component.keyResult = {
+ ...keyResultMetric,
+ unit: Unit.NUMBER
+ };
expect(component.generateUnitLabel())
.toEqual('');
}));
+
+
+ it.each([
+ [0,
+ true],
+ [150,
+ true],
+ [-23,
+ true],
+ [12.3,
+ true],
+ [-100.3,
+ true],
+ [' 123 ',
+ true],
+ [' -123.4 ',
+ true],
+ ['12 .3',
+ false],
+ ['1 2',
+ false],
+ ['',
+ false],
+ ['asdf',
+ false],
+ ['a1',
+ false],
+ ['1a',
+ false],
+ [null,
+ false]
+ ])('should correctly validate value input', (value, validity) => {
+ component.dialogForm = new FormGroup({
+ metricValue: new FormControl(undefined, [Validators.required,
+ Validators.pattern('^\\s*-?\\d+\\.?\\d*\\s*$')])
+ });
+ component.dialogForm.setValue({ metricValue: value });
+ expect(component.dialogForm.valid)
+ .toEqual(validity);
+ });
});
diff --git a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.ts b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.ts
index cdffb73982..e1c1c99282 100644
--- a/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.ts
+++ b/frontend/src/app/components/checkin/check-in-form-metric/check-in-form-metric.component.ts
@@ -1,8 +1,8 @@
-import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
-import { FormGroup, Validators } from '@angular/forms';
+import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
+import { FormGroup } from '@angular/forms';
import { KeyResultMetric } from '../../../shared/types/model/key-result-metric';
import { CheckInMin } from '../../../shared/types/model/check-in-min';
-import { formInputCheck, hasFormFieldErrors } from '../../../shared/common';
+import { formInputCheck } from '../../../shared/common';
import { TranslateService } from '@ngx-translate/core';
import { CheckInMetricMin } from '../../../shared/types/model/check-in-metric-min';
@@ -12,7 +12,7 @@ import { CheckInMetricMin } from '../../../shared/types/model/check-in-metric-mi
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false
})
-export class CheckInFormMetricComponent implements OnInit {
+export class CheckInFormMetricComponent {
@Input()
keyResult!: KeyResultMetric;
@@ -24,15 +24,8 @@ export class CheckInFormMetricComponent implements OnInit {
protected readonly formInputCheck = formInputCheck;
- protected readonly hasFormFieldErrors = hasFormFieldErrors;
-
constructor(private translate: TranslateService) {}
- ngOnInit() {
- this.dialogForm.controls['value'].setValidators([Validators.required,
- Validators.pattern('^-?\\d+\\.?\\d*$')]);
- }
-
generateUnitLabel(): string {
switch (this.keyResult.unit) {
case 'PERCENT':
@@ -48,10 +41,6 @@ export class CheckInFormMetricComponent implements OnInit {
}
}
- getErrorMessage(error: string, field: string): string {
- return field + this.translate.instant('DIALOG_ERRORS.' + error);
- }
-
getCheckInMetric(): CheckInMetricMin {
return this.checkIn as CheckInMetricMin;
}
diff --git a/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.spec.ts b/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.spec.ts
deleted file mode 100644
index c4a93de78e..0000000000
--- a/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.spec.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { MetricCheckInDirective } from './metric-check-in-directive';
-
-describe('MetricCheckInDirective', () => {
- it('should create an instance', () => {
- const directive = new MetricCheckInDirective();
- expect(directive)
- .toBeTruthy();
- });
-
- it.each([
- ['HelloWorld200',
- 200],
- ['200HelloWorld',
- 200],
- ['200\'000',
- 200000],
- ['1050&%ç*',
- 1050],
- ['-1',
- -1],
- ['-ç13&%',
- -13]
- ])('should parse value %s correctly to %s', (value: string, expected: number) => {
- const mockOnChange = jest.fn();
- const directive = new MetricCheckInDirective();
- directive.registerOnChange(mockOnChange);
-
- directive.handleInput(value);
-
- expect(mockOnChange)
- .toHaveBeenCalledWith(expected);
- });
-});
diff --git a/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.ts b/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.ts
deleted file mode 100644
index 838c4fbdf0..0000000000
--- a/frontend/src/app/components/checkin/check-in-form-metric/metric-check-in-directive.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { Directive, forwardRef, HostListener } from '@angular/core';
-import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
-
-@Directive({
- selector: '[metricCheckIn]',
- providers: [{
- provide: NG_VALUE_ACCESSOR,
- useExisting: forwardRef(() => MetricCheckInDirective),
- multi: true
- }],
- standalone: false
-})
-export class MetricCheckInDirective implements ControlValueAccessor {
- private onChange: (value: number | null) => void = () => {
- };
-
- protected readonly CHAR_REGEX = /[^0-9.]/g;
-
- writeValue(): void {
- // does not need to be implemented because the display value does not need to be modified comment is here to make linter happy
- }
-
- registerOnChange(fn: (value: number | null) => void): void {
- this.onChange = fn;
- }
-
- registerOnTouched(): void {
- // does not need to be implemented comment is here to make linter happy
- }
-
- @HostListener('input', ['$event.target.value'])
- handleInput(param: string): void {
- const value: string = param || '0';
- if (value.toString()
- .at(0) == '-') {
- this.onChange(+('-' + value.toString()
- .replace(this.CHAR_REGEX, '')));
- return;
- }
- this.onChange(Number(value.toString()
- .replace(this.CHAR_REGEX, '')));
- }
-}
diff --git a/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.html b/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.html
index 99eec7cbc4..5fb1861765 100644
--- a/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.html
+++ b/frontend/src/app/components/checkin/check-in-form-ordinal/check-in-form-ordinal.component.html
@@ -2,7 +2,7 @@
@@ -97,9 +95,7 @@
formControlName="initiatives"
id="initiatives"
>
-
- {{ getErrorMessage("MAX_VALUE", "Massnahmen", 4096) }}
-
+
diff --git a/frontend/src/app/components/checkin/check-in-form/check-in-form.component.spec.ts b/frontend/src/app/components/checkin/check-in-form/check-in-form.component.spec.ts
index 9ca6f9b30f..04683245c4 100644
--- a/frontend/src/app/components/checkin/check-in-form/check-in-form.component.spec.ts
+++ b/frontend/src/app/components/checkin/check-in-form/check-in-form.component.spec.ts
@@ -29,9 +29,12 @@ import { MatSliderModule } from '@angular/material/slider';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
-import { DialogTemplateCoreComponent } from '../../../shared/custom/dialog-template-core/dialog-template-core.component';
+import {
+ DialogTemplateCoreComponent
+} from '../../../shared/custom/dialog-template-core/dialog-template-core.component';
import { MatDividerModule } from '@angular/material/divider';
import { Action } from '../../../shared/types/model/action';
+import { Zone } from '../../../shared/types/enums/zone';
const dialogMock = {
close: jest.fn()
@@ -72,14 +75,22 @@ describe('CheckInFormComponent', () => {
provideRouter([]),
provideHttpClient(),
provideHttpClientTesting(),
- { provide: MAT_DIALOG_DATA,
- useValue: { keyResult: {} } },
- { provide: MatDialogRef,
- useValue: dialogMock },
- { provide: CheckInService,
- useValue: checkInServiceMock },
- { provide: ActionService,
- useValue: actionServiceMock }
+ {
+ provide: MAT_DIALOG_DATA,
+ useValue: { keyResult: {} }
+ },
+ {
+ provide: MatDialogRef,
+ useValue: dialogMock
+ },
+ {
+ provide: CheckInService,
+ useValue: checkInServiceMock
+ },
+ {
+ provide: ActionService,
+ useValue: actionServiceMock
+ }
],
declarations: [CheckInFormComponent,
DialogTemplateCoreComponent,
@@ -98,7 +109,7 @@ describe('CheckInFormComponent', () => {
it('should save check-in correctly if key-result is metric', waitForAsync(async() => {
component.checkIn = checkInMetric;
component.keyResult = keyResultMetric;
- component.dialogForm.controls['value'].setValue(checkInMetric?.value!.toString());
+ component.dialogForm.controls['metricValue'].setValue(checkInMetric?.value);
component.dialogForm.controls['confidence'].setValue(checkInMetric.confidence);
component.dialogForm.controls['changeInfo'].setValue(checkInMetric.changeInfo);
component.dialogForm.controls['initiatives'].setValue(checkInMetric.initiatives);
@@ -113,9 +124,9 @@ describe('CheckInFormComponent', () => {
id: checkInMetric.id,
version: checkInMetric.version,
confidence: checkInMetric.confidence,
- value: checkInMetric.value!.toString(),
changeInfo: checkInMetric.changeInfo,
initiatives: checkInMetric.initiatives,
+ value: checkInMetric.value,
keyResultId: keyResultMetric.id
});
expect(actionServiceMock.updateActions)
@@ -125,7 +136,7 @@ describe('CheckInFormComponent', () => {
it('should save check-in correctly if key-result is ordinal', waitForAsync(async() => {
component.checkIn = checkInOrdinal;
component.keyResult = keyResultOrdinal;
- component.dialogForm.controls['value'].setValue(checkInOrdinal?.zone!.toString());
+ component.dialogForm.controls['ordinalZone'].setValue(checkInOrdinal?.zone as Zone);
component.dialogForm.controls['confidence'].setValue(checkInOrdinal.confidence);
component.dialogForm.controls['changeInfo'].setValue(checkInOrdinal.changeInfo);
component.dialogForm.controls['initiatives'].setValue(checkInOrdinal.initiatives);
@@ -156,7 +167,6 @@ describe('CheckInFormComponent', () => {
expect(component.dialogForm.value)
.toStrictEqual({
confidence: checkInMetric.confidence,
- value: checkInMetric.value!.toString(),
changeInfo: checkInMetric.changeInfo,
initiatives: checkInMetric.initiatives,
actionList: undefined
@@ -170,7 +180,6 @@ describe('CheckInFormComponent', () => {
expect(component.dialogForm.value)
.toStrictEqual({
confidence: keyResultOrdinal.lastCheckIn!.confidence,
- value: '',
changeInfo: '',
initiatives: '',
actionList: []
@@ -184,7 +193,6 @@ describe('CheckInFormComponent', () => {
expect(component.dialogForm.value)
.toStrictEqual({
confidence: keyResultActions.lastCheckIn!.confidence,
- value: '',
changeInfo: '',
initiatives: '',
actionList: [action1,
diff --git a/frontend/src/app/components/checkin/check-in-form/check-in-form.component.ts b/frontend/src/app/components/checkin/check-in-form/check-in-form.component.ts
index ccdb6db3cf..5f69fa4e36 100644
--- a/frontend/src/app/components/checkin/check-in-form/check-in-form.component.ts
+++ b/frontend/src/app/components/checkin/check-in-form/check-in-form.component.ts
@@ -10,10 +10,11 @@ import { Action } from '../../../shared/types/model/action';
import { ActionService } from '../../../services/action.service';
import { formInputCheck, hasFormFieldErrors } from '../../../shared/common';
import { TranslateService } from '@ngx-translate/core';
-import { CheckIn } from '../../../shared/types/model/check-in';
import { CheckInMetricMin } from '../../../shared/types/model/check-in-metric-min';
import { CheckInOrdinalMin } from '../../../shared/types/model/check-in-ordinal-min';
import { BehaviorSubject } from 'rxjs';
+import { Zone } from '../../../shared/types/enums/zone';
+import { numberValidator } from '../../../shared/constant-library';
@Component({
selector: 'app-check-in-form',
@@ -34,7 +35,9 @@ export class CheckInFormComponent implements OnInit {
isAddingAction = false;
dialogForm = new FormGroup({
- value: new FormControl('', [Validators.required]),
+ metricValue: new FormControl(undefined, [Validators.required,
+ numberValidator()]),
+ ordinalZone: new FormControl(Zone.FAIL, [Validators.required]),
confidence: new FormControl(5, [Validators.required,
Validators.min(0),
Validators.max(10)]),
@@ -43,6 +46,9 @@ export class CheckInFormComponent implements OnInit {
actionList: new FormControl([])
});
+ checkInTypes: string[] = ['metricValue',
+ 'ordinalZone'];
+
protected readonly formInputCheck = formInputCheck;
protected readonly hasFormFieldErrors = hasFormFieldErrors;
@@ -57,6 +63,7 @@ export class CheckInFormComponent implements OnInit {
this.currentDate = new Date();
this.keyResult = data.keyResult;
this.setDefaultValues();
+ this.setValidators(this.keyResult.keyResultType);
}
ngOnInit() {
@@ -65,19 +72,13 @@ export class CheckInFormComponent implements OnInit {
this.dialogForm.patchValue({ actionList: actionList });
}
- getErrorMessage(error: string, field: string, maxLength: number): string {
- return field + this.translate.instant('DIALOG_ERRORS.' + error)
- .format(maxLength);
- }
-
setDefaultValues() {
this.dialogForm.controls.actionList.setValue(this.keyResult.actionList);
- if (this.data.checkIn != null) {
- this.checkIn = this.data.checkIn;
- this.dialogForm.controls.value.setValue(this.getCheckInValue());
- this.dialogForm.controls.confidence.setValue(this.checkIn.confidence);
- this.dialogForm.controls.changeInfo.setValue(this.checkIn.changeInfo);
- this.dialogForm.controls.initiatives.setValue(this.checkIn.initiatives);
+ this.checkIn = this.data.checkIn;
+
+ if (this.checkIn != null) {
+ this.dialogForm.patchValue({ ...this.checkIn });
+ this.setValueOrZone();
return;
}
@@ -95,6 +96,12 @@ export class CheckInFormComponent implements OnInit {
this.checkIn = { confidence: 5 } as CheckInMin;
}
+ setValueOrZone() {
+ this.keyResult.keyResultType === 'metric'
+ ? this.dialogForm.controls.metricValue.setValue((this.checkIn as CheckInMetricMin).value)
+ : this.dialogForm.controls.ordinalZone.setValue((this.checkIn as CheckInOrdinalMin).zone);
+ }
+
calculateTarget(keyResult: KeyResultMetric): number {
return keyResult.stretchGoal - (keyResult.stretchGoal - keyResult.baseline) * 0.3;
}
@@ -104,7 +111,6 @@ export class CheckInFormComponent implements OnInit {
const actionList: Action[] = this.actionList$.value as Action[];
this.dialogForm.patchValue({ actionList: actionList });
-
const baseCheckIn: any = {
id: this.checkIn.id,
version: this.checkIn.version,
@@ -113,12 +119,15 @@ export class CheckInFormComponent implements OnInit {
changeInfo: this.dialogForm.controls.changeInfo.value,
initiatives: this.dialogForm.controls.initiatives.value
};
- const checkIn: CheckIn = {
- ...baseCheckIn,
- [this.keyResult.keyResultType === 'ordinal' ? 'zone' : 'value']: this.dialogForm.controls.value.value
- };
- this.checkInService.saveCheckIn(checkIn)
+ if (this.keyResult.keyResultType === 'metric') {
+ baseCheckIn.value = this.dialogForm.controls.metricValue.value;
+ }
+ if (this.keyResult.keyResultType === 'ordinal') {
+ baseCheckIn.zone = this.dialogForm.controls.ordinalZone.value;
+ }
+
+ this.checkInService.saveCheckIn(baseCheckIn)
.subscribe(() => {
this.actionService.updateActions(this.dialogForm.value.actionList!)
.subscribe(() => {
@@ -127,14 +136,6 @@ export class CheckInFormComponent implements OnInit {
});
}
- getCheckInValue(): string {
- if ((this.checkIn as CheckInMetricMin).value != null) {
- return (this.checkIn as CheckInMetricMin).value!.toString();
- } else {
- return (this.checkIn as CheckInOrdinalMin).zone!;
- }
- }
-
getKeyResultMetric(): KeyResultMetric {
return this.keyResult as KeyResultMetric;
}
@@ -178,4 +179,11 @@ export class CheckInFormComponent implements OnInit {
this.dialogForm.patchValue({ actionList: actionList });
this.isAddingAction = false;
}
+
+ setValidators(type: string) {
+ this.checkInTypes.map((e) => this.dialogForm.get(e))
+ .forEach((e) => e?.disable({ emitEvent: false }));
+ this.dialogForm.get(this.checkInTypes.filter((formName) => formName.includes(type)))
+ ?.enable({ emitEvent: false });
+ }
}
diff --git a/frontend/src/app/components/key-result-dialog/key-result-dialog.component.ts b/frontend/src/app/components/key-result-dialog/key-result-dialog.component.ts
index 508ed16135..8728e95211 100644
--- a/frontend/src/app/components/key-result-dialog/key-result-dialog.component.ts
+++ b/frontend/src/app/components/key-result-dialog/key-result-dialog.component.ts
@@ -20,6 +20,9 @@ import { UserService } from '../../services/user.service';
export class KeyResultDialogComponent implements OnInit {
keyResultForm: FormGroup = getKeyResultForm();
+ keyResultTypes: string[] = ['metric',
+ 'ordinal'];
+
constructor(
@Inject(MAT_DIALOG_DATA) public data: {
objective: Objective;
@@ -91,18 +94,10 @@ export class KeyResultDialogComponent implements OnInit {
}
setValidators(type: string) {
- if (type == 'metric') {
- this.keyResultForm.get('metric')
- ?.enable({ emitEvent: false });
- this.keyResultForm.get('ordinal')
- ?.disable({ emitEvent: false });
- }
- if (type == 'ordinal') {
- this.keyResultForm.get('metric')
- ?.disable({ emitEvent: false });
- this.keyResultForm.get('ordinal')
- ?.enable({ emitEvent: false });
- }
+ this.keyResultTypes.map((e) => this.keyResultForm.get(e))
+ .forEach((e) => e?.disable({ emitEvent: false }));
+ this.keyResultForm.get(type)
+ ?.enable({ emitEvent: false });
}
ngOnInit(): void {
diff --git a/frontend/src/app/shared/constant-library.ts b/frontend/src/app/shared/constant-library.ts
index a5c002d38a..ac14ce753d 100644
--- a/frontend/src/app/shared/constant-library.ts
+++ b/frontend/src/app/shared/constant-library.ts
@@ -127,9 +127,9 @@ function ownerValidator(): ValidatorFn {
};
}
-function numberValidator(): ValidatorFn {
+export function numberValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
- const isAllowed = (/^-?\d+\.?\d*$/).test(control.value);
+ const isAllowed = !Number.isNaN(+control.value);
return isAllowed ? null : { number: { value: control.value } };
};
}
diff --git a/frontend/src/app/shared/custom/error/error.component.ts b/frontend/src/app/shared/custom/error/error.component.ts
index d3852b8ca2..86b8f743be 100644
--- a/frontend/src/app/shared/custom/error/error.component.ts
+++ b/frontend/src/app/shared/custom/error/error.component.ts
@@ -16,6 +16,8 @@ export class ErrorComponent {
@Input() name?: string;
+ @Input() maxErrors: number = Number.POSITIVE_INFINITY;
+
constructor(private translate: TranslateService, private parentF: FormGroupDirective) {
}
@@ -27,7 +29,8 @@ export class ErrorComponent {
}
return Object.entries(formField.errors || {})
.map(([key,
- value]) => this.buildErrorMessage(key, value));
+ value]) => this.buildErrorMessage(key, value))
+ .slice(0, this.maxErrors);
}
buildErrorMessage(key: string, value: any): string {
diff --git a/frontend/src/app/shared/types/model/check-in-metric-min.ts b/frontend/src/app/shared/types/model/check-in-metric-min.ts
index f5b5c3186c..0871ceeb8d 100644
--- a/frontend/src/app/shared/types/model/check-in-metric-min.ts
+++ b/frontend/src/app/shared/types/model/check-in-metric-min.ts
@@ -1,5 +1,5 @@
import { CheckInMin } from './check-in-min';
export interface CheckInMetricMin extends CheckInMin {
- value: number | undefined;
+ value: number;
}
diff --git a/frontend/src/app/shared/types/model/check-in-ordinal-min.ts b/frontend/src/app/shared/types/model/check-in-ordinal-min.ts
index b1a7c04c09..8144e1404b 100644
--- a/frontend/src/app/shared/types/model/check-in-ordinal-min.ts
+++ b/frontend/src/app/shared/types/model/check-in-ordinal-min.ts
@@ -1,5 +1,6 @@
import { CheckInMin } from './check-in-min';
+import { Zone } from '../enums/zone';
export interface CheckInOrdinalMin extends CheckInMin {
- zone: string | undefined;
+ zone: Zone;
}