Browse Source

UI: Entity table models improvements

pull/2592/head
Igor Kulikov 7 years ago
parent
commit
c60e99fad9
  1. 2
      ui-ngx/src/app/modules/home/components/alarm/alarm-table-config.ts
  2. 2
      ui-ngx/src/app/modules/home/components/audit-log/audit-log-table-config.ts
  3. 2
      ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.html
  4. 33
      ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.ts
  5. 7
      ui-ngx/src/app/modules/home/components/entity/contact-based.component.ts
  6. 10
      ui-ngx/src/app/modules/home/components/entity/entities-table.component.html
  7. 78
      ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts
  8. 4
      ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.html
  9. 55
      ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts
  10. 31
      ui-ngx/src/app/modules/home/components/entity/entity-tabs.component.ts
  11. 25
      ui-ngx/src/app/modules/home/components/entity/entity.component.ts
  12. 2
      ui-ngx/src/app/modules/home/components/event/event-table-config.ts
  13. 4
      ui-ngx/src/app/modules/home/models/datasource/entity-datasource.ts
  14. 64
      ui-ngx/src/app/modules/home/models/entity/entities-table-config.models.ts
  15. 7
      ui-ngx/src/app/modules/home/pages/asset/asset.component.ts
  16. 2
      ui-ngx/src/app/modules/home/pages/customer/customer-routing.module.ts
  17. 7
      ui-ngx/src/app/modules/home/pages/customer/customer.component.ts
  18. 13
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.ts
  19. 5
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-routing.module.ts
  20. 7
      ui-ngx/src/app/modules/home/pages/device/device.component.ts
  21. 7
      ui-ngx/src/app/modules/home/pages/entity-view/entity-view.component.ts
  22. 10
      ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts
  23. 7
      ui-ngx/src/app/modules/home/pages/rulechain/rulechain.component.ts
  24. 7
      ui-ngx/src/app/modules/home/pages/tenant/tenant.component.ts
  25. 7
      ui-ngx/src/app/modules/home/pages/user/user.component.ts
  26. 13
      ui-ngx/src/app/modules/home/pages/widget/widget-library-routing.module.ts
  27. 7
      ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts
  28. 2
      ui-ngx/src/app/shared/components/breadcrumb.component.ts
  29. 6
      ui-ngx/src/app/shared/components/breadcrumb.ts
  30. 6
      ui-ngx/src/app/shared/models/entity-type.models.ts

2
ui-ngx/src/app/modules/home/components/alarm/alarm-table-config.ts

@ -72,7 +72,7 @@ export class AlarmTableConfig extends EntityTableConfig<AlarmInfo, TimePageLink>
this.entityType = EntityType.ALARM;
this.entityTranslations = entityTypeTranslations.get(EntityType.ALARM);
this.entityResources = {
} as EntityTypeResource;
} as EntityTypeResource<AlarmInfo>;
this.searchStatus = defaultSearchStatus;
this.headerComponent = AlarmTableHeaderComponent;

2
ui-ngx/src/app/modules/home/components/audit-log/audit-log-table-config.ts

@ -68,7 +68,7 @@ export class AuditLogTableConfig extends EntityTableConfig<AuditLog, TimePageLin
search: 'audit-log.search'
};
this.entityResources = {
} as EntityTypeResource;
} as EntityTypeResource<AuditLog>;
this.entitiesFetchFunction = pageLink => this.fetchAuditLogs(pageLink);

2
ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.html

@ -19,7 +19,7 @@
<mat-toolbar color="primary">
<h2 translate>{{ translations.add }}</h2>
<span fxFlex></span>
<div [tb-help]="resources.helpLinkId"></div>
<div [tb-help]="helpLinkId()"></div>
<button mat-icon-button
(click)="cancel()"
type="button">

33
ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component, ComponentFactoryResolver, Inject, OnInit, SkipSelf, ViewChild } from '@angular/core';
import { Component, ComponentFactoryResolver, Inject, Injector, OnInit, SkipSelf, ViewChild } from '@angular/core';
import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
@ -29,6 +29,7 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod
import { AddEntityDialogData } from '@home/models/entity/entity-component.models';
import { DialogComponent } from '@shared/components/dialog.component';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
@Component({
selector: 'tb-add-entity-dialog',
@ -44,7 +45,7 @@ export class AddEntityDialogComponent extends
entitiesTableConfig: EntityTableConfig<BaseData<HasId>>;
translations: EntityTypeTranslation;
resources: EntityTypeResource;
resources: EntityTypeResource<BaseData<HasId>>;
entity: BaseData<EntityId>;
submitted = false;
@ -56,6 +57,7 @@ export class AddEntityDialogComponent extends
@Inject(MAT_DIALOG_DATA) public data: AddEntityDialogData<BaseData<HasId>>,
public dialogRef: MatDialogRef<AddEntityDialogComponent, BaseData<HasId>>,
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher) {
super(store, router, dialogRef);
}
@ -68,14 +70,35 @@ export class AddEntityDialogComponent extends
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.entitiesTableConfig.entityComponent);
const viewContainerRef = this.entityDetailsFormAnchor.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);
const injector: Injector = Injector.create(
{
providers: [
{
provide: 'entity',
useValue: this.entity
},
{
provide: 'entitiesTableConfig',
useValue: this.entitiesTableConfig
}
],
parent: this.injector
}
);
const componentRef = viewContainerRef.createComponent(componentFactory, 0, injector);
this.entityComponent = componentRef.instance;
this.entityComponent.isEdit = true;
this.entityComponent.entitiesTableConfig = this.entitiesTableConfig;
this.entityComponent.entity = this.entity;
this.detailsForm = this.entityComponent.entityNgForm;
}
helpLinkId(): string {
if (this.resources.helpLinkIdForEntity && this.entityComponent.entityForm) {
return this.resources.helpLinkIdForEntity(this.entityComponent.entityForm.getRawValue());
} else {
return this.resources.helpLinkId;
}
}
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const originalErrorState = this.errorStateMatcher.isErrorState(control, form);
const customErrorState = !!(control && control.invalid && this.submitted);

