thingsboard/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts

756 lines
26 KiB
TypeScript
Raw Normal View History

2019-08-12 19:34:23 +03:00
///
2024-01-09 10:46:16 +02:00
/// Copyright © 2016-2024 The Thingsboard Authors
2019-08-12 19:34:23 +03:00
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
2020-01-30 13:03:53 +02:00
Component,
ComponentFactoryResolver,
ElementRef,
EventEmitter,
Input, NgZone,
OnChanges,
OnDestroy,
OnInit,
SimpleChanges,
2020-01-30 13:03:53 +02:00
ViewChild
2019-08-12 19:34:23 +03:00
} from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { MAX_SAFE_PAGE_SIZE, PageLink, PageQueryParam, TimePageLink } from '@shared/models/page/page-link';
2020-02-10 13:15:29 +02:00
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort, SortDirection } from '@angular/material/sort';
2019-08-21 18:18:46 +03:00
import { EntitiesDataSource } from '@home/models/datasource/entity-datasource';
import { catchError, debounceTime, distinctUntilChanged, map, skip, takeUntil } from 'rxjs/operators';
2019-08-12 19:34:23 +03:00
import { Direction, SortOrder } from '@shared/models/page/sort-order';
import { forkJoin, merge, Observable, of, Subject, Subscription } from 'rxjs';
2019-08-12 19:34:23 +03:00
import { TranslateService } from '@ngx-translate/core';
import { BaseData, HasId } from '@shared/models/base-data';
import { ActivatedRoute, QueryParamsHandling, Router } from '@angular/router';
2019-08-12 19:34:23 +03:00
import {
CellActionDescriptor,
CellActionDescriptorType,
2020-01-30 13:03:53 +02:00
EntityActionTableColumn,
EntityChipsEntityTableColumn,
2020-01-30 13:03:53 +02:00
EntityColumn,
EntityLinkTableColumn,
2019-08-12 19:34:23 +03:00
EntityTableColumn,
EntityTableConfig,
GroupActionDescriptor,
2020-01-30 13:03:53 +02:00
HeaderActionDescriptor
2019-08-21 18:18:46 +03:00
} from '@home/models/entity/entities-table-config.models';
2019-08-12 19:34:23 +03:00
import { EntityTypeTranslation } from '@shared/models/entity-type.models';
import { DialogService } from '@core/services/dialog.service';
2019-08-21 18:18:46 +03:00
import { AddEntityDialogComponent } from './add-entity-dialog.component';
2020-01-30 13:03:53 +02:00
import { AddEntityDialogData, EntityAction } from '@home/models/entity/entity-component.models';
import { calculateIntervalStartEndTime, HistoryWindowType, Timewindow } from '@shared/models/time/time.models';
2020-01-30 13:03:53 +02:00
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
2019-08-12 19:34:23 +03:00
import { TbAnchorComponent } from '@shared/components/tb-anchor.component';
import { isDefined, isEqual, isNotEmptyStr, isUndefined } from '@core/utils';
import { HasUUID } from '@shared/models/id/has-uuid';
import { hidePageSizePixelValue } from '@shared/models/constants';
2023-04-03 19:39:28 +03:00
import { EntitiesTableAction, IEntitiesTableComponent } from '@home/models/entity/entity-table-component.models';
2022-01-19 17:02:18 +02:00
import { EntityDetailsPanelComponent } from '@home/components/entity/entity-details-panel.component';
import { FormBuilder } from '@angular/forms';
2019-08-12 19:34:23 +03:00
@Component({
selector: 'tb-entities-table',
templateUrl: './entities-table.component.html',
styleUrls: ['./entities-table.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
2019-08-12 19:34:23 +03:00
})
export class EntitiesTableComponent extends PageComponent implements IEntitiesTableComponent, AfterViewInit, OnInit, OnChanges, OnDestroy {
2019-08-12 19:34:23 +03:00
@Input()
entitiesTableConfig: EntityTableConfig<BaseData<HasId>>;
translations: EntityTypeTranslation;
headerActionDescriptors: Array<HeaderActionDescriptor>;
groupActionDescriptors: Array<GroupActionDescriptor<BaseData<HasId>>>;
cellActionDescriptors: Array<CellActionDescriptor<BaseData<HasId>>>;
actionColumns: Array<EntityActionTableColumn<BaseData<HasId>>>;
entityColumns: Array<EntityTableColumn<BaseData<HasId>>>;
2019-08-22 18:44:48 +03:00
displayedColumns: string[];
headerCellStyleCache: Array<any> = [];
2019-08-12 19:34:23 +03:00
cellContentCache: Array<SafeHtml> = [];
cellTooltipCache: Array<string> = [];
cellStyleCache: Array<any> = [];
2019-08-12 19:34:23 +03:00
selectionEnabled;
2020-04-08 19:31:08 +03:00
defaultPageSize = 10;
displayPagination = true;
2021-12-14 12:40:18 +02:00
hidePageSize = false;
2020-04-08 19:31:08 +03:00
pageSizeOptions;
2019-08-12 19:34:23 +03:00
pageLink: PageLink;
pageMode = true;
2019-08-12 19:34:23 +03:00
textSearchMode = false;
timewindow: Timewindow;
dataSource: EntitiesDataSource<BaseData<HasId>>;
2021-06-04 20:49:01 +03:00
cellActionType = CellActionDescriptorType;
2019-08-12 19:34:23 +03:00
isDetailsOpen = false;
2020-04-08 19:31:08 +03:00
detailsPanelOpened = new EventEmitter<boolean>();
2019-08-12 19:34:23 +03:00
2019-08-13 19:58:35 +03:00
@ViewChild('entityTableHeader', {static: true}) entityTableHeaderAnchor: TbAnchorComponent;
2019-08-12 19:34:23 +03:00
2020-02-10 13:10:14 +02:00
@ViewChild('searchInput') searchInputField: ElementRef;
2019-08-12 19:34:23 +03:00
2020-02-10 13:10:14 +02:00
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
2019-08-12 19:34:23 +03:00
2022-01-19 17:02:18 +02:00
@ViewChild('entityDetailsPanel') entityDetailsPanel: EntityDetailsPanelComponent;
textSearch = this.fb.control('', {nonNullable: true});
2020-04-08 19:31:08 +03:00
private updateDataSubscription: Subscription;
private viewInited = false;
private widgetResize$: ResizeObserver;
private destroy$ = new Subject<void>();
2019-08-12 19:34:23 +03:00
constructor(protected store: Store<AppState>,
2020-04-10 14:12:40 +03:00
public route: ActivatedRoute,
2019-08-12 19:34:23 +03:00
public translate: TranslateService,
public dialog: MatDialog,
private dialogService: DialogService,
private domSanitizer: DomSanitizer,
private cd: ChangeDetectorRef,
private router: Router,
2021-12-14 12:40:18 +02:00
private componentFactoryResolver: ComponentFactoryResolver,
private elementRef: ElementRef,
private fb: FormBuilder,
private zone: NgZone) {
2019-08-12 19:34:23 +03:00
super(store);
}
ngOnInit() {
2020-04-07 17:06:04 +03:00
if (this.entitiesTableConfig) {
this.init(this.entitiesTableConfig);
} else {
this.route.data.pipe(
takeUntil(this.destroy$)
).subscribe((data) => {
this.init(data.entitiesTableConfig);
});
2020-04-07 17:06:04 +03:00
}
this.widgetResize$ = new ResizeObserver(() => {
this.zone.run(() => {
const showHidePageSize = this.elementRef.nativeElement.offsetWidth < hidePageSizePixelValue;
if (showHidePageSize !== this.hidePageSize) {
this.hidePageSize = showHidePageSize;
this.cd.markForCheck();
}
});
});
2021-12-14 12:40:18 +02:00
this.widgetResize$.observe(this.elementRef.nativeElement);
}
ngOnDestroy() {
if (this.widgetResize$) {
this.widgetResize$.disconnect();
}
this.destroy$.next();
this.destroy$.complete();
2020-04-07 17:06:04 +03:00
}
ngOnChanges(changes: SimpleChanges): void {
for (const propName of Object.keys(changes)) {
const change = changes[propName];
if (!change.firstChange && change.currentValue !== change.previousValue) {
if (propName === 'entitiesTableConfig' && change.currentValue) {
this.init(change.currentValue);
}
}
}
}
private init(entitiesTableConfig: EntityTableConfig<BaseData<HasId>>) {
this.isDetailsOpen = false;
this.entitiesTableConfig = entitiesTableConfig;
this.pageMode = this.entitiesTableConfig.pageMode;
2019-08-12 19:34:23 +03:00
if (this.entitiesTableConfig.headerComponent) {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.entitiesTableConfig.headerComponent);
const viewContainerRef = this.entityTableHeaderAnchor.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);
const headerComponent = componentRef.instance;
headerComponent.entitiesTableConfig = this.entitiesTableConfig;
}
2022-01-19 17:02:18 +02:00
this.entitiesTableConfig.setTable(this);
2019-08-12 19:34:23 +03:00
this.translations = this.entitiesTableConfig.entityTranslations;
this.headerActionDescriptors = [...this.entitiesTableConfig.headerActionDescriptors];
this.groupActionDescriptors = [...this.entitiesTableConfig.groupActionDescriptors];
this.cellActionDescriptors = [...this.entitiesTableConfig.cellActionDescriptors];
if (this.entitiesTableConfig.entitiesDeleteEnabled) {
this.cellActionDescriptors.push(
{
name: this.translate.instant('action.delete'),
icon: 'delete',
isEnabled: entity => this.entitiesTableConfig.deleteEnabled(entity),
onAction: ($event, entity) => this.deleteEntity($event, entity)
}
);
2020-04-07 17:06:04 +03:00
this.groupActionDescriptors.push(
{
name: this.translate.instant('action.delete'),
icon: 'delete',
isEnabled: true,
onAction: ($event, entities) => this.deleteEntities($event, entities)
}
);
2019-08-12 19:34:23 +03:00
}
const enabledGroupActionDescriptors =
this.groupActionDescriptors.filter((descriptor) => descriptor.isEnabled);
this.selectionEnabled = this.entitiesTableConfig.selectionEnabled && enabledGroupActionDescriptors.length;
2019-08-12 19:34:23 +03:00
2019-08-22 18:44:48 +03:00
this.columnsUpdated();
2019-08-12 19:34:23 +03:00
const routerQueryParams: PageQueryParam = this.route.snapshot.queryParams;
2020-04-07 17:06:04 +03:00
let sortOrder: SortOrder = null;
2023-04-03 19:39:28 +03:00
let initialAction: EntitiesTableAction = null;
if (this.pageMode) {
2023-04-03 19:39:28 +03:00
initialAction = routerQueryParams?.action;
if (this.entitiesTableConfig.defaultSortOrder || routerQueryParams.hasOwnProperty('direction')
|| routerQueryParams.hasOwnProperty('property')) {
sortOrder = {
property: routerQueryParams?.property || this.entitiesTableConfig.defaultSortOrder.property,
direction: routerQueryParams?.direction || this.entitiesTableConfig.defaultSortOrder.direction
};
}
} else if (this.entitiesTableConfig.defaultSortOrder){
2020-04-07 17:06:04 +03:00
sortOrder = {
property: this.entitiesTableConfig.defaultSortOrder.property,
direction: this.entitiesTableConfig.defaultSortOrder.direction
2020-04-07 17:06:04 +03:00
};
}
2019-08-12 19:34:23 +03:00
2020-04-08 19:31:08 +03:00
this.displayPagination = this.entitiesTableConfig.displayPagination;
this.defaultPageSize = this.entitiesTableConfig.defaultPageSize;
this.pageSizeOptions = [this.defaultPageSize, this.defaultPageSize * 2, this.defaultPageSize * 3];
2019-08-12 19:34:23 +03:00
if (this.entitiesTableConfig.useTimePageLink) {
this.timewindow = this.entitiesTableConfig.defaultTimewindowInterval;
const interval = this.getTimePageLinkInterval();
2019-08-12 19:34:23 +03:00
this.pageLink = new TimePageLink(10, 0, null, sortOrder,
interval.startTime, interval.endTime);
2019-08-12 19:34:23 +03:00
} else {
this.pageLink = new PageLink(10, 0, null, sortOrder);
}
2020-04-08 19:31:08 +03:00
this.pageLink.pageSize = this.displayPagination ? this.defaultPageSize : MAX_SAFE_PAGE_SIZE;
if (this.pageMode) {
if (routerQueryParams.hasOwnProperty('page')) {
this.pageLink.page = Number(routerQueryParams.page);
}
if (routerQueryParams.hasOwnProperty('pageSize')) {
this.pageLink.pageSize = Number(routerQueryParams.pageSize);
}
const textSearchParam = routerQueryParams.textSearch;
if (isNotEmptyStr(textSearchParam)) {
const decodedTextSearch = decodeURI(textSearchParam);
this.textSearchMode = true;
this.pageLink.textSearch = decodedTextSearch.trim();
this.textSearch.setValue(decodedTextSearch, {emitEvent: false});
}
}
this.dataSource = this.entitiesTableConfig.dataSource(this.dataLoaded.bind(this));
2019-08-12 19:34:23 +03:00
if (this.entitiesTableConfig.onLoadAction) {
this.entitiesTableConfig.onLoadAction(this.route);
}
if (this.entitiesTableConfig.loadDataOnInit) {
this.dataSource.loadEntities(this.pageLink);
}
2020-04-08 19:31:08 +03:00
if (this.viewInited) {
setTimeout(() => {
this.updatePaginationSubscriptions();
}, 0);
}
2023-04-03 19:39:28 +03:00
if (this.pageMode) {
if (initialAction) {
const queryParams: PageQueryParam = {};
this.router.navigate([], {
relativeTo: this.route,
queryParams,
queryParamsHandling: '',
replaceUrl: true
});
}
if (initialAction === 'add') {
setTimeout(() => {
this.addEntity(null);
}, 0);
}
}
2019-08-12 19:34:23 +03:00
}
ngAfterViewInit() {
this.textSearch.valueChanges.pipe(
debounceTime(150),
distinctUntilChanged((prev, current) => (this.pageLink.textSearch ?? '') === current.trim()),
takeUntil(this.destroy$)
).subscribe(value => {
if (this.pageMode) {
const queryParams: PageQueryParam = {
textSearch: isNotEmptyStr(value) ? encodeURI(value) : null,
page: null
};
this.updatedRouterParamsAndData(queryParams);
} else {
this.pageLink.textSearch = isNotEmptyStr(value) ? value.trim() : null;
if (this.displayPagination) {
this.paginator.pageIndex = 0;
}
this.updateData();
}
});
2019-08-12 19:34:23 +03:00
if (this.pageMode) {
this.route.queryParams.pipe(
skip(1),
takeUntil(this.destroy$)
).subscribe((params: PageQueryParam) => {
2022-06-09 18:02:31 +03:00
if (this.displayPagination) {
this.paginator.pageIndex = Number(params.page) || 0;
this.paginator.pageSize = Number(params.pageSize) || this.defaultPageSize;
}
this.sort.active = params.property || this.entitiesTableConfig.defaultSortOrder.property;
this.sort.direction = (params.direction || this.entitiesTableConfig.defaultSortOrder.direction).toLowerCase() as SortDirection;
const textSearchParam = params.textSearch;
if (isNotEmptyStr(textSearchParam)) {
const decodedTextSearch = decodeURI(textSearchParam);
this.textSearchMode = true;
this.pageLink.textSearch = decodedTextSearch.trim();
this.textSearch.setValue(decodedTextSearch, {emitEvent: false});
} else {
this.pageLink.textSearch = null;
this.textSearch.reset('', {emitEvent: false});
}
this.updateData();
});
}
2020-04-08 19:31:08 +03:00
this.updatePaginationSubscriptions();
this.viewInited = true;
}
2019-08-12 19:34:23 +03:00
2020-04-08 19:31:08 +03:00
private updatePaginationSubscriptions() {
if (this.updateDataSubscription) {
this.updateDataSubscription.unsubscribe();
this.updateDataSubscription = null;
}
let paginatorSubscription$: Observable<object>;
const sortSubscription$: Observable<object> = this.sort.sortChange.asObservable().pipe(
map((data) => {
const direction = data.direction.toUpperCase();
const queryParams: PageQueryParam = {
direction: (this.entitiesTableConfig?.defaultSortOrder?.direction === direction ? null : direction) as Direction,
property: this.entitiesTableConfig?.defaultSortOrder?.property === data.active ? null : data.active
};
if (this.displayPagination) {
queryParams.page = null;
this.paginator.pageIndex = 0;
}
return queryParams;
})
);
2020-04-08 19:31:08 +03:00
if (this.displayPagination) {
paginatorSubscription$ = this.paginator.page.asObservable().pipe(
map((data) => ({
page: data.pageIndex === 0 ? null : data.pageIndex,
pageSize: data.pageSize === this.defaultPageSize ? null : data.pageSize
}))
);
2020-04-08 19:31:08 +03:00
}
this.updateDataSubscription = ((this.displayPagination ? merge(sortSubscription$, paginatorSubscription$)
: sortSubscription$) as Observable<PageQueryParam>).pipe(
takeUntil(this.destroy$)
).subscribe(queryParams => this.updatedRouterParamsAndData(queryParams));
2019-08-12 19:34:23 +03:00
}
addEnabled() {
return this.entitiesTableConfig.addEnabled;
}
clearSelection() {
this.dataSource.selection.clear();
this.cd.detectChanges();
}
2024-08-19 18:36:31 +03:00
updateData(closeDetails: boolean = true, reloadEntity: boolean = true) {
2019-08-12 19:34:23 +03:00
if (closeDetails) {
this.isDetailsOpen = false;
}
2020-04-08 19:31:08 +03:00
if (this.displayPagination) {
this.pageLink.page = this.paginator.pageIndex;
this.pageLink.pageSize = this.paginator.pageSize;
} else {
this.pageLink.page = 0;
}
2020-04-07 17:06:04 +03:00
if (this.sort.active) {
this.pageLink.sortOrder = {
property: this.sort.active,
direction: Direction[this.sort.direction.toUpperCase()]
};
} else {
this.pageLink.sortOrder = null;
}
2019-08-12 19:34:23 +03:00
if (this.entitiesTableConfig.useTimePageLink) {
const timePageLink = this.pageLink as TimePageLink;
const interval = this.getTimePageLinkInterval();
timePageLink.startTime = interval.startTime;
timePageLink.endTime = interval.endTime;
2019-08-12 19:34:23 +03:00
}
this.dataSource.loadEntities(this.pageLink);
2024-08-19 18:36:31 +03:00
if (reloadEntity && this.isDetailsOpen && this.entityDetailsPanel) {
2022-01-19 17:02:18 +02:00
this.entityDetailsPanel.reloadEntity();
}
2019-08-12 19:34:23 +03:00
}
2024-09-20 14:08:26 +03:00
private getTimePageLinkInterval(): {startTime?: number; endTime?: number} {
const interval: {startTime?: number; endTime?: number} = {};
switch (this.timewindow.history.historyType) {
case HistoryWindowType.LAST_INTERVAL:
const currentTime = Date.now();
interval.startTime = currentTime - this.timewindow.history.timewindowMs;
interval.endTime = currentTime;
break;
case HistoryWindowType.FIXED:
interval.startTime = this.timewindow.history.fixedTimewindow.startTimeMs;
interval.endTime = this.timewindow.history.fixedTimewindow.endTimeMs;
break;
case HistoryWindowType.INTERVAL:
const startEndTime = calculateIntervalStartEndTime(this.timewindow.history.quickInterval);
interval.startTime = startEndTime[0];
interval.endTime = startEndTime[1];
break;
case HistoryWindowType.FOR_ALL_TIME:
interval.startTime = null;
interval.endTime = null;
break;
}
return interval;
}
private dataLoaded(col?: number, row?: number) {
if (isFinite(col) && isFinite(row)) {
this.clearCellCache(col, row);
} else {
this.headerCellStyleCache.length = 0;
this.cellContentCache.length = 0;
this.cellTooltipCache.length = 0;
this.cellStyleCache.length = 0;
}
}
2019-08-12 19:34:23 +03:00
onRowClick($event: Event, entity) {
2020-04-08 19:31:08 +03:00
if (!this.entitiesTableConfig.handleRowClick($event, entity)) {
this.toggleEntityDetails($event, entity);
}
}
toggleEntityDetails($event: Event, entity) {
2019-08-12 19:34:23 +03:00
if ($event) {
$event.stopPropagation();
}
if (this.dataSource.toggleCurrentEntity(entity)) {
this.isDetailsOpen = true;
} else {
this.isDetailsOpen = !this.isDetailsOpen;
}
2020-04-08 19:31:08 +03:00
this.detailsPanelOpened.emit(this.isDetailsOpen);
2019-08-12 19:34:23 +03:00
}
addEntity($event: Event) {
let entity$: Observable<BaseData<HasId>>;
if (this.entitiesTableConfig.addEntity) {
entity$ = this.entitiesTableConfig.addEntity();
} else {
entity$ = this.dialog.open<AddEntityDialogComponent, AddEntityDialogData<BaseData<HasId>>,
BaseData<HasId>>(AddEntityDialogComponent, {
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: {
entitiesTableConfig: this.entitiesTableConfig
}
}).afterClosed();
}
entity$.subscribe(
(entity) => {
if (entity) {
this.updateData();
2020-04-15 13:00:32 +03:00
this.entitiesTableConfig.entityAdded(entity);
2019-08-12 19:34:23 +03:00
}
}
);
}
onEntityUpdated(entity: BaseData<HasId>) {
2024-08-19 18:36:31 +03:00
this.updateData(false, false);
2020-04-15 13:00:32 +03:00
this.entitiesTableConfig.entityUpdated(entity);
2019-08-12 19:34:23 +03:00
}
onEntityAction(action: EntityAction<BaseData<HasId>>) {
if (action.action === 'delete') {
this.deleteEntity(action.event, action.entity);
}
}
deleteEntity($event: Event, entity: BaseData<HasId>) {
if ($event) {
$event.stopPropagation();
}
this.dialogService.confirm(
this.entitiesTableConfig.deleteEntityTitle(entity),
this.entitiesTableConfig.deleteEntityContent(entity),
this.translate.instant('action.no'),
this.translate.instant('action.yes'),
true
).subscribe((result) => {
if (result) {
this.entitiesTableConfig.deleteEntity(entity.id).subscribe(
() => {
this.updateData();
2020-04-15 13:00:32 +03:00
this.entitiesTableConfig.entitiesDeleted([entity.id]);
2019-08-12 19:34:23 +03:00
}
);
}
});
}
deleteEntities($event: Event, entities: BaseData<HasId>[]) {
if ($event) {
$event.stopPropagation();
}
this.dialogService.confirm(
this.entitiesTableConfig.deleteEntitiesTitle(entities.length),
this.entitiesTableConfig.deleteEntitiesContent(entities.length),
this.translate.instant('action.no'),
this.translate.instant('action.yes'),
true
).subscribe((result) => {
if (result) {
2020-08-27 19:32:15 +03:00
const tasks: Observable<HasUUID>[] = [];
2019-08-12 19:34:23 +03:00
entities.forEach((entity) => {
if (this.entitiesTableConfig.deleteEnabled(entity)) {
2020-08-27 19:32:15 +03:00
tasks.push(this.entitiesTableConfig.deleteEntity(entity.id).pipe(
map(() => entity.id),
catchError(() => of(null)
)));
2019-08-12 19:34:23 +03:00
}
});
forkJoin(tasks).subscribe(
2020-08-27 19:32:15 +03:00
(ids) => {
2019-08-12 19:34:23 +03:00
this.updateData();
2020-08-27 19:32:15 +03:00
this.entitiesTableConfig.entitiesDeleted(ids.filter(id => id !== null));
2019-08-12 19:34:23 +03:00
}
);
}
});
}
onTimewindowChange() {
if (this.displayPagination) {
this.paginator.pageIndex = 0;
}
2019-08-12 19:34:23 +03:00
this.updateData();
}
enterFilterMode() {
this.textSearchMode = true;
setTimeout(() => {
this.searchInputField.nativeElement.focus();
this.searchInputField.nativeElement.setSelectionRange(0, 0);
}, 10);
}
exitFilterMode() {
this.textSearchMode = false;
this.textSearch.reset();
2019-08-12 19:34:23 +03:00
}
resetSortAndFilter(update: boolean = true, preserveTimewindow: boolean = false) {
this.textSearchMode = false;
2019-08-12 19:34:23 +03:00
this.pageLink.textSearch = null;
this.textSearch.reset('', {emitEvent: false});
if (this.entitiesTableConfig.useTimePageLink && !preserveTimewindow) {
this.timewindow = this.entitiesTableConfig.defaultTimewindowInterval;
2020-04-08 19:31:08 +03:00
}
if (this.displayPagination) {
this.paginator.pageIndex = 0;
2019-08-12 19:34:23 +03:00
}
const sortable = this.sort.sortables.get(this.entitiesTableConfig.defaultSortOrder.property);
this.sort.active = sortable.id;
this.sort.direction = this.entitiesTableConfig.defaultSortOrder.direction === Direction.ASC ? 'asc' : 'desc';
if (update) {
this.updatedRouterParamsAndData({}, '');
2019-08-12 19:34:23 +03:00
}
}
2019-08-22 18:44:48 +03:00
columnsUpdated(resetData: boolean = false) {
this.entityColumns = this.entitiesTableConfig.columns.filter(
(column) => column instanceof EntityTableColumn || column instanceof EntityLinkTableColumn ||
column instanceof EntityChipsEntityTableColumn)
.map(column => column as EntityTableColumn<BaseData<HasId>>);
this.actionColumns = this.entitiesTableConfig.columns.filter(
(column) => column instanceof EntityActionTableColumn)
.map(column => column as EntityActionTableColumn<BaseData<HasId>>);
2019-08-22 18:44:48 +03:00
this.displayedColumns = [];
if (this.selectionEnabled) {
this.displayedColumns.push('select');
}
this.entitiesTableConfig.columns.forEach(
2019-08-22 18:44:48 +03:00
(column) => {
this.displayedColumns.push(column.key);
}
);
this.displayedColumns.push('actions');
this.headerCellStyleCache.length = 0;
this.cellContentCache.length = 0;
this.cellTooltipCache.length = 0;
2019-08-22 18:44:48 +03:00
this.cellStyleCache.length = 0;
if (resetData) {
this.dataSource.reset();
}
}
2023-07-03 17:13:11 +03:00
cellActionDescriptorsUpdated() {
this.cellActionDescriptors = [...this.entitiesTableConfig.cellActionDescriptors];
}
headerCellStyle(column: EntityColumn<BaseData<HasId>>) {
const index = this.entitiesTableConfig.columns.indexOf(column);
2019-08-22 18:44:48 +03:00
let res = this.headerCellStyleCache[index];
if (!res) {
2020-02-04 19:50:18 +02:00
const widthStyle: any = {width: column.width};
if (column.width !== '0px') {
widthStyle.minWidth = column.width;
widthStyle.maxWidth = column.width;
}
2019-08-22 18:44:48 +03:00
if (column instanceof EntityTableColumn) {
2020-02-04 19:50:18 +02:00
res = {...column.headerCellStyleFunction(column.key), ...widthStyle};
2019-08-22 18:44:48 +03:00
} else {
2020-02-04 19:50:18 +02:00
res = widthStyle;
2019-08-22 18:44:48 +03:00
}
this.headerCellStyleCache[index] = res;
}
return res;
}
clearCellCache(col: number, row: number) {
const index = row * this.entitiesTableConfig.columns.length + col;
this.cellContentCache[index] = undefined;
this.cellTooltipCache[index] = undefined;
this.cellStyleCache[index] = undefined;
}
cellContent(entity: BaseData<HasId>, column: EntityColumn<BaseData<HasId>>, row: number) {
if (column instanceof EntityTableColumn || column instanceof EntityLinkTableColumn) {
const col = this.entitiesTableConfig.columns.indexOf(column);
const index = row * this.entitiesTableConfig.columns.length + col;
2019-08-22 18:44:48 +03:00
let res = this.cellContentCache[index];
if (isUndefined(res)) {
2019-08-22 18:44:48 +03:00
res = this.domSanitizer.bypassSecurityTrustHtml(column.cellContentFunction(entity, column.key));
this.cellContentCache[index] = res;
}
return res;
} else {
2020-02-05 17:52:18 +02:00
return '';
2019-08-22 18:44:48 +03:00
}
}
cellTooltip(entity: BaseData<HasId>, column: EntityColumn<BaseData<HasId>>, row: number) {
if (column instanceof EntityTableColumn) {
const col = this.entitiesTableConfig.columns.indexOf(column);
const index = row * this.entitiesTableConfig.columns.length + col;
let res = this.cellTooltipCache[index];
if (isUndefined(res)) {
res = column.cellTooltipFunction(entity, column.key);
res = isDefined(res) ? res : null;
this.cellTooltipCache[index] = res;
} else {
return res !== null ? res : undefined;
}
} else {
return undefined;
}
}
cellStyle(entity: BaseData<HasId>, column: EntityColumn<BaseData<HasId>>, row: number) {
const col = this.entitiesTableConfig.columns.indexOf(column);
const index = row * this.entitiesTableConfig.columns.length + col;
let res = this.cellStyleCache[index];
if (!res) {
2020-02-04 19:50:18 +02:00
const widthStyle: any = {width: column.width};
if (column.width !== '0px') {
widthStyle.minWidth = column.width;
widthStyle.maxWidth = column.width;
}
2019-08-22 18:44:48 +03:00
if (column instanceof EntityTableColumn) {
2020-02-04 19:50:18 +02:00
res = {...column.cellStyleFunction(entity, column.key), ...widthStyle};
2019-08-22 18:44:48 +03:00
} else {
2020-02-04 19:50:18 +02:00
res = widthStyle;
2019-08-22 18:44:48 +03:00
}
this.cellStyleCache[index] = res;
}
return res;
2019-08-12 19:34:23 +03:00
}
trackByColumnKey(index, column: EntityTableColumn<BaseData<HasId>>) {
return column.key;
2019-08-12 19:34:23 +03:00
}
2020-01-30 13:03:53 +02:00
trackByEntityId(index: number, entity: BaseData<HasId>) {
return entity.id.id;
}
protected updatedRouterParamsAndData(queryParams: object, queryParamsHandling: QueryParamsHandling = 'merge') {
if (this.pageMode) {
this.router.navigate([], {
relativeTo: this.route,
queryParams,
queryParamsHandling
});
if (queryParamsHandling === '' && isEqual(this.route.snapshot.queryParams, queryParams)) {
this.updateData();
}
} else {
this.updateData();
}
}
detectChanges() {
this.cd.markForCheck();
}
2019-08-12 19:34:23 +03:00
}