/// /// import {Directive, Component, ElementRef, Renderer2, Input, OnInit, AfterViewInit, Inject, EventEmitter, Output,ViewChild, Type, TemplateRef} from '@angular/core'; import {UndefinedToEmptyPipe} from "../Pipes/Pipes" import { JqGridCustomModule } from "../Interfaces/JqGridCustomModule"; import { DyCommon, } from "../../Common/Common" import { DxDataGridComponent, DxTemplateModule,DxTemplateHost } from 'devextreme-angular'; import { HttpClient } from '@angular/common/http'; // { Router } from '@angular/router'; //import CustomStore from 'devextreme/data/custom_store'; import { ModalComponent } from "./Modal"; //import { Autorender } from '../PageComponents/AutoRender'; import { Subject } from 'rxjs'; import { createStore } from "devextreme-aspnet-data-nojquery"; import { GridCustomButton } from '../Interfaces/jqgridCustom'; import CustomStore from 'devextreme/data/custom_store'; import { Router } from '@angular/router'; import * as Cookies from 'js-cookie' import * as moment from 'moment' @Component({ selector: 'dyGrid', template: `
{{totalCount}} records
` }) export class GridComponent implements OnInit, AfterViewInit { elementRef: ElementRef; declare currentTimeZoneOffset; public width; public placeholder; //private Grid: any; //private GridInitial: any; //private instanciated: boolean = false; @Input() editMode: string = "row"; private selectedView: string; @Input() columns: JQueryJqGridColumn[]; @Input("grid-views") views: UIGridView[]; @Input("objectname") objectName: string; @Input("auto-width") @Input("canUpdate") canUpdate = false; @Input("canAdd") canAdd = false; @Input("canDelete") canDelete = false; autoWidth: any = false; @Input("buttons") customButtons: GridCustomButton[]; @Input("distinct") distinct: boolean = false; @Input("height") height: number; @Input("selection") selection: any = {mode:"single"}; @Input("autoHeight") autoHeight: boolean; @Input("loadoninit") loadOnInit: boolean = true; @Input("save-state") saveState: boolean = true; //@Input("multiSelect") multiSelect: boolean = false; @Input("pageSize") pageSize: number = 30; @Input() detailTemplate: TemplateRef; @Input("filters") filters: any[]; @Input("loadAll") loadAll: boolean = false; @Input("beforeInsert") beforeInsert: (value) => {}; @Input("select-all") selectAll: boolean = false; @ViewChild("gridContainer", {static:true}) grid: DxDataGridComponent; @Input() useNewDatastore = false; @ViewChild("displayModal", { static: true }) displayModal: ModalComponent; public ComponentToLoad: Type;; //@Output("onLinkComponentLoaded") onLinkComponentLoaded: EventEmitter; @Output("onLinkClicked") onLinkClicked: EventEmitter = new EventEmitter(); @Output("addNewClicked") addNewClicked: EventEmitter = new EventEmitter(); @Output("onDataLoaded") onDataLoaded: EventEmitter = new EventEmitter(); @Output("onRowUpdate") onRowUpdated: EventEmitter = new EventEmitter(); @Output("onRowDelete") onRowDeleted: EventEmitter = new EventEmitter(); @Input("onCellPrepared") onCellPrepared: (e: any) => {} = (e) => { }; @Output("onToolbarPreparing") onToolbarPreparing: EventEmitter = new EventEmitter(); @Output("onCustomButtonClicked") onCustomButtonClicked: EventEmitter = new EventEmitter(); @Input() title: string; @Input() keyField: string; public totalCount = "0"; @Output() modelChange: EventEmitter = new EventEmitter(); @Output("grid-complete") gridComplete: EventEmitter = new EventEmitter(); private _id: string; private common = new DyCommon(); public _http: HttpClient; private router: Router; @Input() set id(value) { this._id = value; } get id() { return this._id; } public selectedId: string; private cacheItem: { rows: any; records: any; page?: number; total?: any; }; private cachedRows: any; private initalLoaded: boolean = false; private initialServed: boolean = false; constructor(@Inject(ElementRef) elementRef: ElementRef, @Inject(HttpClient) _http: HttpClient, @Inject(Router) _router: Router) { this.elementRef = elementRef; this._http = _http; this.router = _router; var that = this; this.dataSource = { store: new CustomStore({ load: this.loadFunction, key:"id", onLoaded: this.contentReady, update: (key, value) => { value["id"] = key.id; if (this.onRowUpdated.observers.length == 0) { return this._http.post(`api/Objects/${this.objectName}/`, value).toPromise(); } else { var p = new Promise((res, rej) => { this.onRowUpdated.emit({ key: key, value: value }); res(); }); return p; } }, remove: (key) => { if (this.onRowDeleted.observers.length == 0) { return this._http.delete(`api/Objects/${this.objectName}/${key.id}`).toPromise(); } else { var p = new Promise((res, rej) => { this.onRowDeleted.emit({ key: key }); res(); }); return p; } } , insert: (value) => { //value["id"] = key.id; if (this.beforeInsert != undefined) { this.beforeInsert(value); } return this._http.post(`api/Objects/${this.objectName}/`, value).toPromise(); }, }); } } private ngUnsubscribe: Subject = new Subject(); ngOnDestroy(): any { this.ngUnsubscribe.next(); this.ngUnsubscribe.complete(); } get url() {return '/api/Grid/' + this.objectName; } public loadFunction = (loadOptions: DevExpress.data.LoadOptions) => { var that = this; //console.log(loadOptions); //var d = $.Deferred(); var itemsToTake = loadOptions.take; if (that.initalLoaded == false) { itemsToTake = itemsToTake * 2; } if (loadOptions.skip == undefined && loadOptions.take == undefined) { loadOptions.skip = 0; itemsToTake = 1000; } var postData = { skip: loadOptions.skip, take: itemsToTake, sort: loadOptions.sort, filters: loadOptions.filter, columns: that.getColumnNames(), requireTotalCount: loadOptions.requireTotalCount, //totalSummary: loadOptions, distinct:this.distinct, group: loadOptions.group, //groupSummary: loadOptions.groupSummary } if (postData.filters == undefined) { var colFilters = that.checkColumnFilters(); if (colFilters.length > 0) { postData.filters = colFilters; } } if (that.filters != undefined && that.filters.length > 0) { if (postData.filters == undefined) { postData.filters = that.filters; } else { var temp = [] temp.push(postData.filters); temp.push("and") temp.push(that.filters); postData.filters = temp; } } //if (postData.filters.length == 0) { // postData.filters = undefined //} if (that.initalLoaded == true && that.initialServed == false) { that.initialServed = true; var p = new Promise((res, rej) => { //console.log("found cached data") var data = { items: that.cacheItem.rows, data: that.cacheItem.rows, totalCount: that.cacheItem.records } //console.log(data); //this.onDataLoaded.next (data); res(data); }); return p; } return that._http.post('/api/Grid/' + that.objectName, postData) .toPromise() .then(response => { ////console.log(response); var json = response; that.totalCount = json.records; if (that.initalLoaded == false && that.pageSize < json.total) { var NewRows = json.rows.splice(-loadOptions.take, loadOptions.take) that.cacheItem = { page: 1, records: json.records, total: json.total, rows: NewRows }; that.initalLoaded = true; } var retItem = { items: json.rows, data: json.rows, totalCount: json.records } that.onDataLoaded.emit(retItem); return retItem; }) .catch(error => { return {} //throw 'Data Loading Error' }); } public dataSource: any = {}; public hideColumns = () => { //return false; var hide = window.innerWidth < 620; return hide; } public contentReady = (e) => { if (this.selectAll == true) { this.grid.instance.selectAll(); this.selectAll = false; } } private checkColumnFilters = ():Array => { var list = []; $.each(this.grid.columns, (index, item: DevExpress.ui.dxDataGridColumn) => { if (item.filterValue) { if (list.length != 0) { list.push('and'); } list.push([item.dataField, item.selectedFilterOperation, item.filterValue]); } }); return list; } private changedViewSelector = (e) => { var view: UIGridView; $.each(this.views, (index, value:UIGridView) => { if (value.id == e.target.value) { view = value; return false; } }) this.selectedId = view.id; this.changeView(view); return true; } public getStorageKey = () => { var storageKey = this.id + "-state-" + this.objectName; var view = this.getCurrentView(); if (view != undefined) { storageKey += view.name; } return storageKey; } public getCurrentView = () => { var view; $.each(this.views, (index, value) => { if (value.id == this.selectedId) { view = value; return false; } }) return view; } ngAfterViewInit() { this.grid.scrolling = { mode: "virtual", rowRenderingMode: "virtual",useNative:false,preloadEnabled:false }; if (this.detailTemplate != undefined) { this.grid.masterDetail = { enabled: true, template: 'template' } } if (this.views != undefined) { $.each(this.views, (index, item: UIGridView) => { if (item.id == undefined) { item.id = item.name + index; } }); } // this.grid.columnHidingEnabled = this.hideColumns(); this.grid.paging = { pageSize: this.pageSize } this.grid.stateStoring = { enabled: true, customLoad: () => { if (this.saveState == false) { return undefined; } try { var myStorage = window.localStorage; var state = JSON.parse(myStorage.getItem(this.getStorageKey())); if (new Date(state.expiration) > new Date()) { return state; } else { myStorage.removeItem(this.getStorageKey()) } } catch (e) { //console.error(e); } }, customSave: (e) => { if (this.saveState == true) { var myStorage = window.localStorage; e.expiration = new Date(new Date().getTime() + 30 * 60000); myStorage.setItem(this.getStorageKey(), JSON.stringify(e)); } }, type: "custom" } if (this.columns != undefined) { this.createGrid(); } } public createGrid = () => { } public redrawSize =() =>{ } ngOnInit() { if (this.useNewDatastore == true) { this.dataSource = createStore({ key: "id", loadUrl: `/bbapi/object/Grid/${this.objectName}` }); } if (this.views == undefined && this.columns != undefined) { var view: UIGridView = { name: "view", isDefault: true, objectName: this.objectName, columns: this.columns, } this.views = [view]; } if (this.views != undefined) { var view: UIGridView; $.each(this.views, (index, item: UIGridView) => { if (item.isDefault) { view = item; return false; } }); this.selectedId = view.id; this.changeView(view); } } public getColumnNames = ():Array => { var names = []; $.each(this.grid.columns, (index, item: DevExpress.ui.dxDataGridColumn | customDxDataGridColumn) => { if (item.dataField == '$ClientOnly$') { return true; } names.push({ name: item.dataField.replace(/_/g, "."), key: false, index: index, relateType: item.relateType }); }) return names; } public RowDataToComplexObject = (rowData) => { var retObj= {} for (var i = 0; i < this.columns.length; i++ ) { retObj[this.columns[i].name] = rowData[i]; } return retObj; } public changeViewById = (id:string) => { var view: UIGridView; $.each(this.views, (index, item: UIGridView) => { if (item.id == id) { view = item; return false; } }); this.changeView(view); } public instancOfUIGridColumn = (object: any) => { return 'id' in object; } public changeView = (view: UIGridView, clearCookies = true) => { var parent = this; this.columns = []; this.selectedView = view.id; //this.initalLoaded = false; //this.initialServed = false; //if (this.grid.selection != undefined) { //this.grid.selection.mode = view.selectionMode; if (view.selectionMode != undefined) { if (view.selectionMode == "single") { this.grid.selection = { mode: view.selectionMode }; this.grid.selection.showCheckBoxesMode = "never"; } else { this.selection = { mode: view.selectionMode }; this.grid.selection = { mode: view.selectionMode }; this.grid.selection.showCheckBoxesMode = 'always'; //this.grid.selection.showCheckBoxesMode } } //} this.grid.allowColumnResizing = true; this.grid.remoteOperations = true; if (view.objectName != undefined && this.objectName != view.objectName) { this.objectName = view.objectName.split(":")[0]; } this.grid.columnResizingMode = "nextColumn"; // //console.log("Currency Format:" + JqGridCellFormattType["ShortDate"] + JqGridCellFormattType.ShortDate) this.grid.columns = undefined; this.grid.columns = []; //console.log(view); if (view.uiGridColumns != undefined) { $.each(view.uiGridColumns, (index, item: UIGridColumn) => { if (item.label == undefined) { item.label = item.name; } //if (item.name == "Id") { // item.visible = false; //} var dest: DevExpress.ui.dxDataGridColumn|customDxDataGridColumn = { //name: item.name, visibleIndex: index, allowSorting: item.sortable, allowSearch: item.searchable, allowHeaderFiltering: item.searchable, allowFiltering: item.searchable, caption: item.label, visible: item.visible, allowHiding: item.allowHide, dataField: DyCommon.CamelCase(item.name).replace(/\./g, "_"), //sortIndex: item.defaultSort, sortOrder: item.defaultSortOrder, minWidth: 130, dataType: "string" //hidingPriority: 1 } if (item.rowFilter != undefined) { dest.filterValue = item.rowFilter.filterValue; dest.selectedFilterOperation = item.rowFilter.selectedFilterOperation; } if (item.relateType != undefined) { dest.relateType = item.relateType; } if (item.allowHide == true) { dest.hidingPriority = this.GetHidingPriority(dest); } if (item.specialFormat == "number") { dest.dataType = 'number'; } if (item.specialFormat == "Currency" || item.specialFormat == "currency") { dest.format = { type: "currency", precision: 2,currency:'usd' }; dest.dataType = 'number' //dest.cellTemplate = (container, options) => { // ////console.log(options); // var val = options.displayValue; // $(`$${options.displayValue}`).appendTo(container);; //} } var com = new DyCommon(); if (item.cellTemplate != undefined) { dest.cellTemplate = item.cellTemplate; } if (item.openWithCommonEditor) { dest.cellTemplate = (container, options) => { $(`${options.displayValue}`).click(() => { this.onLinkClicked.next({ item: item, options: options }); }).appendTo(container);; } } else if (item.linkFormat != undefined) { dest.cellTemplate = (container, options) => { if (item.openLinkInModal == true) { var text = options.text; if (text == '' || text == undefined) { text = "_"; } $(`${text} `).click(() => { //console.log(options.data); this.displayModal.IframeUrl = com.EvalExpression(item.linkFormat, options.data); this.displayModal.showdialog = true; }).appendTo(container); } else if (item.OpenWithCommonEditor) { this.onLinkClicked.next({ item: item, options: options }); } else { var text = options.text; if (text == '' || text == undefined) { text = "_"; } $(`${text}`).click(() => { this.router.navigateByUrl(com.EvalExpression(item.linkFormat, options.data)); }).appendTo(container); } } //dest.calculateCellValue = (data) => { // return `${com.EvalExpression(dest.dataField, data)}` //} } var thisvar = this; if (item.filter == undefined) { dest.allowHeaderFiltering = false; } if (item.editable != undefined) { dest.allowEditing = item.editable; } if (item.filter != undefined && item.filter.filterURL != undefined) { dest.headerFilter = { dataSource: { map: (data) => { return { text: data[DyCommon.CamelCase(item.filter.filterURLText)], value: [dest.dataField, item.filter.filterURLOPerator, data[DyCommon.CamelCase(item.filter.filterURLValue)]] }; }, store: new DevExpress.data.CustomStore({ load: function (loadOptions: DevExpress.data.LoadOptions) { var url = item.filter.filterURL; if (url.indexOf('?') > -1) { url += "&"; } else { url += "?"; } if (url.indexOf("fields") == -1) { var fields = item.filter.filterURLText; if (item.filter.filterURLText != item.filter.filterURLValue) { fields += `, ${item.filter.filterURLValue}`; } url += `fields=${fields}`; } return thisvar._http.get(url) .toPromise() .then(response => { //console.log(response); var json = response; return json; // return undefined;//{ text: "test1", value: ["OrderNumber", "contains", "1"] }; // items: [{ text: "test1", value: ["OrderNumber", "contains", "1"] }, { text: "test2", value: "test" }], // data: { items: [{ text: "test1", value: ["OrderNumber","contains","1"] }, { text: "test2", value: "test" }] }, //} }) .catch(error => { return {} //throw 'Data Loading Error' }); } }) } } } //console.log(dest); this.grid.export = { enabled: true, fileName: "Employees", allowExportSelectedData: true } dest.lookup = item.lookup; //if (item.visible === false) { // dest.visible = true; // } if (item.specialFormat != undefined) { ////console.log("formatt"); // var formatt: JqGridCellFormattType = JqGridCellFormattType[item.specialFormat]; // dest.format = formatt; switch (item.specialFormat) { case "ShortDate": dest.dataType = "date"; dest.cellTemplate = (container, options) => { var text = ""; if (options.value != undefined && options.value !='') { text= moment(options.value).utc().format("MM/DD/YYYY"); } if (item.linkFormat != undefined) { if (text == '' || text == undefined) { text = "_"; } $(`${text}`).click(() => { this.router.navigateByUrl(com.EvalExpression(item.linkFormat, options.data)); }).appendTo(container); } else { $(`${text}`).click(() => { this.onLinkClicked.next({ item: item, options: options }); }).appendTo(container); } //} //else { // //options.displayValue = new Date(); // $(`${moment(options.value.replace("T00:00:00+00:00", "")).format("MM/DD/YYYY")}`).click(( // this.onLinkClicked.next({ item: item, options: options }); // }).appendTo(container);; //} } break; case "shortDateShortTime": dest.dataType = "date"; // dest.format = item.specialFormat; dest.cellTemplate = (container, options) => { $(`${moment(options.value).format('MM/DD/YYYY h:mm A')}`).click(() => { this.onLinkClicked.next({ item: item, options: options }); }).appendTo(container);; } break; case 'Currency': dest.dataType = "number"; break; case 'Bool': dest.dataType = "boolean" dest.trueText = "Yes"; dest.falseText = "No"; break; default: // dest.dataType = "date"; dest.dataType = item.specialFormat; } } if (dest.dataType == "date" || "shortDateShortTime") { dest.allowHeaderFiltering = true; dest.headerFilter = { dataSource: [{ text: "This Week", value: [[dest.dataField, ">", moment().startOf('week').toDate()], "and", [dest.dataField, "<", moment().endOf('Week').toDate()]] }, { text: "Last Week", value: [[dest.dataField, ">", moment().subtract(1, "weeks").startOf('week').toDate()], "and", [dest.dataField, "<", moment().subtract(1, "weeks").endOf('Week').toDate()]] }, { text: "This Month", value: [[dest.dataField, ">", moment().startOf('month').toDate()], "and", [dest.dataField, "<", moment().endOf('month').toDate()]] }, { text: "Last Month", value: [[dest.dataField, ">", moment().subtract(1, "months").startOf('month').toDate()], "and", [dest.dataField, "<", moment().subtract(1, "months").endOf('month').toDate()]] }, { text: "This Year", value: [[dest.dataField, ">", moment().startOf('year').toDate()], "and", [dest.dataField, "<", moment().endOf('year').toDate()]] }, { text: "Last Year", value: [[dest.dataField, ">", moment().subtract(1, "years").startOf('year').toDate()], "and", [dest.dataField, "<", moment().subtract(1, "years").endOf('year').toDate()]] }] } if (dest.format == "shortDateShortTime") { dest.minWidth = 200; dest.cellTemplate = (container, options) => { $(`${moment(options.displayValue).format('MM/DD/YYYY h:mm A')}`).appendTo(container); } } } this.grid.columns.push(dest) }); } if (view.columns != undefined) { $.each(view.columns, (index, column) => { this.grid.columns.push(column); }) } this.updateFiltersFromView(view); if (clearCookies) { Cookies.remove(this.id + "_search"); } this.grid.filterRow = { visible: true, applyFilter: "auto" }; this.grid.headerFilter = { visible: true } if (view.uiGridFilters != undefined) { var vfg = view.uiGridFilters; if (typeof (view.uiGridFilters) === 'function') { vfg = view.uiGridFilters(); } if (vfg.length == 1) { $.each(vfg, (index, value) => { this.dataSource.filter = [value.field, value.operator, value.data]; }); } else { this.dataSource.filter = []; $.each(vfg, (index, value) => { if (index != 0 && !this.objectName.startsWith("$$SP$$")) { this.dataSource.filter.push("and"); } this.dataSource.filter.push([value.field, value.operator, value.data]); }); } } if (this.filters != undefined) { ////console.log(this.filters); //this.dataSource.filter = this.filters; } this.grid.columnChooser = true; this.grid.rowAlternationEnabled = true; //this.grid.templates //console.log("loadOnInit" + this.loadOnInit); if (this.loadOnInit == true || this.initalLoaded == true) { this.dataSource.store._key = this.keyField; this.grid.dataSource = this.dataSource; } //var alreadyExists = false; //if (this.instanciated) { // alreadyExists = true; // this.ReInitGrid(); //} //this.createGrid(); //if (alreadyExists) { // this.ReloadGird(); //} } public initDataSource = () => { this.dataSource.store._key = this.keyField; this.grid.dataSource = this.dataSource; } public GetHidingPriority = (dest: DevExpress.ui.dxDataGridColumn) => { if (dest.allowHiding == true && this.hideColumns()) { return dest.visibleIndex; } else { return undefined; } } public getHeight = () => { //return "500px"; if (this.height == undefined) { var parentHeight = $(this.elementRef.nativeElement).parent().height(); var height = $(window).height() - $("#menu").height() - $("footer").height() - 20; return height; } return this.height; } public ReInitGrid =() => { //this.GridInitial.empty(); //delete this.GridInitial[0].grid; //$(`#gbox_${this.id}_dyGrid`).empty().replaceWith(this.GridInitial); } public updateFiltersFromView = (view: UIGridView) => { this.filters = []; var parent = this; if (view.uiGridFilters != undefined) { $.each(view.uiGridFilters, (index, item: UIGridFilter) => { var dest: GridFilter = { data: item.data, field: item.field, op: item.operator, type: item.type } //parent.filters.push(dest); }) } } public getSelected = ()=> { //var ids = this.GridInitial.jqGrid('getGridParam', 'selrow'); return this.grid.instance.getSelectedRowsData(); //var ret = []; //var grid = this.GridInitial; //return grid.getRowData(ids); } public getMutipleSelected = () =>{ //var ids = this.GridInitial.jqGrid('getGridParam', "selarrrow") //var ret = []; //$.each(ids, (i, v) => { // ret.push(this.GridInitial.getRowData(v)); //}); //return ret; } private getUrl = () => { if (this.loadOnInit == true) { return this.url; } else { return undefined; } } private getDataType = () => { if (this.loadOnInit == true) { return "json"; } else { return "local"; } } public onToolbarPreparing = (e) => { //console.log("toolbar preparing"); // this.onToolbarPreparing.emit(e); e.toolbarOptions.items.unshift({ location: 'after', widget: 'dxButton', options: { icon: 'glyphicon glyphicon-list-alt', title:"Edit Views", onClick: undefined } },{ location: 'after', template: 'totalGroupCount' }, { location: 'after', widget: 'dxButton', options: { hint: "refresh", icon: 'refresh', onClick: () => { this.grid.instance.refresh()} } }, { location: 'before', template: 'totalRecords' }); var view: UIGridView = this.getCurrentView(); if (view.addNewURL != undefined || this.canAdd == true || this.addNewClicked.observers.length > 0) { var that = this; e.toolbarOptions.items.unshift({ location: 'before', widget: 'dxButton', options: { icon: 'glyphicon glyphicon-plus', title: "Add New", onClick: () => { if (that.addNewClicked.observers.length > 0) { that.addNewClicked.emit(); } else if (this.canAdd == true) { this.grid.instance.addRow(); } else { this.router.navigateByUrl(view.addNewURL); } } } }); } if (view.buttons != undefined) { var that = this; view.buttons.forEach((button) => { e.toolbarOptions.items.unshift({ location: 'before', widget: 'dxButton', options: { icon: button.icon, title: button.title, text: button.text, onClick: () => { that.onCustomButtonClicked.emit(button.title) } } }); }) } if (this.customButtons != undefined) { $.each(this.customButtons, (index, value) => { e.toolbarOptions.items.unshift(value); }) } } public getSortName = () => { var firstVisibleName; for (var i = 0; i < this.columns.length; i++) { var col = this.columns[i]; if (col.defaultSort == true) { return col.name; } if (col.hidden != true && firstVisibleName == undefined) { firstVisibleName = col.name; } } return firstVisibleName; } public getSortOrder = () => { var firstVisibleName; for (var i = 0; i < this.columns.length; i++) { var col = this.columns[i]; if (col.defaultSort == true) { return col.defaultSortOrder; } } return firstVisibleName; } public ReloadGird = () => { this.grid.instance.refresh() } }