@cauca-911/datagrid
Version:
Run `npm install @cauca-911/datagrid --save` to add this library to your project
1 lines • 159 kB
Source Map (JSON)
{"version":3,"file":"cauca-911-datagrid.mjs","sources":["../../../projects/cauca-datagrid/src/lib/data-grid/models/data-grid-row-drop-event.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/base-grid-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/components/data-grid-header/data-grid-header.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/components/data-grid-header/data-grid-header.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/models/density-enum.ts","../../../projects/cauca-datagrid/src/lib/services/preference.ts","../../../projects/cauca-datagrid/src/lib/services/preference.service.ts","../../../projects/cauca-datagrid/src/lib/data-grid/base-data-grid.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/components/button-popover/button-popover.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/components/button-popover/button-popover.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/components/data-grid-table-options/data-grid-table-options.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/components/data-grid-table-options/data-grid-table-options.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/components/data-grid-progress-spiner/data-grid-progress-spiner.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/components/data-grid-progress-spiner/data-grid-progress-spiner.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/data-grid/data-grid.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/data-grid/data-grid.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/odata-grid/odata-listing.service.ts","../../../projects/cauca-datagrid/src/lib/data-grid/odata-grid/odata-grid.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/odata-grid/odata-grid.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/columns/color-data-grid-column/color-data-grid-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/color-data-grid-column/color-data-grid-column.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/components/check-icon/check-icon.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-check-column/data-grid-check-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-check-column/data-grid-check-column.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-column/data-grid-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-column/data-grid-column.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-command-icon-column/data-grid-command-icon-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-command-icon-column/data-grid-command-icon-column.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-commands-column/data-grid-commands-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-commands-column/data-grid-commands-column.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-icon-column/data-grid-icon-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-icon-column/data-grid-icon-column.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-menu-column/data-grid-menu-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/data-grid-menu-column/data-grid-menu-column.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/components/time-label/time-label.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/components/time-label/time-label.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/columns/date-grid-column/date-grid-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/date-grid-column/date-grid-column.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/columns/sortable-data-grid-check-column/sortable-data-grid-check-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/sortable-data-grid-check-column/sortable-data-grid-check-column.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/components/column-label/column-label.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/components/column-label/column-label.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/columns/sortable-data-grid-column/sortable-data-grid-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/sortable-data-grid-column/sortable-data-grid-column.component.html","../../../projects/cauca-datagrid/src/lib/data-grid/columns/translation-grid-column/translation-grid-column.component.ts","../../../projects/cauca-datagrid/src/lib/data-grid/columns/translation-grid-column/translation-grid-column.component.html","../../../projects/cauca-datagrid/src/lib/services/mat-paginator-localization.service.ts","../../../projects/cauca-datagrid/src/lib/provide-cauca-grid.ts","../../../projects/cauca-datagrid/src/public-api.ts","../../../projects/cauca-datagrid/src/cauca-911-datagrid.ts"],"sourcesContent":["export class DataGridRowDropEvent {\n public item: unknown;\n public data: unknown[];\n public fromIndex: number;\n public toIndex: number;\n\n public constructor(data: {\n item: unknown;\n data: unknown[];\n fromIndex: number;\n toIndex: number;\n }) {\n Object.assign(this, data);\n }\n}\n","import { Component, HostBinding, Input, OnDestroy, OnInit, Optional, ViewChild, ViewEncapsulation } from '@angular/core';\r\nimport { MatCellDef, MatColumnDef, MatFooterCellDef, MatHeaderCellDef, MatTable } from '@angular/material/table';\r\n\r\n@Component({ template: '' ,\r\n encapsulation: ViewEncapsulation.None\r\n})\r\nexport abstract class BaseGridColumnComponent implements OnDestroy, OnInit {\r\n\r\n @Input() public prop = '';\r\n @Input() public showLabel = true;\r\n @Input() public label: string | undefined;\r\n @Input() public isInColumnChooser: boolean = true;\r\n @Input() public width: string = \"\";\r\n @Input() public showToolTip: boolean = false;\r\n\r\n @HostBinding('attr.ariaHidden') public ariaHidden!: true;\r\n @HostBinding('class') public classes!: 'column-template cdk-visually-hidden';\r\n\r\n @ViewChild(MatColumnDef, { static: true }) public columnDef!: MatColumnDef;\r\n @ViewChild(MatCellDef, { static: true }) public cellDef!: MatCellDef;\r\n @ViewChild(MatHeaderCellDef, { static: true }) public headerCellDef!: MatHeaderCellDef;\r\n @ViewChild(MatFooterCellDef, { static: true }) public footerCellDef!: MatFooterCellDef;\r\n\r\n public selected: boolean = true;\r\n\r\n public constructor(@Optional() public table: MatTable<unknown>) {\r\n }\r\n\r\n public ngOnInit(): void {\r\n if (this.columnDef) {\r\n if (!this.columnDef.name) {\r\n this.columnDef.name = this.prop;\r\n }\r\n this.columnDef.cell = this.cellDef;\r\n this.columnDef.headerCell = this.headerCellDef;\r\n this.columnDef.footerCell = this.footerCellDef;\r\n }\r\n }\r\n\r\n public ngOnDestroy(): void {\r\n if (this.table) {\r\n this.table.removeColumnDef(this.columnDef);\r\n }\r\n }\r\n\r\n public capitalize(value: string): string {\r\n return value.charAt(0).toUpperCase() + value.slice(1);\r\n }\r\n}\r\n","import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';\nimport { FormControl, ReactiveFormsModule } from '@angular/forms';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatInputModule } from '@angular/material/input';\nimport { IconButtonComponent, RaisedButtonComponent } from '@cauca-911/material';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { Subject, debounceTime, takeUntil } from 'rxjs';\n\n@Component({\n selector: 'cauca-data-grid-header',\n templateUrl: './data-grid-header.component.html',\n styleUrls: ['./data-grid-header.component.scss'],\n imports: [MatFormFieldModule, IconButtonComponent, RaisedButtonComponent, MatInputModule, ReactiveFormsModule, TranslateModule, MatIcon],\n})\nexport class DataGridHeaderComponent implements OnInit, OnDestroy {\n\n public filterControl: FormControl<string> = new FormControl<string>('');\n public showClearButton: boolean;\n\n @Input() public showAddButton: boolean = false;\n @Input() public showRefreshButton: boolean = false;\n @Input() public addButtonLabel: string = '';\n @Output() public filterChange: EventEmitter<string> = new EventEmitter<string>();\n @Output() public addButtonClick: EventEmitter<void> = new EventEmitter<void>();\n @Output() public refreshRequest: EventEmitter<void> = new EventEmitter<void>();\n\n protected _onDestroy = new Subject<void>();\n\n public ngOnInit(): void {\n this.filterControl.valueChanges\n .pipe(\n debounceTime(500),\n takeUntil(this._onDestroy))\n .subscribe((filter: string) => {\n this.filterChange.emit(filter);\n this.showClearButton = !!filter;\n });\n }\n\n public ngOnDestroy(): void {\n this._onDestroy.next();\n this._onDestroy.complete();\n }\n\n public onRefresh(): void {\n this.refreshRequest.emit();\n }\n\n public clearSearchValue(): void {\n this.filterControl.setValue('');\n }\n\n public onAddButtonClick(): void {\n this.addButtonClick.emit(null);\n }\n}\n","<div class=\"grid-header\">\n\n <mat-form-field appearance=\"outline\" class=\"full-width-field grid-search-box\" subscriptSizing=\"dynamic\">\n @if (showClearButton) { <cauca-icon-button matPrefix (buttonClick)=\"clearSearchValue()\" icon=\"close\" /> }\n <mat-label>{{ 'dataGrid.keywordsLabel' | translate}}</mat-label>\n <input matInput [formControl]=\"filterControl\">\n <mat-icon matSuffix>search</mat-icon>\n </mat-form-field>\n\n <ng-content select=\"[filterRow]\" ngProjectAs=\"[filterRow]\" />\n\n @if (showRefreshButton) { <cauca-icon-button (buttonClick)=\"onRefresh()\" icon=\"refresh\" class=\"grid-refresh-button\" /> }\n\n @if (showAddButton) { <cauca-raised-button icon=\"add\" color=\"primary\" [label]=\"addButtonLabel\" [translateLabel]=\"false\" class=\"grid-new-button\" (buttonClick)=\"onAddButtonClick()\" /> }\n</div>","export enum Density {\n Compact = \"compact\",\n Standard = \"standard\",\n Comfortable = \"comfortable\"\n}","import { Density } from \"../data-grid/models/density-enum\";\n\nexport class Preference {\n public gridDensity: Density;\n}\n\nexport default class GridConfiguration {\n public name: string;\n public visibleColumns: string[];\n}\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable, of } from 'rxjs';\nimport GridConfiguration, { Preference } from './preference';\nimport { Density } from '../data-grid/models/density-enum';\n\n\n@Injectable({\n providedIn: 'root'\n})\nexport class PreferenceService {\n public preference: BehaviorSubject<Preference> = new BehaviorSubject<Preference>(new Preference());\n\n public gridConfiguration: GridConfiguration[] = [];\n\n public constructor() {\n const data = localStorage.getItem('GridPreference');\n const configuration = localStorage.getItem('GridConfiguration');\n if (data) {\n this.preference.next(JSON.parse(data));\n }\n if (configuration) {\n this.gridConfiguration = JSON.parse(configuration);\n }\n }\n\n public getPreference(): Preference {\n return this.preference.value;\n }\n\n public setPreferenceDensity(density: Density) {\n const preference = this.getPreference();\n if (density === preference.gridDensity) return;\n preference.gridDensity = density;\n this.preference.next(preference);\n this.addOrUpdatePreference();\n }\n\n public addOrUpdatePreference(): void {\n localStorage.setItem('GridPreference', JSON.stringify(this.getPreference()));\n }\n\n public getPreferenceForGrid(gridName: string): Observable<GridConfiguration> {\n return of(this.getPreferenceForGridNotObservable(gridName));\n }\n\n public addOrUpdateGridPreference(gridName: string, visibleColumns: string[]): Observable<void> {\n const configuration = this.getPreferenceForGridNotObservable(gridName);\n configuration.visibleColumns = visibleColumns || [];\n localStorage.setItem('GridConfiguration', JSON.stringify(this.gridConfiguration));\n return of();\n }\n\n private getPreferenceForGridNotObservable(gridName: string): GridConfiguration {\n const configuration = this.gridConfiguration.find(g => g.name == gridName);\n if (configuration) {\n return configuration;\n }\n const newConfiguration = new GridConfiguration();\n newConfiguration.name = gridName;\n this.gridConfiguration.push(newConfiguration);\n return newConfiguration;\n }\n}","import {\r\n AfterContentInit, Component, ContentChild,\r\n ContentChildren, EventEmitter, input, Input, OnChanges, Output, QueryList, signal, SimpleChanges, ViewChild\r\n} from '@angular/core';\r\nimport { MatColumnDef, MatFooterRowDef, MatHeaderRowDef, MatNoDataRow, MatRowDef, MatTable } from '@angular/material/table';\r\nimport { MatPaginator } from '@angular/material/paginator';\r\nimport { BaseGridColumnComponent } from './columns/base-grid-column.component';\r\nimport { DataGridHeaderComponent } from './components/data-grid-header/data-grid-header.component';\r\nimport { MatSort } from '@angular/material/sort';\r\nimport { Density } from './models/density-enum';\r\nimport { Preference } from '../services/preference';\r\nimport { PreferenceService } from '../services/preference.service';\r\nimport { TranslateService } from '@ngx-translate/core';\r\n\r\n@Component({ template: '' })\r\nexport abstract class BaseDataGridComponent implements AfterContentInit, OnChanges {\r\n @Input({ required: true }) public resourceName: string;\r\n @Input() public displayedColumns: string[] = [];\r\n @Input() public showAddButton: boolean = false;\r\n @Input() public addButtonLabel: string = '';\r\n @Input() public searchableColumns: string[];\r\n @Input() public showTableOptions: boolean = false;\r\n @Input() public showColumnViewer: boolean = true;\r\n @Output() public addButtonClick: EventEmitter<void> = new EventEmitter<void>();\r\n public showPaginator = input<boolean>(false);\r\n public hidePageSize = input<boolean>(false);\r\n public showExpandButton = input<boolean>(false);\r\n public expandedElement = signal<any>(null);\r\n\r\n @ViewChild(DataGridHeaderComponent) public header!: DataGridHeaderComponent;\r\n @ViewChild(MatTable, { static: true }) public table: MatTable<unknown>;\r\n @ContentChildren(BaseGridColumnComponent) public regularColumns: QueryList<BaseGridColumnComponent>;\r\n @ContentChildren(MatColumnDef) public columnDefs: QueryList<MatColumnDef>;\r\n @ContentChild(MatHeaderRowDef) public headerRowDef: QueryList<MatHeaderRowDef>;\r\n @ContentChild(MatFooterRowDef) public footerRowDef: QueryList<MatFooterRowDef>;\r\n @ContentChildren(MatRowDef) public rowDefs: QueryList<MatRowDef<unknown>>;\r\n @ContentChild(MatNoDataRow) public noDataRow: MatNoDataRow;\r\n @ViewChild(MatPaginator) public paginator: MatPaginator;\r\n\r\n public defaultAddButtonLabel: string = '';\r\n public allDisplayedColumns = signal<string[]>([]);\r\n public preference: Preference;\r\n\r\n protected sort: MatSort = null;\r\n\r\n public get density(): typeof Density {\r\n return Density;\r\n }\r\n\r\n public constructor(translateService: TranslateService,\r\n private readonly preferenceService: PreferenceService) {\r\n this.defaultAddButtonLabel = translateService.instant('dataGrid.defaultAddButtonLabel');\r\n }\r\n\r\n public ngAfterContentInit(): void {\r\n this.setUpPaginator(this.paginator, this.showPaginator());\r\n this.setUpFilterPredicate();\r\n if (this.table && this.regularColumns && this.rowDefs && this.columnDefs) {\r\n this.applyColumns();\r\n }\r\n\r\n if (this.showTableOptions) {\r\n this.preferenceService.preference.subscribe((preference) => {\r\n this.preference = preference;\r\n });\r\n } else {\r\n this.showColumnsWhenTableOptionsIsFalse();\r\n this.preference = new Preference();\r\n }\r\n }\r\n\r\n public ngOnChanges(changes: SimpleChanges): void {\r\n this.updateDataWhenNeeded(changes);\r\n this.updateColumnsWhenNeeded(changes);\r\n }\r\n\r\n public onExpand(element: any): void {\r\n if (this.expandedElement() === element) {\r\n this.expandedElement.set(null);\r\n } else {\r\n this.expandedElement.set(element);\r\n }\r\n }\r\n\r\n public clearFilter(): void {\r\n this.header?.clearSearchValue();\r\n }\r\n\r\n public renderRows(): void {\r\n this.forceReloadFilter();\r\n this.applyColumns();\r\n this.table.renderRows();\r\n }\r\n\r\n public onDensityChanged(density: Density): void {\r\n this.preferenceService.setPreferenceDensity(density);\r\n }\r\n\r\n public abstract getData(): unknown[];\r\n protected abstract setUpFilterPredicate(): void;\r\n protected abstract setUpSort(sort: MatSort): void;\r\n protected abstract forceReloadFilter(): void;\r\n protected abstract updateDataWhenNeeded(changes: SimpleChanges): void;\r\n protected abstract showColumnsWhenTableOptionsIsFalse(): void;\r\n\r\n protected setUpPaginator(_paginator: MatPaginator, _showPaginator: boolean): void {\r\n // nothing\r\n }\r\n\r\n protected onColumnsChanged(columns: string[]): void {\r\n this.allDisplayedColumns.set([...columns]);\r\n const columnsToSave = this.removeMandatoryColumns([...columns]);\r\n this.preferenceService.addOrUpdateGridPreference(this.resourceName, columnsToSave).subscribe();\r\n }\r\n\r\n protected applyColumns(): void {\r\n this.regularColumns.forEach(dynColumn => this.table.addColumnDef(dynColumn.columnDef));\r\n this.rowDefs.forEach(rowDef => this.table.addRowDef(rowDef));\r\n this.table.setNoDataRow(this.noDataRow);\r\n this.columnDefs.forEach(columnDef => {\r\n this.table.addColumnDef(columnDef);\r\n this.sort.register({ id: columnDef.name, start: 'desc', disableClear: false });\r\n });\r\n }\r\n\r\n protected updateColumnsWhenNeeded(changes: SimpleChanges): void {\r\n if (changes.displayedColumns) {\r\n this.allDisplayedColumns.set([...this.displayedColumns]);\r\n }\r\n }\r\n\r\n private removeMandatoryColumns(columns: string[]): string[] {\r\n let index = columns.indexOf(\"\");\r\n if (index > -1) {\r\n columns.splice(index, 1);\r\n }\r\n\r\n index = columns.indexOf(\"position\");\r\n if (index > -1) {\r\n columns.splice(index, 1);\r\n }\r\n\r\n index = columns.indexOf(\"buttons\");\r\n if (index > -1) {\r\n columns.splice(index, 1);\r\n }\r\n\r\n index = columns.indexOf(\"menu\");\r\n if (index > -1) {\r\n columns.splice(index, 1);\r\n }\r\n\r\n index = columns.indexOf(\"expand\");\r\n if (index > -1) {\r\n columns.splice(index, 1);\r\n }\r\n\r\n return columns;\r\n }\r\n}\r\n","import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';\nimport { ChangeDetectionStrategy, Component, input, Input, signal } from '@angular/core';\nimport { BasicButtonComponent } from '@cauca-911/material';\n\n@Component({\n selector: 'cauca-button-popover',\n templateUrl: './button-popover.component.html',\n styleUrls: ['./button-popover.component.scss'],\n imports: [CdkConnectedOverlay, BasicButtonComponent, CdkOverlayOrigin],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ButtonPopoverComponent {\n public buttonLabel = input<string>(null);\n public buttonIcon = input<string>('');;\n public color = input<string>('primary');\n\n public isActive = signal<boolean>(false);\n\n public toggle() {\n this.isActive.set(!this.isActive());\n }\n\n public close() {\n if (this.isActive()) {\n this.isActive.set(false);\n }\n }\n}\n","<cauca-basic-button [icon]=\"buttonIcon()\" [color]=\"color()\" [label]=\"buttonLabel()\" [translateLabel]=\"false\" (buttonClick)=\"toggle()\" cdkOverlayOrigin #popoverTrigger=\"cdkOverlayOrigin\" />\n\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"popoverTrigger\"\n [cdkConnectedOverlayOpen]=\"isActive()\"\n [cdkConnectedOverlayHasBackdrop]=\"isActive()\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop-cs'\"\n (backdropClick)=\"toggle()\">\n <ng-content></ng-content>\n</ng-template>","import { Component, EventEmitter, Input, OnInit, Output, QueryList, ViewChild } from '@angular/core';\nimport { Density } from '../../models/density-enum';\nimport { BaseGridColumnComponent } from '../../columns/base-grid-column.component';\nimport { ButtonPopoverComponent } from '../button-popover/button-popover.component';\nimport { MatCardModule } from '@angular/material/card';\nimport { MatCheckboxModule } from '@angular/material/checkbox';\nimport { BasicButtonComponent, MenuItemComponent, RaisedButtonComponent, StrokedButtonComponent } from '@cauca-911/material';\nimport { PreferenceService } from '../../../services/preference.service';\nimport { FormsModule } from '@angular/forms';\nimport { MatMenuModule } from '@angular/material/menu';\nimport { TranslateModule } from '@ngx-translate/core';\n\n@Component({\n selector: 'cauca-data-grid-table-options',\n templateUrl: './data-grid-table-options.component.html',\n styleUrls: ['./data-grid-table-options.component.scss'],\n imports: [MatCardModule, ButtonPopoverComponent, MatCheckboxModule, StrokedButtonComponent, RaisedButtonComponent, BasicButtonComponent, MatMenuModule, FormsModule, TranslateModule, MenuItemComponent],\n})\nexport class DataGridTableOptionsComponent implements OnInit {\n @Input({ required: true }) public gridName: string;\n @Input() public showColumnViewer: boolean = true;\n\n @Output() public densityChanged: EventEmitter<Density> = new EventEmitter<Density>();\n\n @Input() public allColumns: QueryList<BaseGridColumnComponent> = new QueryList();\n @Output() public columnsChanged: EventEmitter<string[]> = new EventEmitter<string[]>();\n\n @ViewChild(ButtonPopoverComponent, { static: true }) public columnViewer: ButtonPopoverComponent;\n\n public columnsSearch: string = '';\n\n public get density(): typeof Density {\n return Density;\n }\n\n public get columns(): BaseGridColumnComponent[] {\n return this.allColumns.filter(c => c.prop !== 'buttons' && c.prop !== 'menu' && c.prop !== '' && c.isInColumnChooser);\n }\n\n public get currentDensityIcon(): string {\n const currentDensity = this.preferenceService.getPreference()?.gridDensity;\n if (currentDensity === Density.Compact) {\n return 'density_small';\n }\n\n if (currentDensity === Density.Comfortable) {\n return 'density_large';\n }\n\n return 'density_medium';\n }\n\n public constructor(private readonly preferenceService: PreferenceService) {\n }\n\n public ngOnInit(): void {\n this.preferenceService.getPreferenceForGrid(this.gridName).subscribe({\n next: configuration => {\n if (configuration?.visibleColumns) {\n this.selectOnlyUserColumns(configuration.visibleColumns);\n } else {\n this.selectAllColumns();\n }\n this.onColumnsChanged();\n }\n });\n }\n\n public closeColumnViewer(): void {\n if (this.columnViewer) {\n this.columnViewer.close();\n }\n }\n\n public changeDensity(newDensity: Density): void {\n this.densityChanged.emit(newDensity);\n }\n\n public onColumnsChanged(): void {\n const newColumns = this.allColumns.filter(column => column.selected);\n this.columnsChanged.emit(newColumns.map((column) => column.prop));\n }\n\n public resetColumns(): void {\n this.allColumns.forEach((column => column.selected = true));\n this.columnsChanged.emit(this.allColumns.map((column) => column.prop));\n }\n\n private selectOnlyUserColumns(configurationVisibleColumns: string[]): void {\n this.allColumns.forEach((column => {\n const index = configurationVisibleColumns.findIndex(c => c === column.prop);\n if (index === -1 && column.prop !== 'buttons' && column.prop !== 'menu' && column.prop !== '') {\n column.selected = false;\n }\n }));\n }\n\n private selectAllColumns(): void {\n this.allColumns.forEach((column => {\n column.selected = true;\n }));\n }\n}\n","<div class=\"table-options-bar\">\n <div class=\"table-options\">\n @if (showColumnViewer) { <cauca-button-popover [buttonLabel]=\"'dataGrid.columns' | translate\" buttonIcon=\"view_column\">\n <mat-card>\n <mat-card-content>\n <div class=\"columns\">\n @for (column of columns; track column) {\n <mat-checkbox color=\"primary\" [(ngModel)]=\"column.selected\"\n (change)=\"onColumnsChanged()\">\n {{column.label}}\n </mat-checkbox>\n }\n </div>\n </mat-card-content>\n <mat-card-actions>\n <cauca-stroked-button [small]=\"true\" color=\"primary\" (buttonClick)=\"resetColumns()\" label=\"dataGrid.columnChooser.reset\" [translateLabel]=\"true\" />\n <cauca-raised-button [small]=\"true\" color=\"primary\" (buttonClick)=\"resetColumns()\" label=\"dataGrid.columnChooser.showAll\" [translateLabel]=\"true\" />\n </mat-card-actions>\n </mat-card>\n </cauca-button-popover> }\n <cauca-basic-button color=\"primary\" [matMenuTriggerFor]=\"densityMenu\" class=\"open-menu-button\" [icon]=\"currentDensityIcon\" label=\"dataGrid.density.title\" [translateLabel]=\"true\" />\n </div>\n\n <ng-content select=\"[customFilter]\"> </ng-content>\n</div>\n\n<mat-menu #densityMenu=\"matMenu\">\n <cauca-menu-item label=\"dataGrid.density.compact\" [translateLabel]=\"true\" icon=\"density_small\" (buttonClick)=\"changeDensity(density.Compact)\" class=\"density-compact\" />\n <cauca-menu-item label=\"dataGrid.density.standard\" [translateLabel]=\"true\" icon=\"density_medium\" (buttonClick)=\"changeDensity(density.Standard)\" class=\"density-standard\" />\n <cauca-menu-item label=\"dataGrid.density.comfortable\" [translateLabel]=\"true\" icon=\"density_large\" (buttonClick)=\"changeDensity(density.Comfortable)\" class=\"density-comfortable\" />\n</mat-menu>","import { ChangeDetectionStrategy, Component, input, Input } from '@angular/core';\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\n\n@Component({\n selector: 'cauca-data-grid-progress-spiner',\n templateUrl: './data-grid-progress-spiner.component.html',\n styleUrls: ['./data-grid-progress-spiner.component.scss'],\n imports: [MatProgressSpinnerModule],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DataGridProgressSpinerComponent {\n\n public isLoading = input<boolean>(false);\n public useBackground = input<boolean>(true);\n}\n","@if (isLoading()) {\n <div class=\"spiner-container\" [class.use-background]=\"useBackground()\">\n <mat-progress-spinner\n color=\"primary\"\n mode=\"indeterminate\">\n </mat-progress-spinner>\n </div>\n}","import {\n AfterContentInit, ChangeDetectionStrategy, Component,\n ContentChild,\n effect,\n EventEmitter, input, Input, OnChanges, output, Output, SimpleChanges,\n TemplateRef\n} from '@angular/core';\nimport { MatCellDef, MatColumnDef, MatFooterCell, MatFooterCellDef, MatFooterRow, MatFooterRowDef, MatHeaderCell, MatHeaderCellDef, MatHeaderRow, MatHeaderRowDef, MatNoDataRow, MatRow, MatRowDef, MatTable, MatTableDataSource, MatTableModule } from '@angular/material/table';\nimport { CdkDrag, CdkDragDrop, CdkDragHandle, CdkDropList, DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop';\nimport { DataGridRowDropEvent } from '../models/data-grid-row-drop-event';\nimport { toLowerCaseAndWithoutDiacritics } from '@cauca-911/core';\nimport { BaseDataGridComponent } from '../base-data-grid.component';\nimport { MatSort } from '@angular/material/sort';\nimport { MatPaginator } from '@angular/material/paginator';\nimport { animate, state, style, transition, trigger } from '@angular/animations';\nimport { PreferenceService } from '../../services/preference.service';\nimport { DataGridHeaderComponent } from '../components/data-grid-header/data-grid-header.component';\nimport { DataGridTableOptionsComponent } from '../components/data-grid-table-options/data-grid-table-options.component';\nimport { IconButtonComponent } from '@cauca-911/material';\nimport { MatIcon } from '@angular/material/icon';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { DataGridProgressSpinerComponent } from '../components/data-grid-progress-spiner/data-grid-progress-spiner.component';\nimport { TranslateModule, TranslateService } from '@ngx-translate/core';\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'cauca-data-grid',\n templateUrl: './data-grid.component.html',\n styleUrls: ['./data-grid.component.scss'],\n animations: [\n trigger('detailExpand', [\n state('collapsed,void', style({height: '0px', minHeight: '0'})),\n state('expanded', style({height: '*'})),\n transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),\n ]),\n ],\n imports: [\n NgTemplateOutlet, // still needed\n // Material Table structure:\n MatTable, MatSort, MatColumnDef,\n MatHeaderCell, MatHeaderCellDef, MatCellDef,\n MatFooterCell, MatFooterCellDef,\n MatRow, MatRowDef,\n MatHeaderRow, MatHeaderRowDef,\n MatFooterRow, MatFooterRowDef,\n MatNoDataRow,\n // Drag and Drop:\n CdkDropList, CdkDrag, CdkDragHandle,\n // Material extras:\n MatIcon, MatPaginator,\n // ngx-translate:\n TranslateModule,\n // Custom Components:\n DataGridHeaderComponent,\n DataGridTableOptionsComponent,\n DataGridProgressSpinerComponent,\n IconButtonComponent\n ]\n})\nexport class DataGridComponent extends BaseDataGridComponent implements OnChanges, AfterContentInit {\n\n @Input() public data: any[] = [];\n @Input() public showLoadingError: boolean = false;\n @Input() public isLoading: boolean = false;\n @Input() public allowReordering: boolean = false;\n @Input() public searchableColumns: string[];\n @Input() public filterPredicate: (data: unknown, filter: string) => boolean;\n @Output() public rowDrop: EventEmitter<DataGridRowDropEvent> = new EventEmitter<DataGridRowDropEvent>();\n @ContentChild(TemplateRef) public rowDetailTemplate!: TemplateRef<any>;\n public showPaginator = input<boolean>(false);\n public showFooter = input<boolean>(false);\n public showHeader = input<boolean>(true);\n public headerColor = input<string|undefined>(undefined);\n public showRefreshButton = input<boolean>(false);\n public refreshData = output<void>();\n\n public dataSource: MatTableDataSource<unknown[]>;\n public dragDisabled: boolean = true;\n public currentFilter: string = '';\n\n public constructor(translateService: TranslateService,\n preferenceService: PreferenceService) {\n super(translateService, preferenceService);\n this.dataSource = new MatTableDataSource([]);\n effect(() => {\n this.setUpPaginator(this.paginator, this.showPaginator());\n });\n }\n\n public onRefreshData(): void {\n this.dataSource.data = [];\n this.refreshData.emit();\n }\n\n public applyFilter(filter: string): void {\n if (this.paginator) {\n this.paginator.firstPage();\n }\n this.dataSource.filter = toLowerCaseAndWithoutDiacritics(filter);\n }\n\n public override setUpSort(sort: MatSort): void {\n this.sort = sort;\n this.dataSource.sort = this.sort;\n }\n\n public override getData(): unknown[] {\n return this.dataSource.data;\n }\n\n public getFilteredData(): unknown[] {\n return this.dataSource.filteredData;\n }\n\n public refreshDisplayedColumns(columns: string[]): void{\n this.onColumnsChanged(columns);\n }\n\n public rowDropped(event: CdkDragDrop<unknown>): void {\n const data: unknown[] = this.getData();\n const filteredData: any[] = this.getFilteredData();\n const fromIndex = data.findIndex((d) => d === filteredData[event.previousIndex]);\n const toIndex = data.findIndex((d) => d === filteredData[event.currentIndex]);\n if (fromIndex >= 0 && toIndex >= 0) {\n moveItemInArray(data, fromIndex, toIndex);\n this.renderRows();\n this.rowDrop.emit(\n new DataGridRowDropEvent({\n item: data[fromIndex],\n data,\n fromIndex,\n toIndex,\n })\n );\n }\n }\n\n protected override setUpPaginator(paginator: MatPaginator, showPaginator: boolean): void {\n this.dataSource.paginator = paginator && showPaginator ? paginator : null;\n }\n\n protected override showColumnsWhenTableOptionsIsFalse(): void {\n if (this.allowReordering) {\n this.allDisplayedColumns.set(['position', ...this.displayedColumns]);\n } else {\n this.allDisplayedColumns.set([...this.displayedColumns]);\n }\n if (this.showExpandButton() && !this.allDisplayedColumns().includes('expand')) {\n this.allDisplayedColumns.set(['expand', ...this.displayedColumns]);\n }\n }\n\n protected override updateColumnsWhenNeeded(changes: SimpleChanges): void {\n if (changes.displayedColumns || changes.allowReordering) {\n if (this.allowReordering && !this.allDisplayedColumns().includes('position')) {\n this.allDisplayedColumns.set(['position', ...this.allDisplayedColumns()]);\n } else {\n this.allDisplayedColumns.set([...this.allDisplayedColumns()]);\n }\n }\n if (this.showExpandButton() && !this.allDisplayedColumns().includes('expand')) {\n this.allDisplayedColumns.set(['expand', ...this.displayedColumns]);\n }\n }\n\n protected onColumnsChanged(columns: string[]): void {\n super.onColumnsChanged(columns);\n if (this.allowReordering && !columns.includes('position')) {\n this.allDisplayedColumns.set(['position', ...columns]);\n } else {\n this.allDisplayedColumns.set([...columns]);\n }\n if (this.showExpandButton() && !this.allDisplayedColumns().includes('expand')) {\n this.allDisplayedColumns.set(['expand', ...this.displayedColumns]);\n }\n }\n\n protected override setUpFilterPredicate(): void {\n if (this.filterPredicate) {\n this.dataSource.filterPredicate = this.filterPredicate;\n } else if (this.searchableColumns?.length > 0) {\n this.dataSource.filterPredicate = (data: unknown, filter: string) => {\n return this.searchableColumns.some((column) => {\n const value = data[column];\n return value?.toString().toLowerCaseAndWithoutDiacritics().includes(filter);\n });\n };\n }\n }\n\n protected override forceReloadFilter(): void {\n // eslint-disable-next-line no-self-assign\n this.dataSource.filter = this.dataSource.filter;\n }\n\n protected override updateDataWhenNeeded(changes: SimpleChanges): void {\n if (changes.data?.currentValue && this.data) {\n this.setData(this.data);\n }\n }\n\n private async setData(data): Promise<void> {\n if (Array.isArray(data)) {\n this.dataSource.data = data;\n setTimeout(() => {\n this.table.setNoDataRow(this.noDataRow);\n this.table.renderRows();\n }, 0);\n }\n }\n}","@if (showHeader()) {\n <cauca-data-grid-header [showAddButton]=\"showAddButton\" [addButtonLabel]=\"addButtonLabel || defaultAddButtonLabel\"\n (addButtonClick)=\"addButtonClick.emit($event)\" (filterChange)=\"applyFilter($event)\"\n [showRefreshButton]=\"showRefreshButton()\" (refreshRequest)=\"onRefreshData()\">\n <ng-content select=\"[filterRow]\" ngProjectAs=\"[filterRow]\" />\n </cauca-data-grid-header>\n}\n\n@if (showTableOptions) {\n <cauca-data-grid-table-options [showColumnViewer]=\"showColumnViewer\" [gridName]=\"resourceName\" (densityChanged)=\"onDensityChanged($event)\" (columnsChanged)=\"onColumnsChanged($event)\" [allColumns]=\"regularColumns\">\n <ng-content\n select=\"[customFilter]\"\n ngProjectAs=\"[customFilter]\">\n </ng-content>\n </cauca-data-grid-table-options>\n}\n\n<table matSort mat-table [dataSource]=\"dataSource\" cdkDropList [cdkDropListData]=\"dataSource\"\n (cdkDropListDropped)=\"rowDropped($event)\" aria-describedby=\"Data Grid\" multiTemplateDataRows>\n\n @if (showExpandButton()) {\n <ng-container matColumnDef=\"expand\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <div class=\"align-commands\">\n <cauca-icon-button (buttonClick)=\"onExpand(row)\" color=\"primary\" class=\"button-icon\" [icon]=\"row === expandedElement() ? 'keyboard_arrow_up' : 'keyboard_arrow_down'\" />\n </div>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n }\n\n @if (allowReordering) {\n <ng-container matColumnDef=\"position\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell (mousedown)=\"dragDisabled = false\" (mouseup)=\"dragDisabled = true\" *matCellDef=\"let group\">\n <mat-icon class=\"reorder-icon\" cdkDragHandle>drag_indicator</mat-icon>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n }\n\n <ng-content></ng-content>\n\n <tr class=\"grid-header\" [style.background-color]=\"headerColor()\" mat-header-row *matHeaderRowDef=\"allDisplayedColumns(); sticky: true\"></tr>\n\n <tr mat-row *matRowDef=\"let row; columns: allDisplayedColumns();\" cdkDrag [cdkDragData]=\"row\"\n [cdkDragDisabled]=\"dragDisabled\" (cdkDragReleased)=\"dragDisabled = true\"\n [class.compact]=\"preference.gridDensity === density.Compact\" [class.standard]=\"preference.gridDensity === density.Standard\"\n [class.comfortable]=\"preference.gridDensity === density.Comfortable\"></tr>\n\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let row\" [attr.colspan]=\"allDisplayedColumns().length\">\n @if (row === expandedElement()) {\n <div class=\"grid-element-detail\" [@detailExpand]=\"row === expandedElement() ? 'expanded' : 'collapsed'\">\n <template [ngTemplateOutlet]=\"rowDetailTemplate\" [ngTemplateOutletContext]=\"{ row: expandedElement() }\"></template>\n </div>\n }\n </td>\n </ng-container>\n\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']\" class=\"grid-detail-row\"></tr>\n\n @if (showFooter()) {\n <tr mat-footer-row *matFooterRowDef=\"allDisplayedColumns(); sticky: false\"></tr>\n }\n\n @if (!isLoading) {\n <tr class=\"mat-row\" *matNoDataRow>\n @if (!showLoadingError && !isLoading) {\n <td class=\"mat-cell data-grid-message\"\n [attr.colspan]=\"allDisplayedColumns().length\">\n <div class=\"icon-text\">\n <mat-icon>grid_off</mat-icon>\n <span>{{ 'dataGrid.noDataLabel' | translate }}</span>\n </div>\n </td>\n }\n @if (showLoadingError) {\n <td class=\"mat-cell data-grid-message error-message\" [attr.colspan]=\"allDisplayedColumns().length\">\n <div class=\"icon-text\">\n <mat-icon>error</mat-icon>\n <span>{{ 'dataGrid.errorLoadingDataLabel' | translate }}</span>\n </div>\n </td>\n }\n </tr>\n }\n\n</table>\n\n<cauca-data-grid-progress-spiner [isLoading]=\"isLoading\" />\n\n@if (showPaginator()) {\n <mat-paginator #paginator [hidePageSize]=\"hidePageSize()\" [pageSizeOptions]=\"[5, 10, 25, 50]\" [pageSize]=\"10\" />\n}","import {EventEmitter, Injectable, signal} from \"@angular/core\";\nimport {ODataDataSource, ODataFilter} from \"odata-data-source\";\nimport {distinctUntilChanged, Subscription} from \"rxjs\";\nimport {HttpClient} from \"@angular/common/http\";\n\nexport interface Paginator {\n pageIndex: number;\n pageSize: number;\n length: number;\n page: EventEmitter<any>;\n}\n\ninterface SingleSort {\n active: string;\n direction: 'asc' | 'desc' | '';\n sortChange: EventEmitter<any>;\n}\ninterface MultiSort {\n sortedBy: {\n id: string;\n direction: 'asc' | 'desc';\n }[];\n multiSortChange: EventEmitter<any>;\n}\n\nexport type Sort = SingleSort | MultiSort;\n\ninterface Props {\n baseUrl: string;\n resourceName: string;\n paginator: Paginator\n sort?: Sort;\n initialSort?: string[];\n filters: ODataFilter[]\n}\n\n@Injectable({\n providedIn: 'root',\n})\nexport class OdataListingService<T = any> {\n public dataSource: ODataDataSource | null = null;\n public error = signal(false);\n public loading = signal(false);\n private errorSubscription: Subscription | null = null;\n private loadingSubscription: Subscription | null = null;\n\n public get data(): T[] | null {\n return this.dataSource?.data ?? null;\n }\n\n public constructor(private readonly httpClient: HttpClient) {}\n\n public initialize({baseUrl, resourceName, paginator, sort, initialSort, filters}: Props): ODataDataSource {\n const newDataSource = new ODataDataSource(this.httpClient, `${baseUrl}odata/${resourceName}`);\n\n newDataSource.filters = filters;\n if (initialSort){\n newDataSource.initialSort = initialSort;\n }\n if (sort) {\n newDataSource.sort = sort;\n }\n newDataSource.paginator = paginator;\n this.dataSource = newDataSource;\n\n this.dataSource.refresh();\n this.errorSubscription = this.dataSource.errors.subscribe((errors) => this.error.set(!!errors));\n\n this.loadingSubscription = this.dataSource.loading\n .pipe(distinctUntilChanged())\n .subscribe((isLoading: boolean) => {\n if (isLoading) {\n this.loading.set(false);\n }\n this.loading.set(isLoading);\n });\n\n return newDataSource;\n }\n\n public updateFilters(filters: ODataFilter[]) {\n if (this.dataSource) {\n this.dataSource.filters = filters;\n }\n }\n\n public forceReloadFilter() {\n if (this.dataSource) {\n // eslint-disable-next-line no-self-assign\n this.dataSource.filters = this.dataSource.filters;\n }\n }\n\n public isInitialized() {\n return this.dataSource !== null;\n }\n\n public refresh() {\n this.dataSource?.refresh();\n }\n\n public destroy() {\n this.errorSubscription?.unsubscribe();\n this.loadingSubscription?.unsubscribe();\n }\n}\n","import { ChangeDetectionStrategy, Component, ContentChild, EventEmitter, inject, input, Input, OnChanges, OnDestroy, Output, SimpleChanges, TemplateRef, ViewChild } from '@angular/core';\nimport { ODataFilter } from 'odata-data-source';\nimport { MatSort } from '@angular/material/sort';\nimport { BaseDataGridComponent } from '../base-data-grid.component';\nimport { CaucaCoreService, toLowerCaseAndWithoutDiacritics, TranslateService } from '@cauca-911/core';\nimport { trigger, state, style, transition, animate } from '@angular/animations';\nimport { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';\nimport { OdataListingService } from \"./odata-listing.service\";\nimport { NgTemplateOutlet } from '@angular/common';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatTable, MatColumnDef, MatHeaderCell, MatHeaderCellDef, MatRow, MatRowDef, MatHeaderRow, MatHeaderRowDef, MatNoDataRow, MatCell, MatCellDef } from '@angular/material/table';\nimport { IconButtonComponent } from '@cauca-911/material';\nimport { DataGridHeaderComponent } from '../components/data-grid-header/data-grid-header.component';\nimport { DataGridProgressSpinerComponent } from '../components/data-grid-progress-spiner/data-grid-progress-spiner.component';\nimport { DataGridTableOptionsComponent } from '../components/data-grid-table-options/data-grid-table-options.component';\nimport { PreferenceService } from '../../services/preference.service';\nimport { TranslateModule } from '@ngx-translate/core';\nimport Icon from 'ol/style/Icon';\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'cauca-odata-grid',\n templateUrl: './odata-grid.component.html',\n styleUrls: ['./odata-grid.component.scss'],\n providers: [OdataListingService],\n animations: [\n trigger('detailExpand', [\n state('collapsed,void', style({height: '0px', minHeight: '0'})),\n state('expanded', style({height: '*'})),\n transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),\n ]),\n ],\n imports: [\n NgTemplateOutlet,\n // Material table structure:\n MatTable, MatColumnDef,\n MatHeaderCell, MatHeaderCellDef, MatCell, MatCellDef,\n MatHeaderRow, MatHeaderRowDef,\n MatRow, MatRowDef, MatNoDataRow,\n // Material extras\n MatIcon, MatPaginator,\n // ngx-translate\n TranslateModule,\n // custom components\n DataGridHeaderComponent,\n DataGridTableOptionsComponent,\n IconButtonComponent,\n DataGridProgressSpinerComponent,\n ]\n})\nexport class OdataGridComponent extends BaseDataGridComponent implements OnChanges, OnDestroy {\n\n public showTableHeader = input(true);\n @Input() public baseSort?: string[];\n @Input() public filterPredicate?: (filter: string) => ODataFilter[];\n @Input() public showHeader: boolean = true;\n @Input() public selectedRowId: any;\n @Input() public idField: string = 'id';\n @Output() public itemClick: EventEmitter<any> = new EventEmitter<any>();\n @Output() public refreshRequested: EventEmitter<void> = new EventEmitter<void>();\n @Input() public showRefreshButton: boolean = false;\n @ContentChild(TemplateRef) public rowDetailTemplate!: TemplateRef<any>;\n @ViewChild(MatPaginator, {static: true}) public paginator!: MatPaginator;\n\n private readonly baseUrl = inject(CaucaCoreService).getConfig().apiUrl;\n\n public constructor(\n translateService: TranslateService,\n preferenceService: PreferenceService,\n public readonly listing: OdataListingService,\n ) {\n super(translateService, preferenceService);\n }\n\n public ngOnDestroy(): void {\n this.listing.destroy();\n }\n\n public refreshData(): void {\n this.listing.refresh();\n this.refreshRequested.emit();\n }\n\n public ngOnChanges(changes: SimpleChanges): void {\n this.updateColumnsWhenNeeded(changes);\n }\n\n public getData(): unknown[] {\n return this.listing.data;\n }\n\n public applyFilter(filter: string): void {\n if (this.filterPredicate) {\n if (this.paginator) {\n this.paginator.firstPage();\n }\n this.listing.updateFilters(this.filterPredicate(toLowerCaseAndWithoutDiacritics(filter)));\n }\n }\n\n public refreshFilter(): void {\n if (this.filterPredicate) {\n this.listing.updateFilters(this.filterPredicate(toLowerCaseAndWithoutDiacritics(this.header.filterControl?.value)));\n }\n }\n\n public override setUpFilterPredicate(): void {\n this.listing.initialize({\n baseUrl: this.baseUrl,\n resourceName: this.resourceName,\n paginator: this.paginator,\n sort: this.sort,\n initialSort: this.baseSort,\n filters: this.filterPredicate?.('') ?? [],\n });\n }\n\n public override setUpSort(sort: MatSort): void {\n this.sort = sort;\n }\n\n protected updateColumnsWhenNeeded(changes: SimpleChanges): void {\n if (changes.displayedColumns || changes.showExpandButton) {\n let columns = [...this.displayedColumns];\n if (this.showExpandButton()) {\n columns = ['expand', ...columns];\n }\n this.allDisplayedColumns.set([...columns]);\n }\n }\n\n protected override forceReloadFilter(): void {\n this.listing.forceReloadFilter();\n }\n\n protected override updateDataWhenNeeded(_changes: SimpleChanges): void {\n // not implemented\n }\n\n protected override onColumnsChanged(columns: string[]): void {\n if (this.showExpandButton() && columns.indexOf('expand') === -1) {\n columns = ['expand', ...columns];\n }\n super.onColumnsChanged(columns);\n }\n\n protected override showColumnsWhenTableOptionsIsFalse(): void {\n let columns = [...this.displayedColumns];\n if (this.showExpandButton()) {\n columns = ['expand', ...columns];\n }\n this.allDisplayedColumns.set([...columns]);\n }\n}\n","@if (showHeader) {\n <cauca-data-grid-header\n [showRefreshButton]=\"showRefreshButton\" (refreshRequest)=\"refreshData()\"\n [showAddButton]=\"showAddButton\"\n [addButtonLabel]=\"addButtonLabel || defaultAddButtonLabel\"\n (addButtonClick)=\"addButtonClick.emit($event)\" (filterChange)=\"applyFilter($event)\">\n <ng-content select=\"[filterRow]\" ngProjectAs=\"[filterRow]\" />\n </cauca-data-grid-header>\n}\n\n<ng-content select=\"[customHeader]\" ngProjectAs=\"[customHeader]\" />\n\n@if (showTableOptions) {\n <cauca-data-grid-table-options [showColumnViewer]=\"showColumnViewer\" [gridName]=\"resourceName\" (densityChanged)=\"onDensityChanged($event)\" (columnsChanged)=\"onColumnsChanged($event)\" [allColumns]=\"regularColumns\">\n <ng-content select=\"[customFilter]\" ngProjectAs=\"[customFilter]\" />\n </cauca-data-grid-table-options>\n}\n\n<div class=\"relative\">\n <table mat-table [dataSource]=\"listing.dataSource\" aria-describedby=\"Data Grid\" multiTemplateDataRows>\n @if (showExpandButton()) {\n <ng-container matColumnDef=\"expand\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <div class=\"align-commands\">\n