UNPKG

@codecabinet.online/codecabinet.online-sni-custom-grid-library

Version:

codecabinet.online created an astonishing grid library

464 lines 333 kB
import { EventEmitter, Output } from '@angular/core'; import { Component, ContentChildren, ElementRef, Input, ViewChild } from '@angular/core'; import { Subject, fromEvent } from 'rxjs'; import { defaultDebounceTime, isNotEmpty } from '../../constants/constants'; import { gridSettings } from '../../constants/gridOptions'; import { CustomGridColumnComponent } from '../custom-grid-column/custom-grid-column.component'; import { columnTypes, customDetailTypes, detailsLoadMethod } from '../custom-grid-models/constants'; import { debounceTime } from 'rxjs/operators'; import * as i0 from "@angular/core"; import * as i1 from "@angular/router"; import * as i2 from "../../services/notification.service"; import * as i3 from "@ngx-translate/core"; import * as i4 from "@progress/kendo-angular-dropdowns"; import * as i5 from "@progress/kendo-angular-dateinputs"; import * as i6 from "@progress/kendo-angular-inputs"; import * as i7 from "ng-apexcharts"; import * as i8 from "@angular/common"; import * as i9 from "@angular/forms"; import * as i10 from "../directives/zipcode.directive"; import * as i11 from "@ng-bootstrap/ng-bootstrap"; import * as i12 from "../directives/routeTransformerDirective.directive"; import * as i13 from "../../pipes/sanitize-html.pipe"; export class CustomGridComponent { constructor(renderer, _router, _toastService, _translate) { this.renderer = renderer; this._router = _router; this._toastService = _toastService; this._translate = _translate; this.rowHasDetails = false; this.hasGridDetails = false; this.hasFilters = false; this.rowDetails = []; this.disabledRows = []; this.disabledReasons = []; this.gridDetails = []; this.gridDetailsOrder = []; /*height of the table*/ this.overflowX = ""; /*overflow style - types : scroll,hidden,auto*/ this.overflowY = ""; /*if set, ignores default grid template*/ this.rowClass = []; /*if set, ignores default grid noRecords*/ this.noRecordsInnerHTML = null; /* Customization properties */ /*-------------------------------------------------------*/ this.popoverConfiguration = null; this.rowCheckable = false; this.checkedRows = []; this.customDetails = []; this.detailsTitle = ""; this.toggleDetailsText = null; this.translationKey = ""; this.gridDetailsTrasnlationKey = ""; this.hasNumbering = false; this.hasStockInputIcon = false; this.dataLoaded = false; this.displayedDetails = []; this.popOverReturnOption = "id"; this.filters = []; this.filtersChange = new Subject(); /* Output */ /*-------------------------------------------------------*/ this.triggerFilters = new EventEmitter(); this.popOver = new EventEmitter(); this.scroll = new EventEmitter(); this.detailsToggled = new EventEmitter(); this.toggleChanged = new EventEmitter(); this.imageEnlarge = new EventEmitter(); this.customDetailsAction = new EventEmitter(); this.tooltipHover = new EventEmitter(); this.modalClickHandler = new EventEmitter(); this.mapHandler = new EventEmitter(); this.checkedRowsChange = new EventEmitter(); /* Local properties */ /*-------------------------------------------------------*/ this.pageable = true; this.hasPageSizeSelection = false; this.pageSizes = [10, 20, 50, 100]; /* Local properties */ /*-------------------------------------------------------*/ this.dataSourceColumns = []; this.columnsDefinition = []; this.grid = []; this.norecords = false; this.columnTypes = columnTypes; this.init = true; this.allSelected = false; this.hasSelected = false; this.localCheckedRows = []; this.customDetailTypes = customDetailTypes; this.tooltipList = []; this._periodRange = { start: null, end: null }; this.showDateRangePopup = false; this.objectKeys = Object.keys; this.filterSubscription = this.filtersChange.pipe(debounceTime(defaultDebounceTime)).subscribe(x => { let filterEvent = { filters: this.filters, filterMethod: this.filterMethod }; this.triggerFilters.emit(filterEvent); }); this.chartOptions = { chart: { height: 200, type: "radialBar" }, series: [67], plotOptions: { radialBar: { hollow: { margin: 15, size: "65%", }, dataLabels: { value: { offsetY: -7, color: "#000", fontSize: "16px", show: true } }, } }, labels: [""], fill: { colors: ["#5ec12d"], } }; } ngOnDestroy() { if (this.filterSubscription) { this.filterSubscription.unsubscribe(); } if (this.scrollWindow) { this.scrollWindow.unsubscribe(); } } ngOnInit() { let ls_page = localStorage.getItem(gridSettings.pageSize); if (ls_page) { this.pageSize = JSON.parse(ls_page); } } ngOnChanges() { this.norecords = this.dataSource && this.dataSource.length == 0; if (this.dataSource && this.init) { this.init = false; this.dataSource.forEach(element => { element.isExpanded = false; // element.isSelected = false; element.isDisabled = false; if (this.detailsLoadMethod == detailsLoadMethod.server) { element.isDetailLoaded = false; } }); } var columnsDef = this.columns?.toArray().map(x => { return { field: isNotEmpty(x.filterKey) ? x.filterKey : x.field, title: x.title, }; }); var columnLabels = this.columns?.toArray().map(x => x.filterDataSource); this.datasourcesDef = columnLabels ? this.renameKeys(columnLabels, this.dataSourceColumns) : null; } ngAfterViewInit() { setTimeout(() => { var columns = this.columns.toArray(); this.dataSourceColumns = columns.map(x => { return { field: isNotEmpty(x.filterKey) ? x.filterKey : x.field, title: x.title, filterKey: isNotEmpty(x.filterKey) ? x.filterKey : x.field, highlightedAnchorKey: x.highlightedAnchorKey }; }); let colProperties = columns.map(x => { return { width: x.width, background: x.background, redirectLink: x.redirectLink, columnType: x.columnType, disabled: x.disabled, hasFilter: x.hasFilter, stateClasses: x.stateClasses, tooltipList: x.tooltipList, filterKey: x.filterKey, displayedItems: x.displayedItems, missingText: x.missingText, disabledTooltipList: x.disabledTooltipList, hiddenContent: x.hiddenContent, textAlign: x.textAlign, props: x.props, colTemplate: x.colTemplate, iconHoverText: x.iconHoverText, isRedirectActive: x.isRedirectActive, columnClasses: x.columnClasses }; }); this.columnsDefinition = this.renameKeys(colProperties, this.dataSourceColumns); var columnLabels = this.columns?.toArray().map(x => x.filterDataSource); this.datasourcesDef = columnLabels ? this.renameKeys(columnLabels, this.dataSourceColumns) : null; // var filters = columns.map(x => this.filters[x.field]); // this.filters = this.renameKeys(filters, this.dataSourceColumns);//not needed anymore }, 0); const SCROLLABLE_AREA = this.height && this.height.search("%") == -1 ? this.elementRef.nativeElement : window; this.scrollWindow = fromEvent(SCROLLABLE_AREA, 'scroll').subscribe((event) => { this.scrollHandler(event); }); } generateDynamicHtml(htmlTemplateProvided, row, stateClasses) { // console.log("[DEBUG]: GenerateDynamicHtml" + htmlTemplateProvided); // console.log(row); const regex = /\{{(.*?)\}}/; var matched = regex.exec(htmlTemplateProvided); while (matched) { htmlTemplateProvided = htmlTemplateProvided.replace(matched[0], row[matched[1]]); matched = regex.exec(htmlTemplateProvided); } if (stateClasses?.length > 0) { const regexClass = /\{#(.*?)\#}/; var matchedClass = regexClass.exec(htmlTemplateProvided); while (matchedClass) { htmlTemplateProvided = htmlTemplateProvided.replace(matchedClass[0], this.selectClass(stateClasses, row, matchedClass[1])); matchedClass = regexClass.exec(htmlTemplateProvided); } } return htmlTemplateProvided; } renameKeys(obj, newKeys) { const keyValues = Object.keys(obj).map(key => { const newKey = newKeys[key] || key; return { [newKey.field]: obj[key] }; }); return Object.assign({}, ...keyValues); } checkRedirectIsActive(isRedirectActive, row) { return isRedirectActive != null && eval(isRedirectActive); } redirectRoute(route = null, id, isRedirectActive, row) { if (isNotEmpty(route) && this.checkRedirectIsActive(isRedirectActive, row)) { if (isNotEmpty(id)) { this._router.navigate([route + '/' + id]); } else { this._router.navigate([route]); } } } redirectUrl(link, row) { if (this.checkDisabledRow(row)) { return; } if (link.isExternal) { window.location.href = link.url; } else { this._router.navigate([link.url], { queryParams: link.queryParams }); } } /* Details */ toggleDetailsContainer(rowIndex, id = null) { this.dataSource.forEach((element, index) => { if (element.isExpanded && index != rowIndex) { element.isExpanded = false; } }); var isExpanded = this.dataSource[rowIndex].isExpanded; var isDetailLoaded = this.dataSource[rowIndex].isDetailLoaded; this.dataSource[rowIndex].isExpanded = !isExpanded; if (!isExpanded && this.detailsLoadMethod == detailsLoadMethod.server && !isDetailLoaded) { this.dataSource[rowIndex].isDetailLoaded = true; let event = { id: id, rowIndex: rowIndex }; this.detailsToggled.emit(event); } } formatDate(date) { var stringToDate = new Date(date); var fullDate = stringToDate.toLocaleDateString(localStorage.getItem("selectedLanguage")); return fullDate; } disabledSwitch(row, disabledExpression) { return eval(disabledExpression); } disabledPopoverButtons(row, disabledExpression) { return eval(disabledExpression); } hidePopoverButtons(row, hiddenExpression) { return eval(hiddenExpression); } checkDisabledRow(row) { if (this.disabledRows.find(y => { return y.key != null ? row[this.dataSourcePK] == y.key : y.index == this.dataSource.indexOf(row); }) != undefined) { return true; } return false; } checkDisabledCheckboxRow(row) { if (row.isDisabled) { return true; } return this.checkDisabledRow(row); } selectClass(event, row, classTarget = null) { return this.selectClassTemplate(event, row, classTarget); } selectRowClass(row) { if (this.rowClass) { return this.selectClassTemplate(this.rowClass, row); } } selectClassTemplate(classArray, row, classTarget = null) { var returnedClass = "default-class"; if (classArray) { classArray.forEach(element => { if (eval(element.expression) && (element.classTarget == classTarget || !classTarget || !element.classTarget)) { returnedClass = element.className; return; } }); } return returnedClass; } disable(exp, row) { return eval(exp); } hideCustomDetail(exp, row) { return eval(exp); } evaluateExpression(exp, row) { return eval(exp); } isNotEmpty(element) { return isNotEmpty(element); } checkHiddenCell(row, expression) { return !eval(expression); } /* Emitters */ /*-------------------------------------------------------*/ toggleValueChange(id) { this.toggleChanged.emit(id); } popoverAction(action, rowData) { let event = { action: action, id: undefined, rowData: undefined }; if (this.popOverReturnOption === "id") { event.id = rowData[this.dataSourcePK]; } if (this.popOverReturnOption === "rowData") { event.rowData = rowData; } if (action != null) { this.popOver.emit(event); } return; } scrollHandler(event) { if (this.pageable) { this.scroll.emit(event); } } imageClickHandler(photo) { this.imageEnlarge.emit(photo); } tooltipHoverHandler(event, rowIndex) { let objEvent = { success: event, rowIndex: rowIndex, data: this.dataSource[rowIndex] }; this.tooltipHover.emit(objEvent); } modalHandler(row, colField) { if (this.columnsDefinition[colField].disabled) { return; } this.modalClickHandler.emit(row); } iconClickedHandler(row, colField) { if (this.evaluateExpression(this.columnsDefinition[colField].disabled, row) || this.checkDisabledRow(row)) { return; } let iconColumn = this.columns.toArray().find(x => x.field == colField); if (iconColumn) { iconColumn.iconClickHandler.emit(row); } } cellActionHandler(row, colField) { if (eval(this.columnsDefinition[colField].disabled) || this.checkDisabledRow(row)) { return; } let column = this.columns.toArray().find(x => x.field == colField); if (column && column.action /*.observers && column.action.observers.length > 0*/) { column.action.emit(row); } } redirectMap(event, row) { if (this.checkDisabledRow(row)) { return; } let eventObject = { event: event, row: row }; this.mapHandler.emit(eventObject); } /* Handlers */ /*-------------------------------------------------------*/ changePageSize(event) { localStorage.setItem(gridSettings.pageSize, JSON.stringify(event)); window.location.reload(); return; } selectHandler(event, rowIndex) { setTimeout(() => { this.dataSource[rowIndex].isSelected = event; this.allSelected = this.dataSource.every(x => x.isSelected); this.checkedRows = this.dataSource.filter(x => x.isSelected); this.checkedRowsChange.emit(this.checkedRows); }); } selectAllHandler() { setTimeout(() => { this.dataSource.filter(x => (x.isSelected != this.allSelected && !this.checkDisabledRow(x) && !x.isDisabled)).forEach(x => { x.isSelected = this.allSelected; }); this.checkedRows = this.dataSource.filter(x => x.isSelected); this.checkedRowsChange.emit(this.checkedRows); }); } customTemplateActionHandler(action, id) { let event = { action: action, id: id }; if (action) { this.customDetailsAction.emit(event); } } isDecimal(value) { return !isNaN(value); } valueChanged(event, popup) { this.showDateRangePopup = false; popup.show = false; this.filtersChange.next(event); } clearDate(event, popup) { this.showDateRangePopup = false; popup.show = false; if (this.filters["startDate"] || this.filters["endDate"]) { this.filters["startDate"] = null; this.filters["endDate"] = null; } this.filtersChange.next(event); } activateCalendar(popup) { this.showDateRangePopup = true; popup.show = true; } openPopup(event) { if (!this.showDateRangePopup) { event.preventDefault(); } } closePopup(event) { if (this.showDateRangePopup) { event.preventDefault(); } } } CustomGridComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CustomGridComponent, deps: [{ token: i0.Renderer2 }, { token: i1.Router }, { token: i2.NotificationService }, { token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); CustomGridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: CustomGridComponent, selector: "custom-grid", inputs: { dataSource: "dataSource", dataSourcePK: "dataSourcePK", filtersDataType: "filtersDataType", rowHasDetails: "rowHasDetails", hasGridDetails: "hasGridDetails", hasFilters: "hasFilters", rowDetails: "rowDetails", disabledRows: "disabledRows", disabledReasons: "disabledReasons", gridDetails: "gridDetails", gridDetailsOrder: "gridDetailsOrder", width: "width", height: "height", overflowX: "overflowX", overflowY: "overflowY", rowTemplate: "rowTemplate", rowClass: "rowClass", noRecordsInnerHTML: "noRecordsInnerHTML", popoverConfiguration: "popoverConfiguration", noDataImg: "noDataImg", detailsLoadMethod: "detailsLoadMethod", rowCheckable: "rowCheckable", checkedRows: "checkedRows", customDetails: "customDetails", detailsTitle: "detailsTitle", toggleDetailsText: "toggleDetailsText", translationKey: "translationKey", gridDetailsTrasnlationKey: "gridDetailsTrasnlationKey", hasNumbering: "hasNumbering", hasStockInputIcon: "hasStockInputIcon", dataLoaded: "dataLoaded", displayedDetails: "displayedDetails", popOverReturnOption: "popOverReturnOption", filterable: "filterable", filters: "filters", filterMethod: "filterMethod", pageable: "pageable", hasPageSizeSelection: "hasPageSizeSelection" }, outputs: { triggerFilters: "triggerFilters", popOver: "popOver", scroll: "scroll", detailsToggled: "detailsToggled", toggleChanged: "toggleChanged", imageEnlarge: "imageEnlarge", customDetailsAction: "customDetailsAction", tooltipHover: "tooltipHover", modalClickHandler: "modalClickHandler", mapHandler: "mapHandler", checkedRowsChange: "checkedRowsChange" }, queries: [{ propertyName: "columns", predicate: CustomGridColumnComponent }], viewQueries: [{ propertyName: "elementRef", first: true, predicate: ["customgrid"], descendants: true, read: ElementRef }, { propertyName: "chart", first: true, predicate: ["chart"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"custom-grid-wrap\" [ngStyle]=\"{'width':width,'height':height,'overflow-x': overflowX, 'overflow-y': overflowY}\" #customgrid>\n <ng-container *ngIf=\"(hasFilters || !norecords)\">\n <div class=\"custom-grid-table\" [ngStyle]=\"{'width':width}\">\n <div class=\"custom-grid-thead\">\n <div class=\"custom-grid-thead-tr header-border-custom-grid\">\n <div class=\"custom-grid-thead-cell cell-disabled\"></div> <!-- disabled row cell -->\n <div *ngIf=\"rowCheckable\" class=\"custom-grid-thead-cell cell-checkbox cell-fixed\"> <!-- row cell checkbox-->\n <input type=\"checkbox\"\n class=\"k-checkbox custom-grid-checkbox\" \n [(ngModel)]=\"allSelected\" \n (ngModelChange)=\"selectAllHandler()\"\n [disabled]=\"dataSourceColumns != null && dataSourceColumns.length == 0\">\n </div>\n <div *ngIf=\"hasNumbering\" class=\"custom-grid-thead-cell cell-numbering cell-fixed\"> <!-- row cell numbering-->\n {{'customGrid.numbering' | translate}}\n </div>\n <!-- row cells data-->\n <div *ngFor=\"let col of dataSourceColumns; let colIndex = index\"\n class=\"custom-grid-thead-cell cell-thead-filter {{columnsDefinition[col.field].columnClasses}}\"\n [hidden]=\"!columnsDefinition[col.field].props.rendered\"\n [ngClass]=\"{\n 'cell-empty': !col.title, 'cell-data': col.title,\n 'cell-date': !datasourcesDef[col.field] && columnsDefinition[col.field].columnType == columnTypes.date || columnsDefinition[col.field].columnType == columnTypes.daterange\n }\"\n >\n <a class=\"table-header-title-custom-grid a-header-custom-grid\" *ngIf=\"col.title\">\n {{ col.title | translate }}\n </a>\n </div>\n <div *ngIf=\"popoverConfiguration != null\" class=\"custom-grid-thead-cell cell-popover cell-fixed\"></div> <!-- disabled row cell popover -->\n </div> <!-- END custom-grid-thead-tr -->\n <div class=\"custom-grid-thead-tr custom-grid-thead-filters\">\n <div class=\"custom-grid-thead-cell cell-disabled\"></div> <!-- disabled row cell -->\n <div *ngIf=\"rowCheckable\" class=\"custom-grid-thead-cell cell-checkbox cell-fixed\"></div> <!-- disabled row cell checkbox -->\n <div *ngIf=\"hasNumbering\" class=\"custom-grid-thead-cell cell-numbering cell-fixed\"></div> <!-- disabled row cell numbering -->\n <!-- row cells data-->\n <div class=\"custom-grid-thead-cell cell-thead-filter {{columnsDefinition[col.field].columnClasses}}\" \n *ngFor=\"let col of dataSourceColumns ; let colIndex = index\"\n [ngClass]=\"{\n 'cell-date': !datasourcesDef[col.field] && columnsDefinition[col.field].columnType == columnTypes.date || columnsDefinition[col.field].columnType == columnTypes.daterange,\n 'cell-empty': !columnsDefinition[col.field].hasFilter,\n 'cell-data': datasourcesDef[col.field] || (!datasourcesDef[col.field] && columnsDefinition[col.field].hasFilter),\n 'cell-dropdown': datasourcesDef[col.field]\n }\"\n >\n \n <ng-container *ngIf=\"datasourcesDef[col.field]; else notDropdown\">\n <div class=\"custom-grid-filter-container custom-grid-combobox\" *ngIf=\"columnsDefinition[col.field].props.rendered\">\n <kendo-combobox placeholder=\"{{'common.actions.filter' | translate}}\"\n [data]=\"datasourcesDef[col.field]\"\n [(ngModel)]=\"filters[col.filterKey]\" \n (ngModelChange)=\"filtersChange.next($event)\"\n valueField=\"id\"\n textField=\"name\"\n [valuePrimitive]=\"true\">\n </kendo-combobox>\n </div>\n </ng-container>\n <ng-template #notDropdown>\n <ng-container [ngSwitch]=\"columnsDefinition[col.field].columnType\">\n <ng-container *ngIf=\"columnsDefinition[col.field].hasFilter\">\n <ng-container *ngSwitchDefault>\n <div class=\"custom-grid-filter-container\" *ngIf=\"columnsDefinition[col.field].props.rendered\">\n <i class=\"icon icon-search wa-icon wa-icon-search\"></i>\n <input type=\"text\" placeholder=\"{{'common.actions.filter' | translate}}\"\n class=\"filter-header-box-custom-grid\" [(ngModel)]=\"filters[col.filterKey]\" (ngModelChange)=\"filtersChange.next($event)\">\n </div>\n </ng-container>\n \n <ng-container *ngSwitchCase=\"columnTypes.text\">\n <div class=\"custom-grid-filter-container\" *ngIf=\"columnsDefinition[col.field].props.rendered\">\n <i class=\"icon icon-search wa-icon wa-icon-search\"></i>\n <input type=\"text\" placeholder=\"{{'common.actions.filter' | translate}}\"\n class=\"filter-header-box-custom-grid\" [(ngModel)]=\"filters[col.filterKey]\" (ngModelChange)=\"filtersChange.next($event)\">\n </div>\n </ng-container>\n \n <ng-container *ngSwitchCase=\"columnTypes.date\">\n <kendo-datepicker class=\"custom-grid-filter-container kendo-datepicker-placeholder\" [format]=\"'d'\" [(ngModel)]=\"filters[col.filterKey]\"\n (ngModelChange)=\"filtersChange.next($event)\" *ngIf=\"columnsDefinition[col.field].props.rendered\">\n <kendo-datepicker-messages today=\"{{ 'calendar.today' | translate }}\"\n toggle=\"{{ 'calendar.toggle' | translate }}\"></kendo-datepicker-messages>\n </kendo-datepicker>\n </ng-container>\n \n <ng-container *ngSwitchCase=\"columnTypes.daterange\">\n <kendo-daterange class=\"custom-grid-filter-container custom-grid-date-range\" *ngIf=\"columnsDefinition[col.field].props.rendered\">\n <div class=\"custom-grid-date-range-anchor d-flex align-items-center\" #anchor (click)=\"activateCalendar(customGridDateRangePopup)\">\n <label class=\"custom-grid-date-range-label d-flex align-items-center\">\n <kendo-dateinput kendoDateRangeStartInput\n [(value)]=\"filters['startDate']\" \n placeholder=\"{{ 'customGrid.startDate' | translate }}\"\n (valueChange)=\"filters['endDate'] = null\"\n class=\"daterange-dateinput\">\n </kendo-dateinput>\n </label>\n <label class=\"custom-grid-date-range-label d-flex align-items-center\">\n <kendo-dateinput kendoDateRangeEndInput\n [(value)]=\"filters['endDate']\" \n placeholder=\"{{ 'customGrid.endDate' | translate }}\"\n class=\"daterange-dateinput\">\n </kendo-dateinput>\n <span class=\"k-icon k-i-calendar\"></span>\n </label>\n </div>\n <kendo-daterange-popup #customGridDateRangePopup (open)=\"openPopup($event)\" (close)=\"closePopup($event)\"\n [anchor]=\"anchor\" \n [anchorAlign]=\"{ horizontal: 'center', vertical: 'bottom'}\"\n [popupAlign]=\"{ horizontal: 'center', vertical: 'top' }\"\n >\n <ng-template kendoDateRangePopupTemplate [ngIf]=\"true\">\n <kendo-multiviewcalendar kendoDateRangeSelection>\n </kendo-multiviewcalendar>\n <div class=\"custom-grid-filter-btn-section\">\n <button class=\"custom-grid-clear-daterange\" \n (click)=\"clearDate($event, customGridDateRangePopup)\">\n {{'common.actions.clear' | translate}}\n </button>\n <button class=\"custom-grid-filter-daterange\" \n (click)=\"valueChanged($event, customGridDateRangePopup)\">\n {{'common.actions.filter' | translate}}\n </button>\n </div> \n </ng-template>\n </kendo-daterange-popup>\n </kendo-daterange>\n </ng-container>\n \n <ng-container *ngSwitchCase=\"columnTypes.textnumber\">\n <div class=\"custom-grid-filter-container\" *ngIf=\"columnsDefinition[col.field].props.rendered\">\n <i class=\"icon icon-search wa-icon wa-icon-search\"></i>\n <input type=\"number\" min=\"0\" zipcodedirective placeholder=\"{{'common.actions.filter' | translate}}\"\n class=\"filter-header-box-custom-grid\" [(ngModel)]=\"filters[col.filterKey]\" (ngModelChange)=\"filtersChange.next($event)\">\n </div>\n </ng-container>\n \n </ng-container>\n </ng-container>\n </ng-template>\n </div>\n <div *ngIf=\"popoverConfiguration != null\" class=\"custom-grid-thead-cell cell-popover cell-fixed\"></div> <!-- disabled row cell popover -->\n </div> <!-- END custom-grid-thead-tr -->\n </div> <!-- END custom-grid-thead -->\n <div class=\"custom-grid-tbody\" *ngIf=\"!norecords\">\n <ng-container *ngFor=\"let row of dataSource; let rowIndex = index\">\n <ng-container *ngIf=\"row\">\n <ng-container *ngIf=\"rowTemplate; else defaultRowTemplate\">\n <ng-container *ngFor=\"let col of dataSourceColumns; let colIndex = index\">\n <div [innerHtml]=\"rowTemplate | sanitizeHtml\"></div>\n </ng-container>\n </ng-container>\n\n <!-- custom-grid-tbody-tr row data-->\n <ng-template #defaultRowTemplate>\n <div class=\"custom-grid-tbody-tr row-box-custom-grid {{selectRowClass(row)}}\"\n [ngClass]=\"{'custom-grid-disabled-row': checkDisabledRow(row), 'row-has-details': rowHasDetails}\">\n <div *ngIf=\"rowCheckable\" class=\"custom-grid-tbody-cell cell-checkbox cell-fixed\"> <!-- row cell checkbox-->\n <input type=\"checkbox\" \n class=\"k-checkbox custom-grid-checkbox\" \n [(ngModel)]=\"row.isSelected\" \n (ngModelChange)=\"selectHandler($event, rowIndex)\" \n [disabled]=\"checkDisabledCheckboxRow(row)\"\n >\n </div>\n <div class=\"custom-grid-tbody-cell cell-disabled\"> <!-- row cell disabled -->\n <ng-container *ngIf=\"checkDisabledRow(row)\">\n <i class=\"icon icon-warning-circle wa-icon wa-icon-warning-circle tooltip-trigger\"\n [ngbTooltip]=\"reasonDisabled\" placement=\"right\"></i>\n <ng-template #reasonDisabled>\n <div class=\"tooltip-container\">\n <ng-container *ngFor=\"let reason of disabledReasons; let reasonIndex = index\">\n <div class=\"tooltip-title\">\n {{reason.title | translate}}\n </div>\n <div class=\"tooltip-content\">\n {{reason.description | translate}}\n </div>\n </ng-container>\n </div>\n </ng-template>\n </ng-container>\n </div>\n <div *ngIf=\"hasNumbering\" class=\"custom-grid-tbody-cell cell-numbering cell-fixed\"> <!-- row cell numbering-->\n {{rowIndex + 1}}.\n </div>\n <!-- row cells data-->\n <ng-container *ngFor=\"let col of dataSourceColumns; let colIndex = index\">\n <ng-container *ngIf=\"!columnsDefinition[col.field].redirectLink; else linkColumn\">\n <ng-container *ngIf=\"columnsDefinition[col.field].colTemplate; else withoutTemplate\">\n <div class=\"custom-grid-tbody-cell cell-data {{columnsDefinition[col.field].columnClasses}}\">\n <div [innerHtml]=\"generateDynamicHtml(columnsDefinition[col.field].colTemplate, row, columnsDefinition[col.field].stateClasses)\"\n class=\"grid-colTemplate-container\">\n </div>\n </div>\n </ng-container>\n\n <ng-template #withoutTemplate>\n <ng-container [ngSwitch]=\"columnsDefinition[col.field].columnType\">\n <ng-container *ngSwitchDefault>\n <div class=\"custom-grid-tbody-cell cell-data {{columnsDefinition[col.field].columnClasses}}\"\n [ngClass]=\"{\n 'custom-grid-disabled-col': evaluateExpression(columnsDefinition[col.field].disabled, row)\n }\"\n (click)=\"cellActionHandler(row, col.field)\"\n *ngIf=\"columnsDefinition[col.field].props.rendered\">\n <span [ngClass]=\"selectClass(columnsDefinition[col.field].stateClasses,row)\"\n *ngIf=\"checkHiddenCell(row, columnsDefinition[col.field].hiddenContent)\">\n {{isNotEmpty(row[col.field]) ? row[col.field] : (columnsDefinition[col.field].missingText | translate)}}\n </span>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"columnTypes.text || columnTypes.textnumber\">\n <div class=\"custom-grid-tbody-cell cell-data cell-text {{columnsDefinition[col.field].columnClasses}}\"\n [ngClass]=\"{\n 'custom-grid-disabled-col': evaluateExpression(columnsDefinition[col.field].disabled, row),\n 'position-relative': row[col.highlightedAnchorKey]\n }\"\n (click)=\"cellActionHandler(row, col.field)\"\n *ngIf=\"columnsDefinition[col.field].props.rendered\">\n <div [class.div-container-highlight]=\"row[col.highlightedAnchorKey]\">\n <div [ngClass]=\"selectClass(columnsDefinition[col.field].stateClasses,row)\"\n [ngStyle]=\"{'text-align': columnsDefinition[col.field].textAlign}\"\n *ngIf=\"checkHiddenCell(row, columnsDefinition[col.field].hiddenContent)\">\n {{isNotEmpty(row[col.field]) ? row[col.field] : (columnsDefinition[col.field].missingText | translate)}}\n </div>\n </div>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"columnTypes.number\">\n <div class=\"custom-grid-tbody-cell cell-data cell-number {{columnsDefinition[col.field].columnClasses}}\"\n [ngClass]=\"{\n 'custom-grid-disabled-col': evaluateExpression(columnsDefinition[col.field].disabled, row)\n }\"\n (click)=\"cellActionHandler(row, col.field)\"\n *ngIf=\"columnsDefinition[col.field].props.rendered\">\n <span [ngClass]=\"selectClass(columnsDefinition[col.field].stateClasses,row)\"\n [ngStyle]=\"{'text-align': columnsDefinition[col.field].textAlign}\"\n *ngIf=\"checkHiddenCell(row, columnsDefinition[col.field].hiddenContent)\">\n {{isNotEmpty(row[col.field]) ? (row[col.field] | number : '1.2-2') : (columnsDefinition[col.field].missingText | translate)}}\n </span>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"columnTypes.date\">\n <div class=\"custom-grid-tbody-cell cell-data cell-date {{columnsDefinition[col.field].columnClasses}}\"\n [ngClass]=\"{\n 'custom-grid-disabled-col': evaluateExpression(columnsDefinition[col.field].disabled, row)\n }\"\n (click)=\"cellActionHandler(row, col.field)\"\n *ngIf=\"columnsDefinition[col.field].props.rendered\">\n <span [ngClass]=\"selectClass(columnsDefinition[col.field].stateClasses,row)\"\n [ngStyle]=\"{'text-align': columnsDefinition[col.field].textAlign}\"\n *ngIf=\"checkHiddenCell(row, columnsDefinition[col.field].hiddenContent)\">\n {{isNotEmpty(row[col.field]) ? formatDate(row[col.field]) : (columnsDefinition[col.field].missingText | translate)}}\n </span>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"columnTypes.daterange\">\n <div class=\"custom-grid-tbody-cell cell-data cell-daterange {{columnsDefinition[col.field].columnClasses}}\"\n [ngClass]=\"{\n 'custom-grid-disabled-col': evaluateExpression(columnsDefinition[col.field].disabled, row)\n }\"\n (click)=\"cellActionHandler(row, col.field)\"\n *ngIf=\"columnsDefinition[col.field].props.rendered\">\n <span [ngClass]=\"selectClass(columnsDefinition[col.field].stateClasses,row)\"\n [ngStyle]=\"{'text-align': columnsDefinition[col.field].textAlign}\"\n *ngIf=\"checkHiddenCell(row, columnsDefinition[col.field].hiddenContent)\">\n {{isNotEmpty(row[\"startDate\"]) && isNotEmpty(row[\"endDate\"]) ? \n formatDate(row[\"startDate\"]) + ' - ' + formatDate(row[\"endDate\"]) :\n (columnsDefinition[col.field].missingText | translate)}}\n </span>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"columnTypes.switch\">\n <div class=\"custom-grid-tbody-cell cell-data cell-switch {{columnsDefinition[col.field].columnClasses}}\"\n *ngIf=\"columnsDefinition[col.field].props.rendered\"\n >\n <ng-container *ngIf=\"checkHiddenCell(row, columnsDefinition[col.field].hiddenContent)\">\n <kendo-switch [(ngModel)]=\"row.supplierConfirmed\"\n name=\"isActive_{{rowIndex}}_{{colIndex}}\"\n (valueChange)=\"toggleValueChange(row[dataSourcePK])\"\n id=\"isActive_{{rowIndex}}_{{colIndex}}\" class=\"toggle\" \n [onLabel]=\"' '\" [offLabel]=\"' '\" [disabled]=\"disabledSwitch(row,columnsDefinition[col.field].disabled)\">\n </kendo-switch>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"columnTypes.list\">\n <div class=\"custom-grid-tbody-cell cell-data cell-list {{columnsDefinition[col.field].columnClasses}}\"\n [ngClass]=\"{\n 'custom-grid-disabled-col': evaluateExpression(columnsDefinition[col.field].disabled, row)\n }\"\n *ngIf=\"columnsDefinition[col.field].props.rendered\"\n >\n <div class=\"row\">\n <div [ngClass]=\"columnsDefinition[col.field].tooltipList ? 'col-md-9' : 'col-md-12'\">\n <p *ngFor=\"let listItem of row[col.field]; let indexListItem = index\"\n class=\"mb-0\"\n [ngStyle]=\"{'text-align': columnsDefinition[col.field].textAlign}\">\n <ng-container *ngFor=\"let objProperty of columnsDefinition[col.field].displayedItems; let indexObjProp = index\">\n {{ objProperty.type == \"number\" ? (listItem[objProperty.item] | number : '1.2-2') : listItem[objProperty.item] }}\n </ng-container>\n </p>\n </div>\n\n <div *ngIf=\"row[col.field].length > 0 && columnsDefinition[col.field].tooltipList\" class=\"col-md-3\">\n <div (mouseenter)=\"tooltipHoverHandler($event, rowIndex)\">\n <i class=\"icon icon-info-circle wa-icon wa-icon-info-circle\"\n [ngbTooltip]=\"stocks\" placement=\"top\"></i>\n </div>\n </div>\n </div>\n <!-- refactor list dinamic -->\n </div>\n\n <ng-template #stocks>\n <div class=\"d-flex\">\n <div class=\"tooltip-container\">\n <span class=\"tooltipItem-title\">{{'customGrid.tooltipTitle' | translate}}</span><br>\n <ng-container *ngFor=\"let ttItem of row.farmStock; let tooltipItem = index\">\n <div class=\"\">\n