7
ui-ngx/src/app/modules/home/components/entity/contact-based.component.ts

@ -22,12 +22,15 @@ import { AfterViewInit } from '@angular/core';
import { POSTAL_CODE_PATTERNS } from '@home/models/contact.models';
import { HasId } from '@shared/models/base-data';
import {EntityComponent} from './entity.component';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
export abstract class ContactBasedComponent<T extends ContactBased<HasId>> extends EntityComponent<T> implements AfterViewInit {
protected constructor(protected store: Store<AppState>,
protected fb: FormBuilder) {
super(store);
protected fb: FormBuilder,
protected entityValue: T,
protected entitiesTableConfig: EntityTableConfig<T>) {
super(store, fb, entityValue, entitiesTableConfig);
}
buildForm(entity: T): FormGroup {

10
ui-ngx/src/app/modules/home/components/entity/entities-table.component.html

@ -135,7 +135,7 @@
</mat-toolbar>
<div fxFlex class="table-container">
<table mat-table [dataSource]="dataSource" [trackBy]="trackByEntityId"
matSort [matSortActive]="pageLink.sortOrder.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear>
matSort [matSortActive]="pageLink.sortOrder?.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear>
<ng-container matColumnDef="select" sticky>
<mat-header-cell *matHeaderCellDef style="width: 30px;">
<mat-checkbox (change)="$event ? dataSource.masterToggle() : null"
@ -153,8 +153,11 @@
</ng-container>
<ng-container [matColumnDef]="column.key" *ngFor="let column of entityColumns; trackBy: trackByColumnKey;">
<mat-header-cell [ngClass]="{'mat-number-cell': column.isNumberColumn}"
*matHeaderCellDef [ngStyle]="headerCellStyle(column)" mat-sort-header [disabled]="!column.sortable"> {{ column.title | translate }} </mat-header-cell>
[fxHide.lt-lg]="column.mobileHide"
*matHeaderCellDef [ngStyle]="headerCellStyle(column)" mat-sort-header [disabled]="!column.sortable">
{{ column.ignoreTranslate ? column.title : (column.title | translate) }} </mat-header-cell>
<mat-cell [ngClass]="{'mat-number-cell': column.isNumberColumn}"
[fxHide.lt-lg]="column.mobileHide"
*matCellDef="let entity; let row = index"
[matTooltip]="cellTooltip(entity, column, row)"
matTooltipPosition="above"
@ -186,8 +189,7 @@
maxWidth: (cellActionDescriptors.length * 40) + 'px',
width: (cellActionDescriptors.length * 40) + 'px' }">
<div fxHide fxShow.gt-md fxFlex fxLayout="row" fxLayoutAlign="end">
<button mat-icon-button [disabled]="isLoading$ | async"
[style.visibility]="actionDescriptor.isEnabled(entity) ? 'visible' : 'hidden'"
<button mat-icon-button [disabled]="(isLoading$ | async) || !actionDescriptor.isEnabled(entity)"
*ngFor="let actionDescriptor of cellActionDescriptors"
matTooltip="{{ actionDescriptor.nameFunction ? actionDescriptor.nameFunction(entity) : actionDescriptor.name }}"
matTooltipPosition="above"

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

@ -20,8 +20,8 @@ import {
Component,
ComponentFactoryResolver,
ElementRef,
Input,
OnInit,
Input, OnChanges,
OnInit, SimpleChanges,
ViewChild
} from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
@ -51,7 +51,7 @@ import { EntityTypeTranslation } from '@shared/models/entity-type.models';
import { DialogService } from '@core/services/dialog.service';
import { AddEntityDialogComponent } from './add-entity-dialog.component';
import { AddEntityDialogData, EntityAction } from '@home/models/entity/entity-component.models';
import { historyInterval, HistoryWindowType, Timewindow } from '@shared/models/time/time.models';
import { DAY, historyInterval, HistoryWindowType, Timewindow } from '@shared/models/time/time.models';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TbAnchorComponent } from '@shared/components/tb-anchor.component';
import { isDefined, isUndefined } from '@core/utils';
@ -62,7 +62,7 @@ import { isDefined, isUndefined } from '@core/utils';
styleUrls: ['./entities-table.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class EntitiesTableComponent extends PageComponent implements AfterViewInit, OnInit {
export class EntitiesTableComponent extends PageComponent implements AfterViewInit, OnInit, OnChanges {
@Input()
entitiesTableConfig: EntityTableConfig<BaseData<HasId>>;
@ -112,7 +112,27 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn
}
ngOnInit() {
this.entitiesTableConfig = this.entitiesTableConfig || this.route.snapshot.data.entitiesTableConfig;
if (this.entitiesTableConfig) {
this.init(this.entitiesTableConfig);
} else {
this.init(this.route.snapshot.data.entitiesTableConfig);
}
}
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;
if (this.entitiesTableConfig.headerComponent) {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.entitiesTableConfig.headerComponent);
const viewContainerRef = this.entityTableHeaderAnchor.viewContainerRef;
@ -138,17 +158,16 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn
onAction: ($event, entity) => this.deleteEntity($event, entity)
}
);
this.groupActionDescriptors.push(
{
name: this.translate.instant('action.delete'),
icon: 'delete',
isEnabled: true,
onAction: ($event, entities) => this.deleteEntities($event, entities)
}
);
}
this.groupActionDescriptors.push(
{
name: this.translate.instant('action.delete'),
icon: 'delete',
isEnabled: this.entitiesTableConfig.entitiesDeleteEnabled,
onAction: ($event, entities) => this.deleteEntities($event, entities)
}
);
const enabledGroupActionDescriptors =
this.groupActionDescriptors.filter((descriptor) => descriptor.isEnabled);
@ -156,24 +175,25 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn
this.columnsUpdated();
const sortOrder: SortOrder = { property: this.entitiesTableConfig.defaultSortOrder.property,
direction: this.entitiesTableConfig.defaultSortOrder.direction };
let sortOrder: SortOrder = null;
if (this.entitiesTableConfig.defaultSortOrder) {
sortOrder = {
property: this.entitiesTableConfig.defaultSortOrder.property,
direction: this.entitiesTableConfig.defaultSortOrder.direction
};
}
if (this.entitiesTableConfig.useTimePageLink) {
this.timewindow = historyInterval(24 * 60 * 60 * 1000);
this.timewindow = historyInterval(DAY);
const currentTime = Date.now();
this.pageLink = new TimePageLink(10, 0, null, sortOrder,
currentTime - this.timewindow.history.timewindowMs, currentTime);
} else {
this.pageLink = new PageLink(10, 0, null, sortOrder);
}
this.dataSource = new EntitiesDataSource<BaseData<HasId>>(
this.entitiesTableConfig.entitiesFetchFunction,
this.entitiesTableConfig.entitySelectionEnabled,
() => {
this.dataLoaded();
}
);
this.dataSource = this.entitiesTableConfig.dataSource(() => {
this.dataLoaded();
});
if (this.entitiesTableConfig.onLoadAction) {
this.entitiesTableConfig.onLoadAction(this.route);
}
@ -214,8 +234,14 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn
}
this.pageLink.page = this.paginator.pageIndex;
this.pageLink.pageSize = this.paginator.pageSize;
this.pageLink.sortOrder.property = this.sort.active;
this.pageLink.sortOrder.direction = Direction[this.sort.direction.toUpperCase()];
if (this.sort.active) {
this.pageLink.sortOrder = {
property: this.sort.active,
direction: Direction[this.sort.direction.toUpperCase()]
};
} else {
this.pageLink.sortOrder = null;
}
if (this.entitiesTableConfig.useTimePageLink) {
const timePageLink = this.pageLink as TimePageLink;
if (this.timewindow.history.historyType === HistoryWindowType.LAST_INTERVAL) {

4
ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.html

@ -25,9 +25,9 @@
(applyDetails)="saveEntity()"
[theForm]="detailsForm">
<div class="details-buttons">
<div [tb-help]="resources.helpLinkId"></div>
<div [tb-help]="helpLinkId()"></div>
</div>
<mat-tab-group class="tb-absolute-fill" [ngClass]="{'tb-headless': isEditValue}" fxFlex [(selectedIndex)]="selectedTab">
<mat-tab-group class="tb-absolute-fill" [ngClass]="{'tb-headless': hideDetailsTabs()}" fxFlex [(selectedIndex)]="selectedTab">
<mat-tab label="{{ 'details.details' | translate }}">
<tb-anchor #entityDetailsForm></tb-anchor>
</mat-tab>

55
ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts

@ -16,10 +16,10 @@
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectionStrategy, ChangeDetectorRef,
Component,
ComponentFactoryResolver,
EventEmitter,
EventEmitter, Injector,
Input,
OnDestroy,
OnInit,
@ -41,6 +41,7 @@ import { EntityAction } from '@home/models/entity/entity-component.models';
import { Subscription } from 'rxjs';
import { MatTab, MatTabGroup } from '@angular/material/tabs';
import { EntityTabsComponent } from '@home/components/entity/entity-tabs.component';
import { deepClone } from '@core/utils';
@Component({
selector: 'tb-entity-details-panel',
@ -79,13 +80,16 @@ export class EntityDetailsPanelComponent extends PageComponent implements OnInit
@ViewChildren(MatTab) inclusiveTabs: QueryList<MatTab>;
translations: EntityTypeTranslation;
resources: EntityTypeResource;
resources: EntityTypeResource<BaseData<HasId>>;
entity: BaseData<HasId>;
editingEntity: BaseData<HasId>;
private currentEntityId: HasId;
private entityActionSubscription: Subscription;
constructor(protected store: Store<AppState>,
private injector: Injector,
private cd: ChangeDetectorRef,
private componentFactoryResolver: ComponentFactoryResolver) {
super(store);
}
@ -127,15 +131,32 @@ export class EntityDetailsPanelComponent extends PageComponent implements OnInit
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.entitiesTableConfig.entityComponent);
const viewContainerRef = this.entityDetailsFormAnchor.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);
const injector: Injector = Injector.create(
{
providers: [
{
provide: 'entity',
useValue: this.entity
},
{
provide: 'entitiesTableConfig',
useValue: this.entitiesTableConfig
}
],
parent: this.injector
}
);
const componentRef = viewContainerRef.createComponent(componentFactory, 0, injector);
this.entityComponent = componentRef.instance;
this.entityComponent.isEdit = this.isEdit;
this.entityComponent.entitiesTableConfig = this.entitiesTableConfig;
this.detailsForm = this.entityComponent.entityNgForm;
this.entityActionSubscription = this.entityComponent.entityAction.subscribe((action) => {
this.entityAction.emit(action);
});
this.buildEntityTabsComponent();
this.entityComponent.entityForm.valueChanges.subscribe(() => {
this.cd.detectChanges();
});
}
buildEntityTabsComponent() {
@ -147,9 +168,14 @@ export class EntityDetailsPanelComponent extends PageComponent implements OnInit
this.entityTabsComponent = componentTabsRef.instance;
this.entityTabsComponent.isEdit = this.isEdit;
this.entityTabsComponent.entitiesTableConfig = this.entitiesTableConfig;
this.entityTabsComponent.detailsForm = this.detailsForm;
}
}
hideDetailsTabs(): boolean {
return this.isEditValue && this.entitiesTableConfig.hideDetailsTabsOnEdit;
}
reload(): void {
this.isEdit = false;
this.entitiesTableConfig.loadEntity(this.currentEntityId).subscribe(
@ -175,13 +201,28 @@ export class EntityDetailsPanelComponent extends PageComponent implements OnInit
this.entityTabsComponent.entity = this.entity;
}
} else {
this.selectedTab = 0;
this.editingEntity = deepClone(this.entity);
this.entityComponent.entity = this.editingEntity;
if (this.entityTabsComponent) {
this.entityTabsComponent.entity = this.editingEntity;
}
if (this.entitiesTableConfig.hideDetailsTabsOnEdit) {
this.selectedTab = 0;
}
}
}
helpLinkId(): string {
if (this.resources.helpLinkIdForEntity && this.entityComponent.entityForm) {
return this.resources.helpLinkIdForEntity(this.entityComponent.entityForm.getRawValue());
} else {
return this.resources.helpLinkId;
}
}
saveEntity() {
if (this.detailsForm.valid) {
const editingEntity = {...this.entity, ...this.entityComponent.entityFormValue()};
const editingEntity = {...this.editingEntity, ...this.entityComponent.entityFormValue()};
this.entitiesTableConfig.saveEntity(editingEntity).subscribe(
(entity) => {
this.entity = entity;

31
ui-ngx/src/app/modules/home/components/entity/entity-tabs.component.ts

@ -31,9 +31,15 @@ import { AuditLogMode } from '@shared/models/audit-log.models';
import { DebugEventType, EventType } from '@shared/models/event.models';
import { AttributeScope, LatestTelemetry } from '@shared/models/telemetry/telemetry.models';
import { NULL_UUID } from '@shared/models/id/has-uuid';
import { NgForm } from '@angular/forms';
import { PageLink } from '@shared/models/page/page-link';
@Directive()
export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends PageComponent implements OnInit, AfterViewInit {
export abstract class EntityTabsComponent<T extends BaseData<HasId>,
P extends PageLink = PageLink,
L extends BaseData<HasId> = T,
C extends EntityTableConfig<T, P, L> = EntityTableConfig<T, P, L>>
extends PageComponent implements OnInit, AfterViewInit {
attributeScopes = AttributeScope;
latestTelemetryTypes = LatestTelemetry;
@ -54,6 +60,8 @@ export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends Pag
entityValue: T;
entitiesTableConfigValue: C;
@ViewChildren(MatTab) entityTabs: QueryList<MatTab>;
isEditValue: boolean;
@ -69,7 +77,7 @@ export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends Pag
@Input()
set entity(entity: T) {
this.entityValue = entity;
this.setEntity(entity);
}
get entity(): T {
@ -77,7 +85,16 @@ export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends Pag
}
@Input()
entitiesTableConfig: EntityTableConfig<T>;
set entitiesTableConfig(entitiesTableConfig: C) {
this.setEntitiesTableConfig(entitiesTableConfig);
}
get entitiesTableConfig(): C {
return this.entitiesTableConfigValue;
}
@Input()
detailsForm: NgForm;
private entityTabsSubject = new BehaviorSubject<Array<MatTab>>(null);
@ -100,4 +117,12 @@ export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends Pag
);
}
protected setEntity(entity: T) {
this.entityValue = entity;
}
protected setEntitiesTableConfig(entitiesTableConfig: C) {
this.entitiesTableConfigValue = entitiesTableConfig;
}
}

25
ui-ngx/src/app/modules/home/components/entity/entity.component.ts

@ -15,18 +15,22 @@
///
import { BaseData, HasId } from '@shared/models/base-data';
import { FormGroup, NgForm } from '@angular/forms';
import { FormBuilder, FormGroup, NgForm } from '@angular/forms';
import { PageComponent } from '@shared/components/page.component';
import { EventEmitter, Input, OnInit, Output, ViewChild, Directive } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { EntityAction } from '@home/models/entity/entity-component.models';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
import { PageLink } from '@shared/models/page/page-link';
@Directive()
export abstract class EntityComponent<T extends BaseData<HasId>> extends PageComponent implements OnInit {
export abstract class EntityComponent<T extends BaseData<HasId>,
P extends PageLink = PageLink,
L extends BaseData<HasId> = T,
C extends EntityTableConfig<T, P, L> = EntityTableConfig<T, P, L>>
extends PageComponent implements OnInit {
entityValue: T;
entityForm: FormGroup;
@ViewChild('entityNgForm', {static: true}) entityNgForm: NgForm;
@ -51,7 +55,8 @@ export abstract class EntityComponent<T extends BaseData<HasId>> extends PageCom
set entity(entity: T) {
this.entityValue = entity;
if (this.entityForm) {
this.entityForm.reset();
this.entityForm.reset(undefined, {emitEvent: false});
this.entityForm.markAsPristine();
this.updateForm(entity);
}
}
@ -60,18 +65,18 @@ export abstract class EntityComponent<T extends BaseData<HasId>> extends PageCom
return this.entityValue;
}
@Input()
entitiesTableConfig: EntityTableConfig<T>;
@Output()
entityAction = new EventEmitter<EntityAction<T>>();
protected constructor(protected store: Store<AppState>) {
protected constructor(protected store: Store<AppState>,
protected fb: FormBuilder,
protected entityValue: T,
protected entitiesTableConfig: C) {
super(store);
this.entityForm = this.buildForm(this.entityValue);
}
ngOnInit() {
this.entityForm = this.buildForm(this.entityValue);
}
onEntityAction($event: Event, action: string) {
@ -96,7 +101,7 @@ export abstract class EntityComponent<T extends BaseData<HasId>> extends PageCom
}
entityFormValue() {
const formValue = this.entityForm ? {...this.entityForm.value} : {};
const formValue = this.entityForm ? {...this.entityForm.getRawValue()} : {};
return this.prepareFormValue(formValue);
}

2
ui-ngx/src/app/modules/home/components/event/event-table-config.ts

@ -94,7 +94,7 @@ export class EventTableConfig extends EntityTableConfig<Event, TimePageLink> {
noEntities: 'event.no-events-prompt'
};
this.entityResources = {
} as EntityTypeResource;
} as EntityTypeResource<Event>;
this.entitiesFetchFunction = pageLink => this.fetchEvents(pageLink);
this.defaultSortOrder = {property: 'createdTime', direction: Direction.DESC};

4
ui-ngx/src/app/modules/home/models/datasource/entity-datasource.ts

@ -36,8 +36,8 @@ export class EntitiesDataSource<T extends BaseData<HasId>, P extends PageLink =
public currentEntity: T = null;
constructor(private fetchFunction: EntitiesFetchFunction<T, P>,
private selectionEnabledFunction: EntityBooleanFunction<T>,
private dataLoadedFunction: () => void) {}
protected selectionEnabledFunction: EntityBooleanFunction<T>,
protected dataLoadedFunction: () => void) {}
connect(collectionViewer: CollectionViewer): Observable<T[] | ReadonlyArray<T>> {
return this.entitiesSubject.asObservable();

64
ui-ngx/src/app/modules/home/models/entity/entities-table-config.models.ts

@ -14,21 +14,21 @@
/// limitations under the License.
///
import {BaseData, HasId} from '@shared/models/base-data';
import {EntitiesFetchFunction} from '@home/models/datasource/entity-datasource';
import {Observable, of} from 'rxjs';
import {emptyPageData} from '@shared/models/page/page-data';
import {DatePipe} from '@angular/common';
import {Direction, SortOrder} from '@shared/models/page/sort-order';
import {EntityType, EntityTypeResource, EntityTypeTranslation} from '@shared/models/entity-type.models';
import {EntityComponent} from '@home/components/entity/entity.component';
import {Type} from '@angular/core';
import {EntityAction} from './entity-component.models';
import {HasUUID} from '@shared/models/id/has-uuid';
import {PageLink} from '@shared/models/page/page-link';
import {EntitiesTableComponent} from '@home/components/entity/entities-table.component';
import {EntityTableHeaderComponent} from '@home/components/entity/entity-table-header.component';
import {ActivatedRoute} from '@angular/router';
import { BaseData, HasId } from '@shared/models/base-data';
import { EntitiesDataSource, EntitiesFetchFunction } from '@home/models/datasource/entity-datasource';
import { Observable, of } from 'rxjs';
import { emptyPageData } from '@shared/models/page/page-data';
import { DatePipe } from '@angular/common';
import { Direction, SortOrder } from '@shared/models/page/sort-order';
import { EntityType, EntityTypeResource, EntityTypeTranslation } from '@shared/models/entity-type.models';
import { EntityComponent } from '@home/components/entity/entity.component';
import { Type } from '@angular/core';
import { EntityAction } from './entity-component.models';
import { HasUUID } from '@shared/models/id/has-uuid';
import { PageLink } from '@shared/models/page/page-link';
import { EntitiesTableComponent } from '@home/components/entity/entities-table.component';
import { EntityTableHeaderComponent } from '@home/components/entity/entity-table-header.component';
import { ActivatedRoute } from '@angular/router';
import { EntityTabsComponent } from '../../components/entity/entity-tabs.component';
export type EntityBooleanFunction<T extends BaseData<HasId>> = (entity: T) => boolean;
@ -76,7 +76,9 @@ export class BaseEntityTableColumn<T extends BaseData<HasId>> {
public key: string,
public title: string,
public width: string = '0px',
public sortable: boolean = true) {
public sortable: boolean = true,
public ignoreTranslate: boolean = false,
public mobileHide: boolean = false) {
}
}
@ -120,7 +122,7 @@ export class DateEntityTableColumn<T extends BaseData<HasId>> extends EntityTabl
export type EntityColumn<T extends BaseData<HasId>> = EntityTableColumn<T> | EntityActionTableColumn<T>;
export class EntityTableConfig<T extends BaseData<HasId>, P extends PageLink = PageLink> {
export class EntityTableConfig<T extends BaseData<HasId>, P extends PageLink = PageLink, L extends BaseData<HasId> = T> {
constructor() {}
@ -137,31 +139,35 @@ export class EntityTableConfig<T extends BaseData<HasId>, P extends PageLink = P
addEnabled = true;
entitiesDeleteEnabled = true;
detailsPanelEnabled = true;
hideDetailsTabsOnEdit = true;
actionsColumnTitle = null;
entityTranslations: EntityTypeTranslation;
entityResources: EntityTypeResource;
entityComponent: Type<EntityComponent<T>>;
entityTabsComponent: Type<EntityTabsComponent<T>>;
entityResources: EntityTypeResource<T>;
entityComponent: Type<EntityComponent<T, P, L>>;
entityTabsComponent: Type<EntityTabsComponent<T, P, L>>;
addDialogStyle = {};
defaultSortOrder: SortOrder = {property: 'createdTime', direction: Direction.ASC};
columns: Array<EntityColumn<T>> = [];
cellActionDescriptors: Array<CellActionDescriptor<T>> = [];
groupActionDescriptors: Array<GroupActionDescriptor<T>> = [];
columns: Array<EntityColumn<L>> = [];
cellActionDescriptors: Array<CellActionDescriptor<L>> = [];
groupActionDescriptors: Array<GroupActionDescriptor<L>> = [];
headerActionDescriptors: Array<HeaderActionDescriptor> = [];
addActionDescriptors: Array<HeaderActionDescriptor> = [];
headerComponent: Type<EntityTableHeaderComponent<T>>;
headerComponent: Type<EntityTableHeaderComponent<L>>;
addEntity: CreateEntityOperation<T> = null;
dataSource: (dataLoadedFunction: () => void) => EntitiesDataSource<L> = (dataLoadedFunction: () => void) => {
return new EntitiesDataSource(this.entitiesFetchFunction, this.entitySelectionEnabled, dataLoadedFunction);
};
detailsReadonly: EntityBooleanFunction<T> = () => false;
entitySelectionEnabled: EntityBooleanFunction<T> = () => true;
deleteEnabled: EntityBooleanFunction<T> = () => true;
deleteEntityTitle: EntityStringFunction<T> = () => '';
deleteEntityContent: EntityStringFunction<T> = () => '';
entitySelectionEnabled: EntityBooleanFunction<L> = () => true;
deleteEnabled: EntityBooleanFunction<T | L> = () => true;
deleteEntityTitle: EntityStringFunction<L> = () => '';
deleteEntityContent: EntityStringFunction<L> = () => '';
deleteEntitiesTitle: EntityCountStringFunction = () => '';
deleteEntitiesContent: EntityCountStringFunction = () => '';
loadEntity: EntityByIdOperation<T> = () => of();
saveEntity: EntityTwoWayOperation<T> = (entity) => of(entity);
deleteEntity: EntityIdOneWayOperation = () => of();
entitiesFetchFunction: EntitiesFetchFunction<T, P> = () => of(emptyPageData<T>());
entitiesFetchFunction: EntitiesFetchFunction<L, P> = () => of(emptyPageData<L>());
onEntityAction: EntityActionFunction<T> = () => false;
entityTitle: EntityStringFunction<T> = (entity) => entity?.name;
}

7
ui-ngx/src/app/modules/home/pages/asset/asset.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component } from '@angular/core';
import { Component, Inject } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { EntityComponent } from '../../components/entity/entity.component';
@ -24,6 +24,7 @@ import { NULL_UUID } from '@shared/models/id/has-uuid';
import { ActionNotificationShow } from '@core/notification/notification.actions';
import { TranslateService } from '@ngx-translate/core';
import { AssetInfo } from '@app/shared/models/asset.models';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
@Component({
selector: 'tb-asset',
@ -38,8 +39,10 @@ export class AssetComponent extends EntityComponent<AssetInfo> {
constructor(protected store: Store<AppState>,
protected translate: TranslateService,
@Inject('entity') protected entityValue: AssetInfo,
@Inject('entitiesTableConfig') protected entitiesTableConfig: EntityTableConfig<AssetInfo>,
public fb: FormBuilder) {
super(store);
super(store, fb, entityValue, entitiesTableConfig);
}
ngOnInit() {

2
ui-ngx/src/app/modules/home/pages/customer/customer-routing.module.ts

@ -124,7 +124,7 @@ const routes: Routes = [
breadcrumb: {
labelFunction: dashboardBreadcumbLabelFunction,
icon: 'dashboard'
} as BreadCrumbConfig,
} as BreadCrumbConfig<DashboardPageComponent>,
auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER],
title: 'customer.dashboard',
widgetEditMode: false

7
ui-ngx/src/app/modules/home/pages/customer/customer.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component } from '@angular/core';
import { Component, Inject } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@ -22,6 +22,7 @@ import { Customer } from '@shared/models/customer.model';
import { ActionNotificationShow } from '@app/core/notification/notification.actions';
import { TranslateService } from '@ngx-translate/core';
import { ContactBasedComponent } from '../../components/entity/contact-based.component';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
@Component({
selector: 'tb-customer',
@ -33,8 +34,10 @@ export class CustomerComponent extends ContactBasedComponent<Customer> {
constructor(protected store: Store<AppState>,
protected translate: TranslateService,
@Inject('entity') protected entityValue: Customer,
@Inject('entitiesTableConfig') protected entitiesTableConfig: EntityTableConfig<Customer>,
protected fb: FormBuilder) {
super(store, fb);
super(store, fb, entityValue, entitiesTableConfig);
}
hideDelete() {

13
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-form.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component } from '@angular/core';
import { Component, Inject } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { EntityComponent } from '../../components/entity/entity.component';
@ -28,6 +28,7 @@ import {
isPublicDashboard
} from '@shared/models/dashboard.models';
import { DashboardService } from '@core/http/dashboard.service';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
@Component({
selector: 'tb-dashboard-form',
@ -45,8 +46,10 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> {
constructor(protected store: Store<AppState>,
protected translate: TranslateService,
private dashboardService: DashboardService,
@Inject('entity') protected entityValue: Dashboard,
@Inject('entitiesTableConfig') protected entitiesTableConfig: EntityTableConfig<Dashboard>,
public fb: FormBuilder) {
super(store);
super(store, fb, entityValue, entitiesTableConfig);
}
ngOnInit() {
@ -103,7 +106,9 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> {
}
private updateFields(entity: Dashboard): void {
this.assignedCustomersText = getDashboardAssignedCustomersText(entity);
this.publicLink = this.dashboardService.getPublicDashboardLink(entity);
if (entity) {
this.assignedCustomersText = getDashboardAssignedCustomersText(entity);
this.publicLink = this.dashboardService.getPublicDashboardLink(entity);
}
}
}

5
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-routing.module.ts

@ -43,7 +43,8 @@ export class DashboardResolver implements Resolve<Dashboard> {
}
}
export const dashboardBreadcumbLabelFunction: BreadCrumbLabelFunction = ((route, translate, component) => component.dashboard.title);
export const dashboardBreadcumbLabelFunction: BreadCrumbLabelFunction<DashboardPageComponent>
= ((route, translate, component) => component.dashboard.title);
const routes: Routes = [
{
@ -74,7 +75,7 @@ const routes: Routes = [
breadcrumb: {
labelFunction: dashboardBreadcumbLabelFunction,
icon: 'dashboard'
} as BreadCrumbConfig,
} as BreadCrumbConfig<DashboardPageComponent>,
auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER],
title: 'dashboard.dashboard',
widgetEditMode: false

7
ui-ngx/src/app/modules/home/pages/device/device.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component } from '@angular/core';
import { Component, Inject } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { EntityComponent } from '../../components/entity/entity.component';
@ -26,6 +26,7 @@ import { ActionNotificationShow } from '@core/notification/notification.actions'
import { TranslateService } from '@ngx-translate/core';
import { DeviceService } from '@core/http/device.service';
import { ClipboardService } from 'ngx-clipboard';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
@Component({
selector: 'tb-device',
@ -42,8 +43,10 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> {
protected translate: TranslateService,
private deviceService: DeviceService,
private clipboardService: ClipboardService,
@Inject('entity') protected entityValue: DeviceInfo,
@Inject('entitiesTableConfig') protected entitiesTableConfig: EntityTableConfig<DeviceInfo>,
public fb: FormBuilder) {
super(store);
super(store, fb, entityValue, entitiesTableConfig);
}
ngOnInit() {

7
ui-ngx/src/app/modules/home/pages/entity-view/entity-view.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component } from '@angular/core';
import { Component, Inject } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { EntityComponent } from '../../components/entity/entity.component';
@ -27,6 +27,7 @@ import { EntityViewInfo } from '@app/shared/models/entity-view.models';
import { Observable } from 'rxjs';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { EntityId } from '@app/shared/models/id/entity-id';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
@Component({
selector: 'tb-entity-view',
@ -50,8 +51,10 @@ export class EntityViewComponent extends EntityComponent<EntityViewInfo> {
constructor(protected store: Store<AppState>,
protected translate: TranslateService,
@Inject('entity') protected entityValue: EntityViewInfo,
@Inject('entitiesTableConfig') protected entitiesTableConfig: EntityTableConfig<EntityViewInfo>,
public fb: FormBuilder) {
super(store);
super(store, fb, entityValue, entitiesTableConfig);
}
ngOnInit() {

10
ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts

@ -126,7 +126,8 @@ export class RuleChainImportGuard implements CanActivate {
}
export const ruleChainBreadcumbLabelFunction: BreadCrumbLabelFunction = ((route, translate, component) => {
export const ruleChainBreadcumbLabelFunction: BreadCrumbLabelFunction<RuleChainPageComponent>
= ((route, translate, component) => {
let label: string = component.ruleChain.name;
if (component.ruleChain.root) {
label += ` (${translate.instant('rulechain.root')})`;
@ -134,7 +135,8 @@ export const ruleChainBreadcumbLabelFunction: BreadCrumbLabelFunction = ((route,
return label;
});
export const importRuleChainBreadcumbLabelFunction: BreadCrumbLabelFunction = ((route, translate, component) => {
export const importRuleChainBreadcumbLabelFunction: BreadCrumbLabelFunction<RuleChainPageComponent> =
((route, translate, component) => {
return `${translate.instant('rulechain.import')}: ${component.ruleChain.name}`;
});
@ -167,7 +169,7 @@ const routes: Routes = [
breadcrumb: {
labelFunction: ruleChainBreadcumbLabelFunction,
icon: 'settings_ethernet'
} as BreadCrumbConfig,
} as BreadCrumbConfig<RuleChainPageComponent>,
auth: [Authority.TENANT_ADMIN],
title: 'rulechain.rulechain',
import: false
@ -187,7 +189,7 @@ const routes: Routes = [
breadcrumb: {
labelFunction: importRuleChainBreadcumbLabelFunction,
icon: 'settings_ethernet'
} as BreadCrumbConfig,
} as BreadCrumbConfig<RuleChainPageComponent>,
auth: [Authority.TENANT_ADMIN],
title: 'rulechain.rulechain',
import: true

7
ui-ngx/src/app/modules/home/pages/rulechain/rulechain.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component } from '@angular/core';
import { Component, Inject } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { EntityComponent } from '../../components/entity/entity.component';
@ -22,6 +22,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActionNotificationShow } from '@core/notification/notification.actions';
import { TranslateService } from '@ngx-translate/core';
import { RuleChain } from '@shared/models/rule-chain.models';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
@Component({
selector: 'tb-rulechain',
@ -32,8 +33,10 @@ export class RuleChainComponent extends EntityComponent<RuleChain> {
constructor(protected store: Store<AppState>,
protected translate: TranslateService,
@Inject('entity') protected entityValue: RuleChain,
@Inject('entitiesTableConfig') protected entitiesTableConfig: EntityTableConfig<RuleChain>,
public fb: FormBuilder) {
super(store);
super(store, fb, entityValue, entitiesTableConfig);
}
hideDelete() {

7
ui-ngx/src/app/modules/home/pages/tenant/tenant.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component } from '@angular/core';
import { Component, Inject } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@ -23,6 +23,7 @@ import {Tenant} from '@app/shared/models/tenant.model';
import {ActionNotificationShow} from '@app/core/notification/notification.actions';
import {TranslateService} from '@ngx-translate/core';
import {ContactBasedComponent} from '../../components/entity/contact-based.component';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
@Component({
selector: 'tb-tenant',
@ -32,8 +33,10 @@ export class TenantComponent extends ContactBasedComponent<Tenant> {
constructor(protected store: Store<AppState>,
protected translate: TranslateService,
@Inject('entity') protected entityValue: Tenant,
@Inject('entitiesTableConfig') protected entitiesTableConfig: EntityTableConfig<Tenant>,
protected fb: FormBuilder) {
super(store, fb);
super(store, fb, entityValue, entitiesTableConfig);
}
hideDelete() {

7
ui-ngx/src/app/modules/home/pages/user/user.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component } from '@angular/core';
import { Component, Inject } from '@angular/core';
import { select, Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { EntityComponent } from '../../components/entity/entity.component';
@ -24,6 +24,7 @@ import { selectAuth } from '@core/auth/auth.selectors';
import { map } from 'rxjs/operators';
import { Authority } from '@shared/models/authority.enum';
import { isUndefined } from '@core/utils';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
@Component({
selector: 'tb-user',
@ -40,8 +41,10 @@ export class UserComponent extends EntityComponent<User> {
);
constructor(protected store: Store<AppState>,
@Inject('entity') protected entityValue: User,
@Inject('entitiesTableConfig') protected entitiesTableConfig: EntityTableConfig<User>,
public fb: FormBuilder) {
super(store);
super(store, fb, entityValue, entitiesTableConfig);
}
hideDelete() {

13
ui-ngx/src/app/modules/home/pages/widget/widget-library-routing.module.ts

@ -114,10 +114,11 @@ export class WidgetEditorAddDataResolver implements Resolve<WidgetEditorData> {
}
}
export const widgetTypesBreadcumbLabelFunction: BreadCrumbLabelFunction = ((route, translate) => route.data.widgetsBundle.title);
export const widgetTypesBreadcumbLabelFunction: BreadCrumbLabelFunction<any> = ((route, translate) =>
route.data.widgetsBundle.title);
export const widgetEditorBreadcumbLabelFunction: BreadCrumbLabelFunction =
((route, translate, component) => component ? (component as WidgetEditorComponent).widget.widgetName : '');
export const widgetEditorBreadcumbLabelFunction: BreadCrumbLabelFunction<WidgetEditorComponent> =
((route, translate, component) => component ? component.widget.widgetName : '');
export const routes: Routes = [
{
@ -146,7 +147,7 @@ export const routes: Routes = [
breadcrumb: {
labelFunction: widgetTypesBreadcumbLabelFunction,
icon: 'now_widgets'
} as BreadCrumbConfig
} as BreadCrumbConfig<any>
},
resolve: {
widgetsBundle: WidgetsBundleResolver
@ -173,7 +174,7 @@ export const routes: Routes = [
breadcrumb: {
labelFunction: widgetEditorBreadcumbLabelFunction,
icon: 'insert_chart'
} as BreadCrumbConfig
} as BreadCrumbConfig<WidgetEditorComponent>
},
resolve: {
widgetEditorData: WidgetEditorDataResolver
@ -189,7 +190,7 @@ export const routes: Routes = [
breadcrumb: {
labelFunction: widgetEditorBreadcumbLabelFunction,
icon: 'insert_chart'
} as BreadCrumbConfig
} as BreadCrumbConfig<WidgetEditorComponent>
},
resolve: {
widgetEditorData: WidgetEditorAddDataResolver

7
ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts

@ -14,12 +14,13 @@
/// limitations under the License.
///
import {Component} from '@angular/core';
import { Component, Inject } from '@angular/core';
import {Store} from '@ngrx/store';
import {AppState} from '@core/core.state';
import {EntityComponent} from '../../components/entity/entity.component';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {WidgetsBundle} from '@shared/models/widgets-bundle.model';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
@Component({
selector: 'tb-widgets-bundle',
@ -29,8 +30,10 @@ import {WidgetsBundle} from '@shared/models/widgets-bundle.model';
export class WidgetsBundleComponent extends EntityComponent<WidgetsBundle> {
constructor(protected store: Store<AppState>,
@Inject('entity') protected entityValue: WidgetsBundle,
@Inject('entitiesTableConfig') protected entitiesTableConfig: EntityTableConfig<WidgetsBundle>,
public fb: FormBuilder) {
super(store);
super(store, fb, entityValue, entitiesTableConfig);
}
hideDelete() {

2
ui-ngx/src/app/shared/components/breadcrumb.component.ts

@ -65,7 +65,7 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
buildBreadCrumbs(route: ActivatedRouteSnapshot, breadcrumbs: Array<BreadCrumb> = []): Array<BreadCrumb> {
let newBreadcrumbs = breadcrumbs;
if (route.routeConfig && route.routeConfig.data) {
const breadcrumbConfig = route.routeConfig.data.breadcrumb as BreadCrumbConfig;
const breadcrumbConfig = route.routeConfig.data.breadcrumb as BreadCrumbConfig<any>;
if (breadcrumbConfig && !breadcrumbConfig.skip) {
let label;
let labelFunction;

6
ui-ngx/src/app/shared/components/breadcrumb.ts

@ -27,10 +27,10 @@ export interface BreadCrumb {
queryParams: Params;
}
export type BreadCrumbLabelFunction = (route: ActivatedRouteSnapshot, translate: TranslateService, component: any) => string;
export type BreadCrumbLabelFunction<C> = (route: ActivatedRouteSnapshot, translate: TranslateService, component: C) => string;
export interface BreadCrumbConfig {
labelFunction: BreadCrumbLabelFunction;
export interface BreadCrumbConfig<C> {
labelFunction: BreadCrumbLabelFunction<C>;
label: string;
icon: string;
skip: boolean;

6
ui-ngx/src/app/shared/models/entity-type.models.ts

@ -15,6 +15,7 @@
///
import {TenantId} from './id/tenant-id';
import { BaseData, HasId } from '@shared/models/base-data';
///
/// Copyright © 2016-2019 The Thingsboard Authors
@ -63,8 +64,9 @@ export interface EntityTypeTranslation {
search?: string;
}
export interface EntityTypeResource {
export interface EntityTypeResource<T> {
helpLinkId: string;
helpLinkIdForEntity?(entity: T): string;
}
export const entityTypeTranslations = new Map<EntityType | AliasEntityType, EntityTypeTranslation>(
@ -223,7 +225,7 @@ export const entityTypeTranslations = new Map<EntityType | AliasEntityType, Enti
]
);
export const entityTypeResources = new Map<EntityType, EntityTypeResource>(
export const entityTypeResources = new Map<EntityType, EntityTypeResource<BaseData<HasId>>>(
[
[
EntityType.TENANT,

Loading…
Cancel
Save