UNPKG

ddata-ui-input

Version:

DData UI Input module, components, models & services

809 lines (796 loc) 123 kB
import { faCog, faCheckSquare, faSquare, faCalendar, faSearch } from '@fortawesome/free-solid-svg-icons'; import { BaseModel, DdataCoreModule, ValidatorService, ProxyFactoryService, Paginate, SpinnerService } from 'ddata-core'; import * as i0 from '@angular/core'; import { Pipe, EventEmitter, Component, Input, Output, ViewChild, HostListener, ViewContainerRef, NgModule } from '@angular/core'; import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i2 from '@fortawesome/angular-fontawesome'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import * as i2$1 from 'ngx-color-picker'; import { ColorPickerModule } from 'ngx-color-picker'; import * as i2$2 from '@angular/forms'; import { FormsModule } from '@angular/forms'; import * as moment from 'moment'; import * as i3 from '@ng-bootstrap/ng-bootstrap'; import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap'; import { BehaviorSubject, fromEvent, Subscription } from 'rxjs'; import { debounceTime, distinctUntilChanged, takeUntil, tap, switchMap, map, finalize, take } from 'rxjs/operators'; import * as i1$1 from '@angular/router'; import * as i2$3 from 'ddata-ui-common'; import { DdataUiCommonModule } from 'ddata-ui-common'; import * as i3$1 from 'ngx-material-timepicker'; import { NgxMaterialTimepickerModule } from 'ngx-material-timepicker'; class DialogContentItem { constructor(component, data) { this.component = component; this.data = data; } } class DialogContentWithOptions { constructor(component, options) { this.component = component; this.options = options; } } // tslint:disable: variable-name class SearchModelFunctions extends BaseModel { constructor() { super(...arguments); this.icons = { cog: faCog, }; } init(data) { data = !!data ? data : {}; this.initAsNumberWithDefaults(['id'], data); this.initAsStringWithDefaults(['name', 'description', 'type', 'found_model_name'], data); this.icon = this.setIcon(this.type); this.url = this.setUrl(this.type); return this; } setUrl(type) { return type.replace(new RegExp(/_/, 'g'), '/'); } setIcon(type) { if (!type) { return this.icons.cog; } return this.icons[type] ?? this.icons.cog; } } class Search extends SearchModelFunctions { constructor() { super(...arguments); // tslint:disable: variable-name this.api_endpoint = '/search'; this.model_name = 'Search'; } init(data) { data = !!data ? data : {}; super.init(data); this.initAsStringWithDefaults(['searchText'], data); return this; } prepareToSave() { return { term: !!this.searchText ? this.searchText : '', }; } } class SearchResult extends SearchModelFunctions { init(data) { super.init(data); return this; } } class DescriptionPipe { transform(value) { value = !!value ? value : ''; let result = ''; const parts = value.split('|'); parts.forEach((part) => { part = part.replace(new RegExp(/^tel:(.*?)$/), '<a href="tel:$1" class="mr-3">$1</a>'); part = part.replace(new RegExp(/^email:(.*?)$/), '<a href="mailto:$1" class="mr-3">$1</a>'); part = part.replace(new RegExp(/^url:(.*?)$/), '<a href="$1" class="mr-3" target="_blank">$1</a>'); part = part.replace(new RegExp(/^description:(.*?)$/), '<span class="description">$1</span>'); result += part + ' '; }); return result; } } DescriptionPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DescriptionPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); DescriptionPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.0.2", ngImport: i0, type: DescriptionPipe, name: "description" }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DescriptionPipe, decorators: [{ type: Pipe, args: [{ name: 'description' }] }] }); class InputHelperService { constructor() { this.validatorService = DdataCoreModule.InjectorInstance.get(ValidatorService); } validateField(model, field) { // handle missing validation rule if (!model.validationRules[field]) { console.error('Missing validation rule:' + field + ' from model: ' + model.constructor.name); return false; } const isValid = this.validatorService.validate(model[field], model.validationRules[field]); // if not valid & validation error is not set if (!isValid && !model.validationErrors.includes(field)) { model.validationErrors.push(field); return false; } // it's valid & validation error set - need remove if (model.validationErrors.includes(field)) { model.validationErrors.splice(model.validationErrors.indexOf(field), 1); } return true; } getTitle(model, field) { if (!model || !model.fields[field] || !model.fields[field].title) { console.error(`The model not contains the '${field}' field's title. You need to set in your model the fields.${field}.title field.`); return ''; } return model.fields[field].title; } getLabel(model, field) { if (!model || !model.fields[field] || !model.fields[field].label) { console.error(`The model not contains the '${field}' field's label. You need to set in your model the fields.${field}.label field.`); return ''; } return model.fields[field].label; } getPlaceholder(model, field) { if (!model || !model.fields[field] || !model.fields[field].placeholder) { console.error(`The model not contains the '${field}' field's placeholder. You need to set in your model the fields.${field}.placeholder field.`); return ''; } return model.fields[field].title; } getPrepend(model, field) { if (!model || !model.fields[field] || !model.fields[field].prepend) { return ''; } return model.fields[field].prepend; } getAppend(model, field) { if (!model || !model.fields[field] || !model.fields[field].append) { return ''; } return model.fields[field].append; } isRequired(model, field) { return model.validationRules[field].includes('required'); } randChars() { let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const charactersLength = characters.length; for (let i = 0; i < 50; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } } class DdataInputCheckboxComponent { constructor() { // tslint:disable: variable-name this._model = new BaseModel(); this._field = 'isValid'; this._label = ''; this.disabled = false; this.showLabel = true; this.showLabelAfter = true; this.labelClass = 'col pl-2 col-form-label'; this.wrapperClass = 'd-flex'; this.iconOn = faCheckSquare; this.iconOff = faSquare; this.changed = new EventEmitter(); this.iterable = 0; } set model(value) { if (!value) { value = new BaseModel(); } this._model = value; if (!!this._model.fields) { if (!!this._model.fields[this._field]) { this._label = this._model.fields[this._field].label ?? ''; } } } get model() { return this._model; } set field(value) { if (value === 'undefined') { value = 'isValid'; } this._field = value; } get field() { return this._field; } ngOnInit() { this.iterable = Math.floor(Math.random() * 100); } clicked() { if (!this.disabled) { this.model[this._field] = !this.model[this._field]; this.changed.emit(this.model[this._field]); } } getIcon() { return !!this.model[this._field] ? this.iconOn : this.iconOff; } } DdataInputCheckboxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DdataInputCheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); DdataInputCheckboxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.2", type: DdataInputCheckboxComponent, selector: "dd-input-checkbox", inputs: { disabled: "disabled", model: "model", field: "field", showLabel: "showLabel", showLabelAfter: "showLabelAfter", labelClass: "labelClass", wrapperClass: "wrapperClass", iconOn: "iconOn", iconOff: "iconOff" }, outputs: { changed: "changed" }, ngImport: i0, template: "<div [class]=\"wrapperClass\">\n\n <label *ngIf=\"showLabel && !showLabelAfter\"\n [class]=\"labelClass\"\n [class.disabled]=\"disabled\"\n [for]=\"_field + iterable\"\n >\n {{ _label }}:\n </label>\n\n <button type=\"button\" class=\"btn btn-light\"\n (click)=\"clicked()\"\n [disabled]=\"disabled\"\n [id]=\"_field + iterable\"\n [name]=\"_field + iterable\"\n [title]=\"_label\"\n >\n <fa-icon [icon]=\"getIcon()\"></fa-icon>\n </button>\n\n <label *ngIf=\"showLabel && showLabelAfter\"\n [class]=\"labelClass\"\n [class.disabled]=\"disabled\"\n [for]=\"_field + iterable\"\n >\n {{ _label }}\n </label>\n\n</div>\n", styles: [".disabled{opacity:.3}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DdataInputCheckboxComponent, decorators: [{ type: Component, args: [{ selector: 'dd-input-checkbox', template: "<div [class]=\"wrapperClass\">\n\n <label *ngIf=\"showLabel && !showLabelAfter\"\n [class]=\"labelClass\"\n [class.disabled]=\"disabled\"\n [for]=\"_field + iterable\"\n >\n {{ _label }}:\n </label>\n\n <button type=\"button\" class=\"btn btn-light\"\n (click)=\"clicked()\"\n [disabled]=\"disabled\"\n [id]=\"_field + iterable\"\n [name]=\"_field + iterable\"\n [title]=\"_label\"\n >\n <fa-icon [icon]=\"getIcon()\"></fa-icon>\n </button>\n\n <label *ngIf=\"showLabel && showLabelAfter\"\n [class]=\"labelClass\"\n [class.disabled]=\"disabled\"\n [for]=\"_field + iterable\"\n >\n {{ _label }}\n </label>\n\n</div>\n", styles: [".disabled{opacity:.3}\n"] }] }], ctorParameters: function () { return []; }, propDecorators: { disabled: [{ type: Input }], model: [{ type: Input }], field: [{ type: Input }], showLabel: [{ type: Input }], showLabelAfter: [{ type: Input }], labelClass: [{ type: Input }], wrapperClass: [{ type: Input }], iconOn: [{ type: Input }], iconOff: [{ type: Input }], changed: [{ type: Output }] } }); class DdataInputColorComponent { constructor(helperService) { this.helperService = helperService; // tslint:disable: variable-name this._field = ''; this._title = ''; this._label = ''; this._placeholder = ''; this._prepend = ''; this._append = ''; this._isRequired = false; this._model = new BaseModel(); this.disabled = false; this.type = 'text'; this.inputClass = 'form-control'; this.labelClass = 'col-12 col-md-3 px-0 col-form-label'; this.inputBlockClass = 'col-12 d-flex px-0'; this.inputBlockExtraClass = 'col-md-9'; this.showLabel = true; this.autoFocus = false; this.wrapperClass = 'd-flex flex-wrap'; this.changed = new EventEmitter(); this.random = this.helperService.randChars(); this.toggle = false; this.validatorService = DdataCoreModule.InjectorInstance.get(ValidatorService); } set model(value) { if (!value) { value = new BaseModel(); } this._model = value; if (!!this._model && !!this._model.fields[this._field]) { this._title = this.helperService.getTitle(this._model, this._field); this._placeholder = this.helperService.getPlaceholder(this._model, this._field); this._prepend = this.helperService.getPrepend(this._model, this._field); this._append = this.helperService.getAppend(this._model, this._field); this._label = this.helperService.getLabel(this._model, this._field); } if (!!this._model && !!this._model.validationRules[this._field]) { this._isRequired = this.helperService.isRequired(this._model, this._field); } } get model() { return this._model; } set field(value) { if (value === 'undefined') { value = 'isValid'; } this._field = value; } set append(value) { if (value === 'undefined') { value = ''; } this._append = value; } set prepend(value) { if (value === 'undefined') { value = ''; } this._prepend = value; } set labelText(value) { if (value === 'undefined') { value = ''; } this._label = value; } ngOnInit() { if (this.autoFocus) { this.inputBox.nativeElement.focus(); } } validateField() { const isValid = this.helperService.validateField(this._model, this._field); if (isValid) { this.changed.emit(this._model); } } } DdataInputColorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DdataInputColorComponent, deps: [{ token: InputHelperService }], target: i0.ɵɵFactoryTarget.Component }); DdataInputColorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.2", type: DdataInputColorComponent, selector: "dd-input-color", inputs: { model: "model", field: "field", append: "append", prepend: "prepend", labelText: "labelText", disabled: "disabled", type: "type", inputClass: "inputClass", labelClass: "labelClass", inputBlockClass: "inputBlockClass", inputBlockExtraClass: "inputBlockExtraClass", showLabel: "showLabel", autoFocus: "autoFocus", wrapperClass: "wrapperClass" }, outputs: { changed: "changed" }, viewQueries: [{ propertyName: "inputBox", first: true, predicate: ["inputBox"], descendants: true }], ngImport: i0, template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_isRequired\"> *</span>\n </label>\n\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n <div class=\"input-color-container\" [style.background]=\"model[_field]\" (click)=\"toggle=!toggle\"></div>\n\n <div class=\"input-group-prepend\" *ngIf=\" _prepend != '' \">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [(ngModel)]=\"model[_field]\"\n [id]=\"_field + '_' + random\"\n [attr.name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [disabled]=\"disabled\"\n [type]=\"type\"\n [(colorPicker)]=\"model[_field]\"\n [(cpToggle)]=\"toggle\"\n cpPosition=\"bottom\"\n cpOutputFormat=\"hex\"\n cpAlphaChannel=\"disabled\"\n cpFallbackColor=\"#c0c0c0\"\n (keyup)=\"validateField()\"\n #inputBox>\n\n <div class=\"input-group-append\" *ngIf=\"_append != ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n\n</div>\n", styles: [".input-color-container{width:40px}\n"], dependencies: [{ kind: "directive", type: i2$1.ColorPickerDirective, selector: "[colorPicker]", inputs: ["cpWidth", "cpHeight", "cpToggle", "cpDisabled", "cpIgnoredElements", "cpFallbackColor", "cpColorMode", "cpCmykEnabled", "cpOutputFormat", "cpAlphaChannel", "cpDisableInput", "cpDialogDisplay", "cpSaveClickOutside", "cpCloseClickOutside", "cpUseRootViewContainer", "cpPosition", "cpPositionOffset", "cpPositionRelativeToArrow", "cpOKButton", "cpOKButtonText", "cpOKButtonClass", "cpCancelButton", "cpCancelButtonText", "cpCancelButtonClass", "cpPresetLabel", "cpPresetColorsClass", "cpMaxPresetColorsLength", "cpPresetEmptyMessage", "cpPresetEmptyMessageClass", "cpAddColorButton", "cpAddColorButtonText", "cpAddColorButtonClass", "cpRemoveColorButtonClass", "colorPicker", "cpPresetColors"], outputs: ["cpInputChange", "cpToggleChange", "cpSliderChange", "cpSliderDragEnd", "cpSliderDragStart", "colorPickerOpen", "colorPickerClose", "colorPickerCancel", "colorPickerSelect", "colorPickerChange", "cpCmykColorChange", "cpPresetColorsChange"], exportAs: ["ngxColorPicker"] }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DdataInputColorComponent, decorators: [{ type: Component, args: [{ selector: 'dd-input-color', template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_isRequired\"> *</span>\n </label>\n\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n <div class=\"input-color-container\" [style.background]=\"model[_field]\" (click)=\"toggle=!toggle\"></div>\n\n <div class=\"input-group-prepend\" *ngIf=\" _prepend != '' \">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [(ngModel)]=\"model[_field]\"\n [id]=\"_field + '_' + random\"\n [attr.name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [disabled]=\"disabled\"\n [type]=\"type\"\n [(colorPicker)]=\"model[_field]\"\n [(cpToggle)]=\"toggle\"\n cpPosition=\"bottom\"\n cpOutputFormat=\"hex\"\n cpAlphaChannel=\"disabled\"\n cpFallbackColor=\"#c0c0c0\"\n (keyup)=\"validateField()\"\n #inputBox>\n\n <div class=\"input-group-append\" *ngIf=\"_append != ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n\n</div>\n", styles: [".input-color-container{width:40px}\n"] }] }], ctorParameters: function () { return [{ type: InputHelperService }]; }, propDecorators: { model: [{ type: Input }], field: [{ type: Input }], append: [{ type: Input }], prepend: [{ type: Input }], labelText: [{ type: Input }], disabled: [{ type: Input }], type: [{ type: Input }], inputClass: [{ type: Input }], labelClass: [{ type: Input }], inputBlockClass: [{ type: Input }], inputBlockExtraClass: [{ type: Input }], showLabel: [{ type: Input }], autoFocus: [{ type: Input }], wrapperClass: [{ type: Input }], changed: [{ type: Output }], inputBox: [{ type: ViewChild, args: ['inputBox'] }] } }); class DdataInputDateComponent { constructor(changeDetector) { this.changeDetector = changeDetector; this.helperService = DdataCoreModule.InjectorInstance.get(InputHelperService); // tslint:disable: variable-name this._field = ''; this._title = ''; this._label = ''; this._placeholder = ''; this._prepend = ''; this._append = ''; this._isRequired = false; this._model = new BaseModel(); this._moment = moment; this.disabled = false; this.inputClass = 'form-control'; this.labelClass = 'col-12 col-md-3 px-0 col-form-label'; this.inputBlockClass = 'col-12 d-flex px-0'; this.inputBlockExtraClass = 'col-md-9'; this.showLabel = true; this.autoFocus = false; this.isViewOnly = false; this.viewOnlyClass = 'form-control border-0 bg-light'; this.buttonClass = 'input-group-prepend btn btn-light mb-0'; this.wrapperClass = 'd-flex flex-wrap'; this.format = 'YYYY-MM-DD'; this.separator = '-'; this.labelApply = 'OK'; this.labelCancel = 'Cancel'; this.position = 'center'; this.direction = 'down'; this.showIcon = true; this.autoApply = true; this.singleDatePicker = true; this.changed = new EventEmitter(); this.icon = { calendar: faCalendar, }; this.random = this.helperService.randChars(); this.selectedValue = !!this.model[this._field] ? this.model[this._field] : ''; } set moment(value) { if (!value) { value = moment; } this._moment = value; } set model(value) { if (!value) { value = new BaseModel(); } this._model = value; if (!!this._model && !!this._model.fields[this._field]) { this._title = this.helperService.getTitle(this._model, this._field); this._placeholder = this.helperService.getPlaceholder(this._model, this._field); this._prepend = this.helperService.getPrepend(this._model, this._field); this._append = this.helperService.getAppend(this._model, this._field); this._label = this.helperService.getLabel(this._model, this._field); } if (!!this._model && !!this._model.validationRules[this._field]) { this._isRequired = this.helperService.isRequired(this._model, this._field); } } get model() { return this._model; } set field(value) { if (value === 'undefined') { value = 'isValid'; } this._field = value; } set append(value) { if (value === 'undefined') { value = ''; } this._append = value; } set prepend(value) { if (value === 'undefined') { value = ''; } this._prepend = value; } set labelText(value) { if (value === 'undefined') { value = ''; } this._label = value; } ngOnInit() { if (!!this.model[this._field]) { this.selectedValue = this.model[this._field]; } if (this.autoFocus) { this.inputBox.nativeElement.focus(); } } change(value) { this.selectedValue = value.year + '-' + value.month.toString().padStart(2, '0') + '-' + value.day.toString().padStart(2, '0'); this.model[this._field] = this.selectedValue; const isValid = this.helperService.validateField(this._model, this._field); if (isValid) { this.changed.emit(this._model); } } typeChange(event) { this._model[this._field] = event.target.value; } } DdataInputDateComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DdataInputDateComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); DdataInputDateComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.2", type: DdataInputDateComponent, selector: "dd-input-date", inputs: { moment: "moment", model: "model", field: "field", append: "append", prepend: "prepend", labelText: "labelText", disabled: "disabled", inputClass: "inputClass", labelClass: "labelClass", inputBlockClass: "inputBlockClass", inputBlockExtraClass: "inputBlockExtraClass", showLabel: "showLabel", autoFocus: "autoFocus", isViewOnly: "isViewOnly", viewOnlyClass: "viewOnlyClass", buttonClass: "buttonClass", wrapperClass: "wrapperClass", format: "format", separator: "separator", labelApply: "labelApply", labelCancel: "labelCancel", position: "position", direction: "direction", showIcon: "showIcon", autoApply: "autoApply", singleDatePicker: "singleDatePicker" }, outputs: { changed: "changed" }, viewQueries: [{ propertyName: "inputBox", first: true, predicate: ["inputBox"], descendants: true }], ngImport: i0, template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_is_required\"> *</span>\n </label>\n\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n\n <div class=\"input-group-prepend\" *ngIf=\" _prepend != '' \">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <ng-container *ngIf=\"!isViewOnly\">\n\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [disabled]=\"disabled\"\n [id]=\"_field + '_' + random\"\n [name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [value]=\"model[_field]\"\n (dateSelect)=\"change($event)\"\n type=\"text\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n (click)=\"d.toggle()\"\n (change)=\"typeChange($event)\">\n\n </ng-container>\n\n <ng-container *ngIf=\"isViewOnly\">\n <div [class]=\"viewOnlyClass\">{{ model[_field] }}</div>\n </ng-container>\n\n <label [class]=\"buttonClass\" *ngIf=\"!disabled && showIcon\" [for]=\"_field + '_' + random\">\n <fa-icon [icon]=\"icon.calendar\"></fa-icon>\n </label>\n\n <div class=\"input-group-append\" *ngIf=\"_append != ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n\n</div>\n", styles: [":host{position:relative;flex:1 1 auto}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "spin", "pulse", "mask", "styles", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "classes", "transform", "a11yRole"] }, { kind: "directive", type: i3.NgbInputDatepicker, selector: "input[ngbDatepicker]", inputs: ["autoClose", "contentTemplate", "datepickerClass", "dayTemplate", "dayTemplateData", "displayMonths", "firstDayOfWeek", "footerTemplate", "markDisabled", "minDate", "maxDate", "navigation", "outsideDays", "placement", "popperOptions", "restoreFocus", "showWeekNumbers", "startDate", "container", "positionTarget", "weekdays", "disabled"], outputs: ["dateSelect", "navigate", "closed"], exportAs: ["ngbDatepicker"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DdataInputDateComponent, decorators: [{ type: Component, args: [{ selector: 'dd-input-date', template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_is_required\"> *</span>\n </label>\n\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n\n <div class=\"input-group-prepend\" *ngIf=\" _prepend != '' \">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <ng-container *ngIf=\"!isViewOnly\">\n\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [disabled]=\"disabled\"\n [id]=\"_field + '_' + random\"\n [name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [value]=\"model[_field]\"\n (dateSelect)=\"change($event)\"\n type=\"text\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n (click)=\"d.toggle()\"\n (change)=\"typeChange($event)\">\n\n </ng-container>\n\n <ng-container *ngIf=\"isViewOnly\">\n <div [class]=\"viewOnlyClass\">{{ model[_field] }}</div>\n </ng-container>\n\n <label [class]=\"buttonClass\" *ngIf=\"!disabled && showIcon\" [for]=\"_field + '_' + random\">\n <fa-icon [icon]=\"icon.calendar\"></fa-icon>\n </label>\n\n <div class=\"input-group-append\" *ngIf=\"_append != ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n\n</div>\n", styles: [":host{position:relative;flex:1 1 auto}\n"] }] }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { moment: [{ type: Input }], model: [{ type: Input }], field: [{ type: Input }], append: [{ type: Input }], prepend: [{ type: Input }], labelText: [{ type: Input }], disabled: [{ type: Input }], inputClass: [{ type: Input }], labelClass: [{ type: Input }], inputBlockClass: [{ type: Input }], inputBlockExtraClass: [{ type: Input }], showLabel: [{ type: Input }], autoFocus: [{ type: Input }], isViewOnly: [{ type: Input }], viewOnlyClass: [{ type: Input }], buttonClass: [{ type: Input }], wrapperClass: [{ type: Input }], format: [{ type: Input }], separator: [{ type: Input }], labelApply: [{ type: Input }], labelCancel: [{ type: Input }], position: [{ type: Input }], direction: [{ type: Input }], showIcon: [{ type: Input }], autoApply: [{ type: Input }], singleDatePicker: [{ type: Input }], changed: [{ type: Output }], inputBox: [{ type: ViewChild, args: ['inputBox'] }] } }); class DdataInputComponent { constructor() { this.helperService = DdataCoreModule.InjectorInstance.get(InputHelperService); // tslint:disable: variable-name this._field = ''; this._title = ''; this._label = ''; this._placeholder = ''; this._prepend = ''; this._append = ''; this._max = ''; this._isRequired = false; this._model = new BaseModel(); this.disabled = false; this.isViewOnly = false; this.type = 'text'; this.inputClass = 'form-control'; this.labelClass = 'col-12 col-md-3 px-0 col-form-label'; this.inputBlockClass = 'col-12 d-flex px-0'; this.inputBlockExtraClass = 'col-md-9'; this.viewOnlyClass = 'form-control border-0 bg-light'; this.wrapperClass = 'd-flex flex-wrap'; this.showLabel = true; this.autoFocus = false; this.enableCharacterCounter = false; this.enableWordCounter = false; this.maxLength = 255; this.maxWords = 7; this.wordCounterWarningMessage = ''; this.changed = new EventEmitter(); this.maxLengthReached = new EventEmitter(); this.random = this.helperService.randChars(); this.displayWordCounterWarning = false; } set model(value) { // prevent undefined if (!value) { console.error('The input-box component get undefined model'); return; } this._model = value; if (!this._model.fields) { console.error(`Your ${this._model.model_name}'s 'fields' field is`, this._model.fields); return; } if (!this._model.fields[this._field]) { console.error(`The ${this._model.model_name}'s ${this._field} field is `, this._model.fields[this._field]); return; } if (!!this._model && !!this._model.fields[this._field]) { this._title = this.helperService.getTitle(this._model, this._field); this._placeholder = this.helperService.getPlaceholder(this._model, this._field); this._prepend = this.helperService.getPrepend(this._model, this._field); this._append = this.helperService.getAppend(this._model, this._field); this._label = this.helperService.getLabel(this._model, this._field); } if (!!this._model && !!this._model.validationRules[this._field]) { this._isRequired = this.helperService.isRequired(this._model, this._field); } } get model() { return this._model; } set field(value) { if (value === 'undefined') { value = 'isValid'; } this._field = value; } set append(value) { if (value === 'undefined') { value = ''; } this._append = value; } set prepend(value) { if (value === 'undefined') { value = ''; } this._prepend = value; } set labelText(value) { if (value === 'undefined') { value = ''; } this._label = value; } ngOnInit() { } ngAfterViewInit() { if (this.autoFocus) { this.inputBox.nativeElement.focus(); } } validateField() { const isValid = this.helperService.validateField(this._model, this._field); if (isValid) { this.changed.emit(this._model); } } setWordCounterWarning(value) { this.displayWordCounterWarning = value; } } DdataInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DdataInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); DdataInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.2", type: DdataInputComponent, selector: "dd-input", inputs: { model: "model", field: "field", append: "append", prepend: "prepend", labelText: "labelText", disabled: "disabled", isViewOnly: "isViewOnly", type: "type", inputClass: "inputClass", labelClass: "labelClass", inputBlockClass: "inputBlockClass", inputBlockExtraClass: "inputBlockExtraClass", viewOnlyClass: "viewOnlyClass", wrapperClass: "wrapperClass", showLabel: "showLabel", autoFocus: "autoFocus", enableCharacterCounter: "enableCharacterCounter", enableWordCounter: "enableWordCounter", maxLength: "maxLength", maxWords: "maxWords", wordCounterWarningMessage: "wordCounterWarningMessage" }, outputs: { changed: "changed", maxLengthReached: "maxLengthReached" }, viewQueries: [{ propertyName: "inputBox", first: true, predicate: ["inputBox"], descendants: true }], ngImport: i0, template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_isRequired\"> *</span>\n </label>\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n <div class=\"input-group-prepend\" *ngIf=\" _prepend != '' \">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <ng-container *ngIf=\"!isViewOnly\">\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [(ngModel)]=\"model[_field]\"\n [id]=\"_field + '_' + random\"\n [attr.name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [disabled]=\"disabled\"\n [type]=\"type\"\n [autocomplete]=\"random\"\n (keyup)=\"validateField()\"\n #inputBox>\n <ng-container *ngIf=\"enableCharacterCounter\">\n <character-counter [currentLength]=\"model[_field]?.length || 0\" [maxLength]=\"maxLength\"></character-counter>\n </ng-container>\n <ng-container *ngIf=\"enableWordCounter\">\n <app-word-counter\n [currentLength]=\"model[_field]\"\n [maxLength]=\"maxWords\"\n (maxLentghReached)=\"showWordCounterWarning = $event\"\n ></app-word-counter>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"isViewOnly\">\n <div\n [id]=\"_field + '_' + random\"\n [class]=\"viewOnlyClass\"\n [attr.name]=\"_field + '_' + random\"\n [title]=\"_title\">\n {{ model[_field] }}\n </div>\n </ng-container>\n <div class=\"input-group-append\" *ngIf=\"_append != ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n <div *ngIf=\"displayWordCounterWarning && wordCounterWarningMessage !== ''\" class=\"d-flex pb-2\">\n <div class=\"col-12 col-md-7 offset-md-3 bg-warning p-2 rounded\">\n {{ wordCounterWarningMessage }}\n </div>\n </div>\n</div>\n", styles: [".autocomplete-list-container{position:absolute;display:inline-block;top:100%;width:100%;transition:all .2s}.autocomplete-spinner-place{top:calc(100% + 40px);transition:all .2s}.autocomplete-list{position:absolute;border:1px solid #d4d4d4;border-bottom:none;border-top:none;z-index:99;top:100%;left:0;right:0;box-shadow:0 5px 10px #0000004d}.autocomplete-list-item{padding:10px;cursor:pointer;background-color:#fff;border-bottom:1px solid #d4d4d4}.autocomplete-list-item:hover{background-color:#e9e9e9}.active{background-color:#1e90ff!important;color:#fff}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DdataInputComponent, decorators: [{ type: Component, args: [{ selector: 'dd-input', template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_isRequired\"> *</span>\n </label>\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n <div class=\"input-group-prepend\" *ngIf=\" _prepend != '' \">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <ng-container *ngIf=\"!isViewOnly\">\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [(ngModel)]=\"model[_field]\"\n [id]=\"_field + '_' + random\"\n [attr.name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [disabled]=\"disabled\"\n [type]=\"type\"\n [autocomplete]=\"random\"\n (keyup)=\"validateField()\"\n #inputBox>\n <ng-container *ngIf=\"enableCharacterCounter\">\n <character-counter [currentLength]=\"model[_field]?.length || 0\" [maxLength]=\"maxLength\"></character-counter>\n </ng-container>\n <ng-container *ngIf=\"enableWordCounter\">\n <app-word-counter\n [currentLength]=\"model[_field]\"\n [maxLength]=\"maxWords\"\n (maxLentghReached)=\"showWordCounterWarning = $event\"\n ></app-word-counter>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"isViewOnly\">\n <div\n [id]=\"_field + '_' + random\"\n [class]=\"viewOnlyClass\"\n [attr.name]=\"_field + '_' + random\"\n [title]=\"_title\">\n {{ model[_field] }}\n </div>\n </ng-container>\n <div class=\"input-group-append\" *ngIf=\"_append != ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n <div *ngIf=\"displayWordCounterWarning && wordCounterWarningMessage !== ''\" class=\"d-flex pb-2\">\n <div class=\"col-12 col-md-7 offset-md-3 bg-warning p-2 rounded\">\n {{ wordCounterWarningMessage }}\n </div>\n </div>\n</div>\n", styles: [".autocomplete-list-container{position:absolute;display:inline-block;top:100%;width:100%;transition:all .2s}.autocomplete-spinner-place{top:calc(100% + 40px);transition:all .2s}.autocomplete-list{position:absolute;border:1px solid #d4d4d4;border-bottom:none;border-top:none;z-index:99;top:100%;left:0;right:0;box-shadow:0 5px 10px #0000004d}.autocomplete-list-item{padding:10px;cursor:pointer;background-color:#fff;border-bottom:1px solid #d4d4d4}.autocomplete-list-item:hover{background-color:#e9e9e9}.active{background-color:#1e90ff!important;color:#fff}\n"] }] }], ctorParameters: function () { return []; }, propDecorators: { model: [{ type: Input }], field: [{ type: Input }], append: [{ type: Input }], prepend: [{ type: Input }], labelText: [{ type: Input }], disabled: [{ type: Input }], isViewOnly: [{ type: Input }], type: [{ type: Input }], inputClass: [{ type: Input }], labelClass: [{ type: Input }], inputBlockClass: [{ type: Input }], inputBlockExtraClass: [{ type: Input }], viewOnlyClass: [{ type: Input }], wrapperClass: [{ type: Input }], showLabel: [{ type: Input }], autoFocus: [{ type: Input }], enableCharacterCounter: [{ type: Input }], enableWordCounter: [{ type: Input }], maxLength: [{ type: Input }], maxWords: [{ type: Input }], wordCounterWarningMessage: [{ type: Input }], changed: [{ type: Output }], maxLengthReached: [{ type: Output }], inputBox: [{ type: ViewChild, args: ['inputBox'] }] } }); class BaseSearch extends Search { } class BaseSearchResult extends SearchResult { } class DdataInputSearchComponent { constructor(elementRef, router) { this.elementRef = elementRef; this.router = router; this.model = new BaseSearch().init(); this.pageNumber = 0; this.service = new ProxyFactoryService().get(BaseSearch); this.icon = { search: faSearch, }; this.isActive = new BehaviorSubject(false); this.models = []; this.paginate = new Paginate(BaseSearchResult); this.spinner = DdataCoreModule.InjectorInstance.get(SpinnerService); } clickout(event) { if (!this.elementRef.nativeElement.contains(event.target)) { // click out of component this.close(); } } ngOnDestroy() { this.isActive.next(false); } close() { this.models = []; this.isActive.next(false); } search() { // don't run if search string is empty, but reset models & close previous connection if (this.model.searchText === '') { this.isActive.next(false); this.models = []; return; } // close previous connection this.isActive.next(false); return fromEvent(this.searchInput.nativeElement, 'keyup').pipe( // run after 500 ms of last keyup debounceTime(500), // run only if value is changed distinctUntilChanged(), // run only if search input is still active and value is not empty string takeUntil(this.isActive), // switch on spinner tap(() => this.spinner.on('search')), // run search method switchMap(() => this.service.search(this.model.prepareToSave(), this.pageNumber).pipe(map((result) => { this.setResult(result); return result; }))), // switch off spinner finalize(() => this.spinner.off('search'))); } changePage(turnToPage) { this.service.getPage(turnToPage).pipe( // run only if search input is still active and value is not empty string takeUntil(this.isActive), // take only last result take(1), // switch on spinner tap(() => this.spinner.on('global-search-change-page')), // set result map((result) => { this.setResult(result); return result; }), // switch off spinner finalize(() => this.spinner.off('global-search-change-page'))).subscribe(); } go(model) { const url = model.url + '/edit/' + model.id; this.close(); this.router.navigateByUrl(url); } setResult(result) { this.paginate = result; this.models = []; result.data.forEach((item) => { const model = new BaseSearchResult().init(item); this.models.push(model); }); } } DdataInputSearchComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DdataInputSearchComponent, deps: [{ token: i0.ElementRef }, { token: i1$1.Router }], target: i0.ɵɵFactoryTarget.Component }); DdataInputSearchComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.2", type: DdataInputSearchComponent, selector: "dd-search", inputs: { model: "model", pageNumber: "pageNumber", service: "service" }, host: { listeners: { "document:click": "clickout($event)" } }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: "<div class=\"col-12 px-0\">\n <!-- keres\u0151 input -->\n <div class=\"input-group\" id=\"dropdownMenuButton\">\n <input #searchInput type=\"text\" autocomplete=\"off\" class=\"form-control border-0\" placeholder=\"Keres\u00E9s...\"\n name=\"search-string\" [(ngModel)]=\"model.searchText\">\n\n <div class=\"input-group-append\">\n <button type=\"submit\" class=\"btn btn-secondary border-0\" (click)=\"search()\">\n <fa-icon [icon]=\"icon.search\" [fixedWidth]=\"true\"></fa-icon>\n </button>\n </div>\n\n </div>\n\n <!-- dropdown men\u00FC -->\n <div class=\"search-dropdown col-12\" *ngIf=\"models.length > 0\" [ngStyle]=\"{'display': models.length > 0 ? 'block' : 'none' }\">\n <div class=\"border-bottom text-left dropdown-item\" *ngFor=\"let model of models\" (click)=\"go(model)\">\n <div class=\"row\">\n <!-- icon -->\n <div class=\"col-1 px-0 text-center text-muted\">\n <fa-icon [icon]=\"model.icon\" [fixedWidth]=\"true\"></fa-icon>\n </div>\n <div class=\"col-10\">\n <!-- name -->\n <div class=\"row\">\n <div class=\"col-12 font-bold\">\n {{ model.name }}\n </div>\n </div>\n <!-- description -->\n <div class=\"row\">\n <div class=\"col-12 small text-muted\" [innerHTML]=\"model.description | description\">