ddata-ui-input
Version:
DData UI Input module, components, models & services
809 lines (796 loc) • 123 kB
JavaScript
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\">