Implemented calculated fields table
This commit is contained in:
		
							parent
							
								
									85119d0247
								
							
						
					
					
						commit
						bd34ed5011
					
				
							
								
								
									
										78
									
								
								ui-ngx/src/app/core/http/calculated-fields.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								ui-ngx/src/app/core/http/calculated-fields.service.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2024 The Thingsboard Authors
 | 
			
		||||
///
 | 
			
		||||
/// 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 { Injectable } from '@angular/core';
 | 
			
		||||
import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils';
 | 
			
		||||
import { Observable, of } from 'rxjs';
 | 
			
		||||
import { HttpClient } from '@angular/common/http';
 | 
			
		||||
import { PageData } from '@shared/models/page/page-data';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
// [TODO]: [Calculated fields] - implement when BE ready
 | 
			
		||||
export class CalculatedFieldsService {
 | 
			
		||||
 | 
			
		||||
  fieldsMock = [
 | 
			
		||||
    {
 | 
			
		||||
      name: 'Calculated Field 1',
 | 
			
		||||
      type: 'Simple',
 | 
			
		||||
      expression: '1 + 2',
 | 
			
		||||
      id: {
 | 
			
		||||
        id: '1',
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'Calculated Field 2',
 | 
			
		||||
      type: 'Script',
 | 
			
		||||
      expression: '${power}',
 | 
			
		||||
      id: {
 | 
			
		||||
        id: '2',
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private http: HttpClient
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  public getCalculatedField(calculatedFieldId: string, config?: RequestConfig): Observable<any> {
 | 
			
		||||
    return of(this.fieldsMock[0]);
 | 
			
		||||
    // return this.http.get<any>(`/api/calculated-field/${calculatedFieldId}`, defaultHttpOptionsFromConfig(config));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public saveCalculatedField(calculatedField: any, config?: RequestConfig): Observable<any> {
 | 
			
		||||
    return of(this.fieldsMock[1]);
 | 
			
		||||
    // return this.http.post<any>('/api/calculated-field', calculatedField, defaultHttpOptionsFromConfig(config));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public deleteCalculatedField(calculatedFieldId: string, config?: RequestConfig): Observable<boolean> {
 | 
			
		||||
    return of(true);
 | 
			
		||||
    // return this.http.delete<boolean>(`/api/calculated-field/${calculatedFieldId}`, defaultHttpOptionsFromConfig(config));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getCalculatedFields(query: any,
 | 
			
		||||
                   config?: RequestConfig): Observable<PageData<any>> {
 | 
			
		||||
    return of({
 | 
			
		||||
      data: this.fieldsMock,
 | 
			
		||||
      totalPages: 1,
 | 
			
		||||
      totalElements: 2,
 | 
			
		||||
      hasNext: false,
 | 
			
		||||
    });
 | 
			
		||||
    // return this.http.get<PageData<any>>(`/api/calculated-field${query.toQuery()}`,
 | 
			
		||||
    //   defaultHttpOptionsFromConfig(config));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,157 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2024 The Thingsboard Authors
 | 
			
		||||
///
 | 
			
		||||
/// 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 { EntityTableColumn, EntityTableConfig } from '@home/models/entity/entities-table-config.models';
 | 
			
		||||
import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import { Direction } from '@shared/models/page/sort-order';
 | 
			
		||||
import { MatDialog } from '@angular/material/dialog';
 | 
			
		||||
import { TimePageLink } from '@shared/models/page/page-link';
 | 
			
		||||
import { Observable, of } from 'rxjs';
 | 
			
		||||
import { PageData } from '@shared/models/page/page-data';
 | 
			
		||||
import { EntityId } from '@shared/models/id/entity-id';
 | 
			
		||||
import { DialogService } from '@core/services/dialog.service';
 | 
			
		||||
import { MINUTE } from '@shared/models/time/time.models';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { getCurrentAuthState } from '@core/auth/auth.selectors';
 | 
			
		||||
import { ChangeDetectorRef, DestroyRef, ViewContainerRef } from '@angular/core';
 | 
			
		||||
import { Overlay } from '@angular/cdk/overlay';
 | 
			
		||||
import { UtilsService } from '@core/services/utils.service';
 | 
			
		||||
import { EntityService } from '@core/http/entity.service';
 | 
			
		||||
import { EntityDebugSettings } from '@shared/models/entity.models';
 | 
			
		||||
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
 | 
			
		||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
 | 
			
		||||
import { TbPopoverService } from '@shared/components/popover.service';
 | 
			
		||||
import { EntityDebugSettingsPanelComponent } from '@home/components/entity/debug/entity-debug-settings-panel.component';
 | 
			
		||||
import { CalculatedFieldsService } from '@core/http/calculated-fields.service';
 | 
			
		||||
import { catchError, switchMap } from 'rxjs/operators';
 | 
			
		||||
 | 
			
		||||
export class CalculatedFieldsTableConfig extends EntityTableConfig<any, TimePageLink> {
 | 
			
		||||
 | 
			
		||||
  readonly calculatedFieldsDebugPerTenantLimitsConfiguration =
 | 
			
		||||
    getCurrentAuthState(this.store)['calculatedFieldsDebugPerTenantLimitsConfiguration'] || '1:1';
 | 
			
		||||
  readonly maxDebugModeDuration = getCurrentAuthState(this.store).maxDebugModeDurationMinutes * MINUTE;
 | 
			
		||||
 | 
			
		||||
  constructor(private calculatedFieldsService: CalculatedFieldsService,
 | 
			
		||||
              private entityService: EntityService,
 | 
			
		||||
              private dialogService: DialogService,
 | 
			
		||||
              private translate: TranslateService,
 | 
			
		||||
              private dialog: MatDialog,
 | 
			
		||||
              public entityId: EntityId = null,
 | 
			
		||||
              private store: Store<AppState>,
 | 
			
		||||
              private viewContainerRef: ViewContainerRef,
 | 
			
		||||
              private overlay: Overlay,
 | 
			
		||||
              private cd: ChangeDetectorRef,
 | 
			
		||||
              private utilsService: UtilsService,
 | 
			
		||||
              private durationLeft: DurationLeftPipe,
 | 
			
		||||
              private popoverService: TbPopoverService,
 | 
			
		||||
              private destroyRef: DestroyRef,
 | 
			
		||||
  ) {
 | 
			
		||||
    super();
 | 
			
		||||
    this.tableTitle = this.translate.instant('calculated-fields.label');
 | 
			
		||||
    this.detailsPanelEnabled = false;
 | 
			
		||||
    this.selectionEnabled = true;
 | 
			
		||||
    this.searchEnabled = true;
 | 
			
		||||
    this.addEnabled = true;
 | 
			
		||||
    this.entitiesDeleteEnabled = true;
 | 
			
		||||
    this.actionsColumnTitle = '';
 | 
			
		||||
    this.entityType = EntityType.CALCULATED_FIELDS;
 | 
			
		||||
    this.entityTranslations = entityTypeTranslations.get(EntityType.CALCULATED_FIELDS);
 | 
			
		||||
 | 
			
		||||
    this.entitiesFetchFunction = pageLink => this.fetchCalculatedFields(pageLink);
 | 
			
		||||
 | 
			
		||||
    this.defaultSortOrder = {property: 'name', direction: Direction.DESC};
 | 
			
		||||
 | 
			
		||||
    this.columns.push(
 | 
			
		||||
      new EntityTableColumn<any>('name', 'common.name', '33%'));
 | 
			
		||||
    this.columns.push(
 | 
			
		||||
      new EntityTableColumn<any>('type', 'common.type', '50px'));
 | 
			
		||||
    this.columns.push(
 | 
			
		||||
      new EntityTableColumn<any>('expression', 'calculated-fields.expression', '50%'));
 | 
			
		||||
 | 
			
		||||
    this.cellActionDescriptors.push(
 | 
			
		||||
      {
 | 
			
		||||
        name: '',
 | 
			
		||||
        nameFunction: (entity) => this.getDebugConfigLabel(entity?.debugSettings),
 | 
			
		||||
        icon: 'mdi:bug',
 | 
			
		||||
        isEnabled: () => true,
 | 
			
		||||
        iconFunction: ({ debugSettings }) => this.isDebugActive(debugSettings?.allEnabledUntil) || debugSettings?.failuresEnabled ? 'mdi:bug' : 'mdi:bug-outline',
 | 
			
		||||
        onAction: ($event, entity) => this.onOpenDebugConfig($event, entity),
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        name: this.translate.instant('action.edit'),
 | 
			
		||||
        icon: 'edit',
 | 
			
		||||
        isEnabled: () => true,
 | 
			
		||||
        // // [TODO]: [Calculated fields] - implement edit
 | 
			
		||||
        onAction: (_, entity) => {}
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fetchCalculatedFields(pageLink: TimePageLink): Observable<PageData<any>> {
 | 
			
		||||
    return this.calculatedFieldsService.getCalculatedFields(pageLink);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onOpenDebugConfig($event: Event, { debugSettings = {}, id }: any): void {
 | 
			
		||||
    const { renderer, viewContainerRef } = this.getTable();
 | 
			
		||||
    if ($event) {
 | 
			
		||||
      $event.stopPropagation();
 | 
			
		||||
    }
 | 
			
		||||
    const trigger = $event.target as Element;
 | 
			
		||||
    if (this.popoverService.hasPopover(trigger)) {
 | 
			
		||||
      this.popoverService.hidePopover(trigger);
 | 
			
		||||
    } else {
 | 
			
		||||
      const debugStrategyPopover = this.popoverService.displayPopover(trigger, renderer,
 | 
			
		||||
        viewContainerRef, EntityDebugSettingsPanelComponent, 'bottom', true, null,
 | 
			
		||||
        {
 | 
			
		||||
          debugLimitsConfiguration: this.calculatedFieldsDebugPerTenantLimitsConfiguration,
 | 
			
		||||
          maxDebugModeDuration: this.maxDebugModeDuration,
 | 
			
		||||
          entityLabel: this.translate.instant('debug-settings.integration'),
 | 
			
		||||
          ...debugSettings
 | 
			
		||||
        },
 | 
			
		||||
        {},
 | 
			
		||||
        {}, {}, true);
 | 
			
		||||
      debugStrategyPopover.tbComponentRef.instance.popover = debugStrategyPopover;
 | 
			
		||||
      debugStrategyPopover.tbComponentRef.instance.onSettingsApplied.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((settings: EntityDebugSettings) => {
 | 
			
		||||
        this.onDebugConfigChanged(id.id, settings);
 | 
			
		||||
        debugStrategyPopover.hide();
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private getDebugConfigLabel(debugSettings: EntityDebugSettings): string {
 | 
			
		||||
    const isDebugActive = this.isDebugActive(debugSettings?.allEnabledUntil);
 | 
			
		||||
 | 
			
		||||
    if (!isDebugActive) {
 | 
			
		||||
      return debugSettings?.failuresEnabled ? this.translate.instant('debug-settings.failures') : this.translate.instant('common.disabled');
 | 
			
		||||
    } else {
 | 
			
		||||
      return this.durationLeft.transform(debugSettings?.allEnabledUntil)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private isDebugActive(allEnabledUntil: number): boolean {
 | 
			
		||||
    return allEnabledUntil > new Date().getTime();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private onDebugConfigChanged(id: string, debugSettings: EntityDebugSettings): void {
 | 
			
		||||
    this.calculatedFieldsService.getCalculatedField(id).pipe(
 | 
			
		||||
      switchMap(field => this.calculatedFieldsService.saveCalculatedField({ ...field, debugSettings })),
 | 
			
		||||
      catchError(() => of(null)),
 | 
			
		||||
      takeUntilDestroyed(this.destroyRef),
 | 
			
		||||
    ).subscribe(() => this.updateData());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1 @@
 | 
			
		||||
<tb-entities-table [entitiesTableConfig]="calculatedFieldsTableConfig"></tb-entities-table>
 | 
			
		||||
@ -0,0 +1,104 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2024 The Thingsboard Authors
 | 
			
		||||
///
 | 
			
		||||
/// 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 {
 | 
			
		||||
  ChangeDetectionStrategy,
 | 
			
		||||
  ChangeDetectorRef,
 | 
			
		||||
  Component,
 | 
			
		||||
  DestroyRef,
 | 
			
		||||
  Input,
 | 
			
		||||
  OnInit,
 | 
			
		||||
  ViewChild,
 | 
			
		||||
  ViewContainerRef,
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import { EntityId } from '@shared/models/id/entity-id';
 | 
			
		||||
import { EntitiesTableComponent } from '@home/components/entity/entities-table.component';
 | 
			
		||||
import { EntityService } from '@core/http/entity.service';
 | 
			
		||||
import { DialogService } from '@core/services/dialog.service';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import { MatDialog } from '@angular/material/dialog';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { Overlay } from '@angular/cdk/overlay';
 | 
			
		||||
import { UtilsService } from '@core/services/utils.service';
 | 
			
		||||
import { CalculatedFieldsTableConfig } from '@home/components/calculated-fields/calculated-fields-table-config';
 | 
			
		||||
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
 | 
			
		||||
import { TbPopoverService } from '@shared/components/popover.service';
 | 
			
		||||
import { CalculatedFieldsService } from '@core/http/calculated-fields.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-calculated-fields-table',
 | 
			
		||||
  templateUrl: './calculated-fields-table.component.html',
 | 
			
		||||
  changeDetection: ChangeDetectionStrategy.OnPush,
 | 
			
		||||
})
 | 
			
		||||
export class CalculatedFieldsTableComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  @Input() entityId: EntityId;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  set active(active: boolean) {
 | 
			
		||||
    if (this.activeValue !== active) {
 | 
			
		||||
      this.activeValue = active;
 | 
			
		||||
      if (this.activeValue && this.dirtyValue) {
 | 
			
		||||
        this.dirtyValue = false;
 | 
			
		||||
        this.entitiesTable.updateData();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @ViewChild(EntitiesTableComponent, {static: true}) entitiesTable: EntitiesTableComponent;
 | 
			
		||||
 | 
			
		||||
  calculatedFieldsTableConfig: CalculatedFieldsTableConfig;
 | 
			
		||||
 | 
			
		||||
  private activeValue = false;
 | 
			
		||||
  private dirtyValue = false;
 | 
			
		||||
 | 
			
		||||
  constructor(private calculatedFieldsService: CalculatedFieldsService,
 | 
			
		||||
              private entityService: EntityService,
 | 
			
		||||
              private dialogService: DialogService,
 | 
			
		||||
              private translate: TranslateService,
 | 
			
		||||
              private dialog: MatDialog,
 | 
			
		||||
              private store: Store<AppState>,
 | 
			
		||||
              private overlay: Overlay,
 | 
			
		||||
              private viewContainerRef: ViewContainerRef,
 | 
			
		||||
              private cd: ChangeDetectorRef,
 | 
			
		||||
              private durationLeft: DurationLeftPipe,
 | 
			
		||||
              private popoverService: TbPopoverService,
 | 
			
		||||
              private destroyRef: DestroyRef,
 | 
			
		||||
              private utilsService: UtilsService) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.dirtyValue = !this.activeValue;
 | 
			
		||||
 | 
			
		||||
    this.calculatedFieldsTableConfig = new CalculatedFieldsTableConfig(
 | 
			
		||||
      this.calculatedFieldsService,
 | 
			
		||||
      this.entityService,
 | 
			
		||||
      this.dialogService,
 | 
			
		||||
      this.translate,
 | 
			
		||||
      this.dialog,
 | 
			
		||||
      this.entityId,
 | 
			
		||||
      this.store,
 | 
			
		||||
      this.viewContainerRef,
 | 
			
		||||
      this.overlay,
 | 
			
		||||
      this.cd,
 | 
			
		||||
      this.utilsService,
 | 
			
		||||
      this.durationLeft,
 | 
			
		||||
      this.popoverService,
 | 
			
		||||
      this.destroyRef
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -25,8 +25,10 @@ import {
 | 
			
		||||
  OnChanges,
 | 
			
		||||
  OnDestroy,
 | 
			
		||||
  OnInit,
 | 
			
		||||
  Renderer2,
 | 
			
		||||
  SimpleChanges,
 | 
			
		||||
  ViewChild
 | 
			
		||||
  ViewChild,
 | 
			
		||||
  ViewContainerRef,
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import { PageComponent } from '@shared/components/page.component';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
@ -141,7 +143,9 @@ export class EntitiesTableComponent extends PageComponent implements IEntitiesTa
 | 
			
		||||
              private router: Router,
 | 
			
		||||
              private elementRef: ElementRef,
 | 
			
		||||
              private fb: FormBuilder,
 | 
			
		||||
              private zone: NgZone) {
 | 
			
		||||
              private zone: NgZone,
 | 
			
		||||
              public viewContainerRef: ViewContainerRef,
 | 
			
		||||
              public renderer: Renderer2) {
 | 
			
		||||
    super(store);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -183,6 +183,8 @@ import {
 | 
			
		||||
} from '@home/components/dashboard-page/layout/select-dashboard-breakpoint.component';
 | 
			
		||||
import { EntityChipsComponent } from '@home/components/entity/entity-chips.component';
 | 
			
		||||
import { DashboardViewComponent } from '@home/components/dashboard-view/dashboard-view.component';
 | 
			
		||||
import { CalculatedFieldsTableComponent } from '@home/components/calculated-fields/calculated-fields-table.component';
 | 
			
		||||
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations:
 | 
			
		||||
@ -326,7 +328,8 @@ import { DashboardViewComponent } from '@home/components/dashboard-view/dashboar
 | 
			
		||||
      RateLimitsDetailsDialogComponent,
 | 
			
		||||
      SendNotificationButtonComponent,
 | 
			
		||||
      EntityChipsComponent,
 | 
			
		||||
      DashboardViewComponent
 | 
			
		||||
      DashboardViewComponent,
 | 
			
		||||
      CalculatedFieldsTableComponent,
 | 
			
		||||
    ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
@ -463,11 +466,13 @@ import { DashboardViewComponent } from '@home/components/dashboard-view/dashboar
 | 
			
		||||
    RateLimitsDetailsDialogComponent,
 | 
			
		||||
    SendNotificationButtonComponent,
 | 
			
		||||
    EntityChipsComponent,
 | 
			
		||||
    DashboardViewComponent
 | 
			
		||||
    DashboardViewComponent,
 | 
			
		||||
    CalculatedFieldsTableComponent,
 | 
			
		||||
  ],
 | 
			
		||||
  providers: [
 | 
			
		||||
    WidgetComponentService,
 | 
			
		||||
    CustomDialogService,
 | 
			
		||||
    DurationLeftPipe,
 | 
			
		||||
    {provide: EMBED_DASHBOARD_DIALOG_TOKEN, useValue: EmbedDashboardDialogComponent},
 | 
			
		||||
    {provide: COMPLEX_FILTER_PREDICATE_DIALOG_COMPONENT_TOKEN, useValue: ComplexFilterPredicateDialogComponent},
 | 
			
		||||
    {provide: DASHBOARD_PAGE_COMPONENT_TOKEN, useValue: DashboardPageComponent},
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,7 @@ import { SafeHtml } from '@angular/platform-browser';
 | 
			
		||||
import { PageLink } from '@shared/models/page/page-link';
 | 
			
		||||
import { Timewindow } from '@shared/models/time/time.models';
 | 
			
		||||
import { EntitiesDataSource } from '@home/models/datasource/entity-datasource';
 | 
			
		||||
import { ElementRef, EventEmitter } from '@angular/core';
 | 
			
		||||
import { ElementRef, EventEmitter, Renderer2, ViewContainerRef } from '@angular/core';
 | 
			
		||||
import { TbAnchorComponent } from '@shared/components/tb-anchor.component';
 | 
			
		||||
import { MatPaginator } from '@angular/material/paginator';
 | 
			
		||||
import { MatSort } from '@angular/material/sort';
 | 
			
		||||
@ -64,6 +64,8 @@ export interface IEntitiesTableComponent {
 | 
			
		||||
  paginator: MatPaginator;
 | 
			
		||||
  sort: MatSort;
 | 
			
		||||
  route: ActivatedRoute;
 | 
			
		||||
  viewContainerRef: ViewContainerRef;
 | 
			
		||||
  renderer: Renderer2;
 | 
			
		||||
 | 
			
		||||
  addEnabled(): boolean;
 | 
			
		||||
  clearSelection(): void;
 | 
			
		||||
 | 
			
		||||
@ -32,6 +32,10 @@
 | 
			
		||||
                      [entityName]="entity.name">
 | 
			
		||||
  </tb-attribute-table>
 | 
			
		||||
</mat-tab>
 | 
			
		||||
<mat-tab *ngIf="entity"
 | 
			
		||||
         label="{{ 'calculated-fields.label' | translate }}" #calculatedFieldsTab="matTab">
 | 
			
		||||
  <tb-calculated-fields-table [active]="calculatedFieldsTab.isActive" [entityId]="entity.id"/>
 | 
			
		||||
</mat-tab>
 | 
			
		||||
<mat-tab *ngIf="entity"
 | 
			
		||||
         label="{{ 'alarm.alarms' | translate }}" #alarmsTab="matTab">
 | 
			
		||||
  <tb-alarm-table [active]="alarmsTab.isActive" [entityId]="entity.id"></tb-alarm-table>
 | 
			
		||||
 | 
			
		||||
@ -49,7 +49,8 @@ export enum EntityType {
 | 
			
		||||
  OAUTH2_CLIENT = 'OAUTH2_CLIENT',
 | 
			
		||||
  DOMAIN = 'DOMAIN',
 | 
			
		||||
  MOBILE_APP_BUNDLE = 'MOBILE_APP_BUNDLE',
 | 
			
		||||
  MOBILE_APP = 'MOBILE_APP'
 | 
			
		||||
  MOBILE_APP = 'MOBILE_APP',
 | 
			
		||||
  CALCULATED_FIELDS = 'CALCULATED_FIELDS',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum AliasEntityType {
 | 
			
		||||
@ -478,6 +479,18 @@ export const entityTypeTranslations = new Map<EntityType | AliasEntityType, Enti
 | 
			
		||||
        noEntities: 'mobile.no-bundles',
 | 
			
		||||
        search: 'mobile.search-bundles'
 | 
			
		||||
      }
 | 
			
		||||
    ],
 | 
			
		||||
    [
 | 
			
		||||
      EntityType.CALCULATED_FIELDS,
 | 
			
		||||
      {
 | 
			
		||||
        type: 'calculated-fields.label',
 | 
			
		||||
        typePlural: 'calculated-fields.label',
 | 
			
		||||
        list: 'calculated-fields.list',
 | 
			
		||||
        add: 'action.add',
 | 
			
		||||
        noEntities: 'calculated-fields.no-found',
 | 
			
		||||
        search: 'action.search',
 | 
			
		||||
        selectedEntities: 'calculated-fields.selected-fields'
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  ]
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
@ -1003,6 +1003,13 @@
 | 
			
		||||
            "all-messages": "Save all debug events during time limit."
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "calculated-fields": {
 | 
			
		||||
        "label": "Calculated fields",
 | 
			
		||||
        "expression": "Expression",
 | 
			
		||||
        "no-found": "No calculated fields found",
 | 
			
		||||
        "list": "{ count, plural, =1 {One calculated field} other {List of # calculated fields} }",
 | 
			
		||||
        "selected-fields": "{ count, plural, =1 {1 calculated field} other {# calculated fields} } selected"
 | 
			
		||||
    },
 | 
			
		||||
    "confirm-on-exit": {
 | 
			
		||||
        "message": "You have unsaved changes. Are you sure you want to leave this page?",
 | 
			
		||||
        "html-message": "You have unsaved changes.<br/>Are you sure you want to leave this page?",
 | 
			
		||||
@ -1027,6 +1034,8 @@
 | 
			
		||||
        "city-max-length": "Specified city should be less than 256"
 | 
			
		||||
    },
 | 
			
		||||
    "common": {
 | 
			
		||||
        "name": "Name",
 | 
			
		||||
        "type": "Type",
 | 
			
		||||
        "username": "Username",
 | 
			
		||||
        "password": "Password",
 | 
			
		||||
        "enter-username": "Enter username",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user