diff --git a/projects/common-form-elements/src/lib/dynamic-form/dynamic-form.component.ts b/projects/common-form-elements/src/lib/dynamic-form/dynamic-form.component.ts index 17ef3fd9e44a126e92caf11c715ca4cc0755bb9d..97472f61b69efe289527e94f91900394f8cee594 100644 --- a/projects/common-form-elements/src/lib/dynamic-form/dynamic-form.component.ts +++ b/projects/common-form-elements/src/lib/dynamic-form/dynamic-form.component.ts @@ -281,6 +281,9 @@ export class DynamicFormComponent implements OnInit, OnChanges, OnDestroy { case 'time': validationList.push(this.validateTime.bind(this, element.validations[i].value, element)); break; + case 'maxtimevalue': + validationList.push(this.validateMaxTime.bind(this, element.validations[i].value, element)); + break; case 'compare': validationList.push(this.compareFields.bind(this, element.validations[i].criteria)); break; @@ -351,6 +354,23 @@ export class DynamicFormComponent implements OnInit, OnChanges, OnDestroy { // return moment(control.value, pattern, true).isValid() && control.touched ? null : {time: true}; } + validateMaxTime(maxTimeValue, field, control: AbstractControl): ValidationErrors | null { + if (control.value && maxTimeValue) { + const maxTimeInputTimeArray = control.value.split(':'); + const maxTimeAllowedArray = maxTimeValue.split(':'); + const maxTimeAllowedInSeconds = (_.parseInt(maxTimeAllowedArray[0]) * 3600) + + (_.parseInt(maxTimeAllowedArray[1]) * 60); + const maxTimeInputInSeconds = (_.parseInt(maxTimeInputTimeArray[0]) * 3600) + + (_.parseInt(maxTimeInputTimeArray[1]) * 60); + if (maxTimeInputInSeconds > maxTimeAllowedInSeconds) { + return { maxtimevalue: true }; + } + return null; + } else { + return null; + } + } + compareFields(criteria, control: AbstractControl): ValidationErrors | null { diff --git a/projects/common-form-elements/src/lib/dynamic-timer/dynamic-timer.component.html b/projects/common-form-elements/src/lib/dynamic-timer/dynamic-timer.component.html index cddd7c1657d5d05d0715234682a8ae4106ded73c..a24d623b85e699728b9523c5ff75a44e54c0a6c5 100644 --- a/projects/common-form-elements/src/lib/dynamic-timer/dynamic-timer.component.html +++ b/projects/common-form-elements/src/lib/dynamic-timer/dynamic-timer.component.html @@ -1,7 +1,7 @@ -<div class="sb-input"> +<!-- <div class="sb-input"> <label *ngIf="label" [attr.data-title]="field.description ? field.description : null"> {{label}}</label> - <input (keyup)="onChangeEvent($event)" [class.valid]="formControlRef.valid && + <input (keyup)="onChangeEvent($event)" [class.valid]="formControlRef.valid && (formControlRef.dirty || formControlRef.touched)" [class.invalid]="formControlRef.invalid && (formControlRef.dirty || formControlRef.touched)" class="sb-textbox {{disabled}}" placeholder={{placeholder}} type="text" @@ -13,4 +13,46 @@ {{ validation.message }} </div> </ng-container> +</div> --> + +<div class="sb-input"> + <label *ngIf="label" [attr.data-title]="field.description ? field.description : null"> {{label}}</label> + <ng-container> + <div class="d-flex"> + <div> + <input class="p-10 mr-20" list="hours" #hourField name="hour" id="hour" maxlength="2" + placeholder="{{placeholders[0]}}" + (change)="onChangeTimer(field, 'hr', $event.target.value)" + (keyup)="onChangeTimer(field, 'hr', $event.target.value);" + (focusout)="onFocusOutEvent('hr', $event.target.value)" + [attr.disabled]="disabled ? true : ( depends ? (isDependsInvalid ? true : null) : null )"> + <datalist id="hours"> + <option *ngFor="let hour of hourOptions" [value]="hour"> + </datalist> + </div> + <div> + <input class="p-10 mr-20" list="minutes" #minField name="minute" id="minute" maxlength="2" + placeholder="{{placeholders[1]}}" + (change)="onChangeTimer(field, 'min', $event.target.value)" + (keyup)="onChangeTimer(field, 'min', $event.target.value)" + (focusout)="onFocusOutEvent('min', $event.target.value)" + [attr.disabled]="disabled ? true : ( depends ? (isDependsInvalid ? true : null) : null )"> + <datalist id="minutes"> + <ng-container> + <option *ngFor="let minute of minuteOptions" [value]="minute">{{minute}}</option> + </ng-container> + </datalist> + </div> + <div> + <button *ngIf="!disabled" class="sb-btn sb-btn-normal sb-btn-outline-primary" (click)="restTime()">Reset</button> + </div> + </div> + <ng-container *ngFor="let validation of validations"> + <div class="cf-error" + *ngIf="(validation.type && (validation.type).toLowerCase() && validation.message && formControlRef.errors && formControlRef.errors[(validation.type).toLowerCase()] && + (formControlRef.dirty || formControlRef.touched)) "> + {{ validation.message }} + </div> + </ng-container> + </ng-container> </div> diff --git a/projects/common-form-elements/src/lib/dynamic-timer/dynamic-timer.component.ts b/projects/common-form-elements/src/lib/dynamic-timer/dynamic-timer.component.ts index 335829a4c819b12f6aeb1eb799c9e752531b224f..9836b20d64c3a58888ed2b335f30062bafe1ff76 100644 --- a/projects/common-form-elements/src/lib/dynamic-timer/dynamic-timer.component.ts +++ b/projects/common-form-elements/src/lib/dynamic-timer/dynamic-timer.component.ts @@ -37,16 +37,24 @@ export class DynamicTimerComponent implements OnInit, OnDestroy { @Input() dataLoadStatusDelegate: Subject<'LOADING' | 'LOADED'>; @ViewChild('validationTrigger') validationTrigger: ElementRef; + @ViewChild('hourField') hourField: ElementRef; + @ViewChild('minField') minField: ElementRef; public isDependsInvalid: any; contextValueChangesSubscription?: Subscription; options$?: Observable<FieldConfigOption<any>[]>; value: any = null; maxValue: any = []; - + hourOptions = []; + minuteOptions = []; + defaultMin: any = null; + defaultHr: any = null; + placeholders = []; constructor(private changeDetectionRef: ChangeDetectorRef) { } ngOnInit() { + this.getPlaceHolder(); this.findMaxValue(); + this.getHourAndMinuteOptions(); if (!this.options) { this.options = _.isEmpty(this.field.options) ? this.isOptionsClosure(this.field.options) && this.field.options : []; } @@ -64,7 +72,11 @@ export class DynamicTimerComponent implements OnInit, OnDestroy { if (!_.isEmpty(this.depends)) { this.contextValueChangesSubscription = merge(..._.map(this.depends, depend => depend.valueChanges)).pipe( tap((value: any) => { - this.value = null; + this.defaultHr = null; + this.defaultMin = null; + this.hourField.nativeElement.value = null; + this.minField.nativeElement.value = null; + // this.value = null; this.formControlRef.patchValue(null); this.isDependsInvalid = _.includes(_.map(this.depends, depend => depend.invalid), true); }) @@ -72,14 +84,61 @@ export class DynamicTimerComponent implements OnInit, OnDestroy { this.isDependsInvalid = _.includes(_.map(this.depends, depend => depend.invalid), true); } - this.setDefaultValue(); + // this.setDefaultValue(); + } + + ngAfterViewInit() { + this.setDefaultValue(); + } + + getPlaceHolder() { + if (this.placeholder) { + this.placeholders = this.placeholder.split(':'); + } else { + this.placeholders[0] = 'hh'; + this.placeholders[1] = 'mm'; + } + } + + getHourAndMinuteOptions() { + let maxHour = 5; + if (!_.isEmpty(this.maxValue)) { + maxHour = Number(this.maxValue[0]); + } + for (let i = 0; i <= maxHour; i++) { + if (i.toString().length === 1) { + this.hourOptions.push('0' + i.toString()); + } else { + this.hourOptions.push(i.toString()); + } + } + for (let i = 0; i < 60; i++) { + if (i.toString().length === 1) { + this.minuteOptions.push('0' + i.toString()); + } else { + this.minuteOptions.push(i.toString()); + } + } } setDefaultValue() { if (!_.isEmpty(this.default)) { - this.value = this.default; } + const defaultTime = this.default.split(':'); + this.defaultHr = defaultTime[0]; + this.defaultMin = defaultTime[1]; + this.hourField.nativeElement.value = defaultTime[0]; + this.minField.nativeElement.value = defaultTime[1]; + // this.value = this.default; + this.setFormFieldValue(); + } + } + + setFormFieldValue() { + this.formControlRef.markAsTouched(); + this.formControlRef.patchValue(this.defaultHr + ':' + this.defaultMin); } + /* checkValue(str, max) { if (str.charAt(0) !== '0') { let num = _.parseInt(str); @@ -110,8 +169,9 @@ export class DynamicTimerComponent implements OnInit, OnDestroy { str = num > _.parseInt(max.toString().charAt(0)) && num.toString().length === 2 ? '0' + max : '0' + num.toString(); } return str; - } + } */ + /* onChangeEvent(event?: any, type?) { type = 'text'; let input = event.target.value; @@ -140,23 +200,23 @@ export class DynamicTimerComponent implements OnInit, OnDestroy { }); this.value = output.join('').substr(0, this.getMaxValueLength()); } - this.formControlRef.markAsTouched(); this.formControlRef.patchValue(this.value); - } + } */ findMaxValue() { - let maxObj = _.find(this.validations, {type: 'max'}); + let maxObj = _.find(this.validations, {type: 'maxtimevalue'}); maxObj = maxObj && maxObj.value ? maxObj : !_.isEmpty(_.compact(this.dependencyTerms)) ? {type: 'max', value: this.dependencyTerms} : {}; this.maxValue = maxObj && maxObj.value ? maxObj.value.split(':').map((v) => v.replace(/\D/g, '')) : []; } + /* getMaxValueLength() { const flattenedArray = this.maxValue.join(':'); return flattenedArray && flattenedArray.length; - } + } */ isOptionsClosure(options: any) { return typeof options === 'function'; @@ -168,4 +228,91 @@ export class DynamicTimerComponent implements OnInit, OnDestroy { } } + onChangeTimer(field, fieldType, value) { + if (fieldType === 'hr') { + const numericValue = value.replace(/[^0-9]/g, ''); + this.defaultHr = numericValue; + this.hourField.nativeElement.value = numericValue; + if (!this.defaultMin) { + this.defaultMin = '00'; + this.minField.nativeElement.value = '00'; + } + } + if (fieldType === 'min') { + const numericValue = value.replace(/[^0-9]/g, ''); + if (_.parseInt(numericValue) > 59) { + const subtractedMinute = _.toString(_.parseInt(numericValue) - 60); + if (subtractedMinute.length === 1) { + this.defaultMin = '0' + subtractedMinute; + } else { + this.defaultMin = _.toString(subtractedMinute); + } + if (this.defaultHr) { + this.defaultHr = _.toString(_.parseInt(this.defaultHr) + 1); + if (this.defaultHr.length === 1) { + this.defaultHr = '0' + this.defaultHr; + } else { + this.defaultHr = _.toString(this.defaultHr); + } + } else if (!this.defaultHr) { + this.defaultHr = '00'; + } + this.minField.nativeElement.value = this.defaultMin; + this.hourField.nativeElement.value = this.defaultHr; + } else { + this.defaultMin = numericValue; + this.minField.nativeElement.value = numericValue; + if (!this.defaultHr) { + this.defaultHr = '00'; + this.hourField.nativeElement.value = '00'; + } + } + } + + if (this.defaultHr && this.defaultMin) { + this.patchTimerValue(); + } + + } + + patchTimerValue() { + let hour, minute; + if (this.defaultHr.length === 1) { + hour = '0' + this.defaultHr; + } else { + hour = this.defaultHr; + } + if (this.defaultMin.length === 1) { + minute = '0' + this.defaultMin; + } else { + minute = this.defaultMin; + } + const totalTime = hour + ':' + minute + ':00'; + this.formControlRef.markAsTouched(); + this.formControlRef.patchValue(totalTime); + } + + restTime() { + this.defaultHr = null; + this.defaultMin = null; + this.hourField.nativeElement.value = null; + this.minField.nativeElement.value = null; + this.formControlRef.markAsTouched(); + this.formControlRef.patchValue(null); + } + + onFocusOutEvent(fieldType, value) { + if (fieldType === 'hr') { + if (value.length === 1) { + this.defaultHr = '0' + value; + this.hourField.nativeElement.value = this.defaultHr; + } + } + if (fieldType === 'min') { + if (value.length === 1) { + this.defaultMin = '0' + value; + this.minField.nativeElement.value = this.defaultMin; + } + } + } } diff --git a/src/app/formConfig.ts b/src/app/formConfig.ts index 91d2e9e71627bcbd1ba81d2b5cf231c7bef98421..2db3e0c307aca665e7a0db71dcc740f2ed76fdcc 100644 --- a/src/app/formConfig.ts +++ b/src/app/formConfig.ts @@ -935,7 +935,63 @@ export const timer = [ 'KP_FT_1591276469489', 'KP_FT_1591276469748' ] - } + }, + { + 'code': 'maxTime', + 'visible': true, + 'editable': true, + 'dataType': 'text', + 'name': 'MaxTimer', + 'default': '00:00', + 'renderingHints': { + 'class': 'sb-g-col-lg-1 required' + }, + 'description': 'MaxTime for the content', + 'inputType': 'timer', + 'label': 'Max time', + 'placeholder': 'hh:mm', + 'required': true, + 'validations': [ + { + 'type': 'required', + 'message': 'Maxtime is required' + }, + { + 'type': 'maxtimevalue', + 'value': '05:30', + 'message': 'max time should be less than or equal to 05:30' + } + ] + }, + { + 'code': 'warningTime', + 'visible': true, + 'editable': true, + 'dataType': 'text', + 'name': 'Warning Time', + 'renderingHints': { + 'class': 'sb-g-col-lg-1' + }, + 'depends': [ + 'maxTime' + ], + 'description': 'warning for the content', + 'inputType': 'timer', + 'label': 'Warning Time', + 'placeholder': 'hh:mm', + 'required': false, + 'validations': [ + { + 'type': 'compare', + 'criteria': { + '<=': [ + 'maxTime' + ] + }, + 'message': 'warning time should be less than max timer' + } + ] + }, ] } ];