import {path} from '../../environments/path'; import {AgGridLocale} from '../lang/ag-gridlocale'; import {IGridValidationErrors} from '../model/virtual/grid-validation-errors'; import {GridSelectEditorComponent} from '../grid-cellrenderer/grid-select/grid-select-editor/grid-select-editor.component'; import {GridSelectRendererComponent} from '../grid-cellrenderer/grid-select/grid-select-renderer/grid-select-renderer.component'; import {GridCheckboxRendererComponent} from '../grid-cellrenderer/grid-checkbox/grid-checkbox-renderer/grid-checkbox-renderer.component'; import {GridCheckboxEditorComponent} from '../grid-cellrenderer/grid-checkbox/grid-checkbox-editor/grid-checkbox-editor.component'; import {GridDateRendererComponent} from '../grid-cellrenderer/grid-date/grid-date-renderer/grid-date-renderer.component'; import {GridDateEditorComponent} from '../grid-cellrenderer/grid-date/grid-date-editor/grid-date-editor.component'; import {GridTextRendererComponent} from '../grid-cellrenderer/grid-text/grid-text-renderer/grid-text-renderer.component'; import {GridTextEditorComponent} from '../grid-cellrenderer/grid-text/grid-text-editor/grid-text-editor.component'; import {AgGridComponentConst} from './ag-grid-component-const'; import {GridInputRendererComponent} from '../grid-cellrenderer/grid-input/grid-input-renderer/grid-input-renderer.component'; import {GridInputEditorComponent} from '../grid-cellrenderer/grid-input/grid-input-editor/grid-input-editor.component'; import {GridBlockedRendererComponent} from '../grid-cellrenderer/grid-blocked/grid-blocked-renderer/grid-blocked-renderer.component'; import {GridBlockedEditorComponent} from '../grid-cellrenderer/grid-blocked/grid-blocked-editor/grid-blocked-editor.component'; import {Utils} from '../utils/utils'; export class AgGridComponent { static readonly MIN_HEIGHT: number = 16; public params: any; public columnDefs: any[] = []; public defaultColDef: {} = {}; public rowData: any[] = []; public rowSelection: string; public gridParamsColumnApi; public gridParamsApi; public apiAssetsPath: string; public resetSearchBtn: boolean; public localeText: {}; public frameworkComponents: {}; public bSizeColumnsToFit: boolean; public gridErrors: IGridValidationErrors[]; public errorIndex: number; public resetValueByError: boolean; public errorMessage: string; public nextAddedItemId: number; /** * Constructor */ constructor(bSizeColumnsToFit: boolean = true) { AgGridComponentConst.setGridInputError(); this.rowData = []; this.columnDefs = []; this.rowSelection = 'multiple'; this.defaultColDef = { editable: true }; this.apiAssetsPath = path.path_assets; this.frameworkComponents = {}; this.localeText = AgGridLocale.getLocale(); this.bSizeColumnsToFit = bSizeColumnsToFit; this.gridErrors = []; this.errorIndex = -1; this.resetValueByError = false; this.errorMessage = null; this.nextAddedItemId = null; this.frameworkComponents = { gridSelectEditor: GridSelectEditorComponent, gridSelectRenderer: GridSelectRendererComponent, gridCheckboxRenderer: GridCheckboxRendererComponent, gridCheckboxEditor: GridCheckboxEditorComponent, gridDateRenderer: GridDateRendererComponent, gridDateEditor: GridDateEditorComponent, gridInputRenderer: GridInputRendererComponent, gridInputEditor: GridInputEditorComponent, gridTextRenderer: GridTextRendererComponent, gridTextEditor: GridTextEditorComponent, gridBlockedRenderer: GridBlockedRendererComponent, gridBlockedEditor: GridBlockedEditorComponent }; } /** * Callback on grid ready */ public onGridReady(params): void { this.params = params; this.gridParamsColumnApi = params.columnApi; this.gridParamsApi = params.api; // Set for cadasters if (!this.bSizeColumnsToFit) { const allColumnIds = []; this.gridParamsColumnApi.getAllColumns().forEach((column) => { allColumnIds.push(column.colId); }); this.gridParamsColumnApi.autoSizeColumns(allColumnIds); } } /** * On row clicked */ public onRowClicked(e): void { // Reset error message AgGridComponentConst.setGridInputError(); this.errorMessage = null; } /** * On cell editing stopped */ public onCellEditingStopped(e): void { if (null !== AgGridComponentConst.gridInputError) { this.errorMessage = AgGridComponentConst.gridInputError; e.api.ensureIndexVisible(e.rowIndex, 'middle'); e.api.ensureColumnVisible(e.colDef.field.toString()); } else { this.errorMessage = null; } } /** * Sizes columns to fit */ public onFirstDataRendered(params: any): void { // Set for info components if (this.bSizeColumnsToFit) { params.api.sizeColumnsToFit(); } } /** * Resizes grid */ public gridSizeChanged(params: any): void { if (undefined !== this.gridParamsApi) { this.gridParamsApi.sizeColumnsToFit(); } } /** * Search Form */ public searchFormSubmit(params: any): void { if (params.target.value !== '') { this.resetSearchBtn = true; this.gridParamsApi.setQuickFilter(params.target.value); } else { this.resetSearchBtn = false; this.gridParamsApi.setQuickFilter(null); } } /** * Reset search input */ public resetSearch(e: any): void { e.originalTarget[0].value = ''; this.resetSearchBtn = false; this.gridParamsApi.setQuickFilter(null); } /** * Stop editing state */ public stopEditing(): void { this.params.api.stopEditing(); } /** * Configures scrollToService - https://www.npmjs.com/package/@nicky-lenaers/ngx-scroll-to */ public scrollTo(targetFieldName: string = null, lastFieldName: string = null): void { if (null !== targetFieldName) { if (null !== lastFieldName) { // Scroll to last field first to ensure our target field name is on left-hand side this.params.api.ensureColumnVisible(lastFieldName); } this.params.api.ensureColumnVisible(targetFieldName); } } /** * Cell renderer selector for individual cells with optional default parameters */ public cellRendererSelector(params: any): {} { return AgGridComponentConst.cellRendererSelector(params); } /** * Cell editor selector for individual cells */ public cellEditorSelector(params: any): {} { return AgGridComponentConst.cellEditorSelector(params); } /** * Validates grid */ public validateGrid(): boolean { const oldErrors: IGridValidationErrors[] = this.gridErrors; this.gridErrors = []; this.errorIndex = -1; const primaryColumns = this.params.api.columnController.primaryColumns; const errorColumn: any[] = []; const errors: IGridValidationErrors[] = []; primaryColumns.forEach((value) => { if (undefined !== value.colDef.cellEditorParams) { if (undefined !== value.colDef.cellEditorParams.mandatory && true === value.colDef.cellEditorParams.mandatory) { errorColumn.push(value.colDef.field); } } }); errorColumn.forEach((value, i) => { this.params.api.forEachNode((rowNode, index) => { if (null === rowNode.data[value] || undefined === rowNode.data[value]) { errors.push({ column: value, row: index }); } }); }); this.gridErrors = errors; if (this.gridErrors.length !== 0) { if (oldErrors.length !== this.gridErrors.length) { this.params.api.ensureIndexVisible(this.gridErrors[0].row, 'middle'); this.params.api.ensureColumnVisible(this.gridErrors[0].column); } } return this.gridErrors.length === 0; } /** * Jumps to error */ public jumpToError(direction: string): void { const errorLength: number = this.gridErrors.length - 1; // If any errors if (errorLength >= 0) { // if errorIndex is smaller or same as list of all errors if (errorLength === 0) { this.errorIndex = 0; } else { if (direction === 'next') { this.errorIndex = this.errorIndex < errorLength ? this.errorIndex + 1 : 0; } else { this.errorIndex = this.errorIndex <= 0 ? errorLength : this.errorIndex - 1; } } this.params.api.ensureIndexVisible(this.gridErrors[this.errorIndex].row, 'middle'); this.params.api.ensureColumnVisible(this.gridErrors[this.errorIndex].column); } else { // reset errorIndex if no errors this.errorIndex = -1; } } /** * Shows input error */ public showInputError(positionIndex: number, field: string, oldValue: string, type: string): void { this.resetValueByError = true; this.params.api.clearFocusedCell(); this.params.api.ensureIndexVisible(positionIndex, 'middle'); this.params.api.ensureColumnVisible(field); // Lifecycle hack setTimeout(() => { // Reset to old value this.params.api.getRowNode(positionIndex).setDataValue(field, oldValue); this.params.api.startEditingCell({ rowIndex: positionIndex, colKey: field, }); switch (type) { case 'int': this.errorMessage = 'Bitte geben Sie einen ganzzahligen Wert ein.'; break; case 'float': this.errorMessage = 'Bitte geben Sie einen dezimalen oder ganzzahligen Wert ein.'; break; } }, 10); } /** * Add row to grid and returns position index */ public addRow(item: {}): number { this.initNextAddedItemId(); const rowModel = this.gridParamsApi.rowModel; // Note: default is last row let addIndex: number = rowModel.rowsToDisplay.length + 1; rowModel.rowsToDisplay.forEach((row, i) => { if (row.selected === true) { // Note: Add index is the row after selected row addIndex = i + 1; return; } }); this.gridParamsApi.updateRowData({ add: [item], addIndex }); return addIndex; } /** * Removes selected rows */ public removeRows(): void { this.initNextAddedItemId(); const selectedRows: {}[] = this.gridParamsApi.getSelectedRows(); this.gridParamsApi.updateRowData({remove: selectedRows}); } /** * Gets next row position */ public getNextRowPosition(): number { return this.gridParamsApi.rowModel.length + 1; } /** * inits next dummy id for next added entry, if necessary */ private initNextAddedItemId(): void { if (this.nextAddedItemId === null) { this.nextAddedItemId = (this.rowData.length + 1) * -1; } } /** * Returns dummy id for added entry */ public getNextAddedItemId(): number { this.initNextAddedItemId(); const res: number = this.nextAddedItemId; this.nextAddedItemId--; return res; } /** * column resize event */ public onColumnResized(event): void { if (event.finished !== false) { event.api.setHeaderHeight(AgGridComponent.MIN_HEIGHT); const headerCells = Array.from(document.querySelectorAll('.content .ag-header-cell-label')); let minHeight: number = AgGridComponent.MIN_HEIGHT; headerCells.forEach(cell => { minHeight = Math.max(minHeight, cell.scrollHeight); }); // set header height to calculated height + padding (top: 8px, bottom: 8px) event.api.setHeaderHeight(minHeight + 16); } if (event.finished) { this.gridParamsApi.resetRowHeights(); } } /** * Renders colored dot */ public dotRenderer(params): string { return ''; } /** * Renders email address */ public emailRenderer(params): string { return null !== params.value ? '' + params.value + '' : ''; } /** * Renders phone number */ public phoneRenderer(params): string { return null !== params.value ? '' + params.value + '' : ''; } /** * Renders phone number */ public urlRenderer(params): string { return null !== params.value ? '' + params.value + '' : ''; } /** * option renderer */ public optionRenderer(params): string { return params.data.is_option_meeting ? 'Ja' : ''; } /** * address renderer */ public addressRenderer(params): string { let address = ''; if (params.data.typeType === 'visit') { const street = params.data.street !== null ? params.data.street : ''; const streetNo = params.data.street_no !== null ? params.data.street_no : ''; const zip = params.data.zip !== null ? params.data.zip : ''; const city = params.data.city !== null ? params.data.city : ''; let br = ''; if (zip !== null || city !== null) { br = '
'; } address = street + ' ' + streetNo + ' ' + br + zip + ' ' + city; } return address; } /** * participants renderer */ public participantsRenderer(params): string { let participantNames = ''; params.data.participants.forEach((value) => { participantNames += params.data.that.appService.getConfig().vc_user_by_id[value.participant_user_id].firstname + ' ' + params.data.that.appService.getConfig().vc_user_by_id[value.participant_user_id].lastname + '
'; }); return participantNames; } /** * Time renderer */ public timeRenderer(params): string { return Utils.getDateTimeToDisplay(params.value, false, true); } /** * Date renderer */ public dateRenderer(params): string { return Utils.getDateTimeToDisplay(params.value); } /** * Datetime renderer */ public dateTimeRenderer(params): string { return Utils.getDateTimeToDisplay(params.value, true, true); } /** * Date comparator */ public dateComparator(date1, date2, callbackCheck: boolean = true) { if (date1 === null && date2 === null) { return 0; } if (date1 === null) { return -1; } if (date2 === null) { return 1; } const stamp1: number = Utils.getParsedDate(date1); const stamp2: number = Utils.getParsedDate(date2); return stamp1 < stamp2 ? 1 : stamp1 === stamp2 ? 0 : -1; } }