Implement Events table
This commit is contained in:
		
							parent
							
								
									9d4b79c91c
								
							
						
					
					
						commit
						fea3c368a3
					
				@ -53,10 +53,11 @@ public class EventController extends BaseController {
 | 
			
		||||
            @RequestParam("tenantId") String strTenantId,
 | 
			
		||||
            @RequestParam int pageSize,
 | 
			
		||||
            @RequestParam int page,
 | 
			
		||||
            @RequestParam(required = false) String textSearch,
 | 
			
		||||
            @RequestParam(required = false) String sortProperty,
 | 
			
		||||
            @RequestParam(required = false) String sortOrder,
 | 
			
		||||
            @RequestParam(required = false) Long startTime,
 | 
			
		||||
            @RequestParam(required = false) Long endTime,
 | 
			
		||||
            @RequestParam(required = false, defaultValue = "false") boolean ascOrder
 | 
			
		||||
    ) throws ThingsboardException {
 | 
			
		||||
            @RequestParam(required = false) Long endTime) throws ThingsboardException {
 | 
			
		||||
        checkParameter("EntityId", strEntityId);
 | 
			
		||||
        checkParameter("EntityType", strEntityType);
 | 
			
		||||
        try {
 | 
			
		||||
@ -64,8 +65,7 @@ public class EventController extends BaseController {
 | 
			
		||||
 | 
			
		||||
            EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId);
 | 
			
		||||
            checkEntityId(entityId, Operation.READ);
 | 
			
		||||
            TimePageLink pageLink = createTimePageLink(pageSize, page, "",
 | 
			
		||||
                    "createdTime", ascOrder ? "asc" : "desc", startTime, endTime);
 | 
			
		||||
            TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
 | 
			
		||||
            return checkNotNull(eventService.findEvents(tenantId, entityId, eventType, pageLink));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
@ -81,10 +81,11 @@ public class EventController extends BaseController {
 | 
			
		||||
            @RequestParam("tenantId") String strTenantId,
 | 
			
		||||
            @RequestParam int pageSize,
 | 
			
		||||
            @RequestParam int page,
 | 
			
		||||
            @RequestParam(required = false) String textSearch,
 | 
			
		||||
            @RequestParam(required = false) String sortProperty,
 | 
			
		||||
            @RequestParam(required = false) String sortOrder,
 | 
			
		||||
            @RequestParam(required = false) Long startTime,
 | 
			
		||||
            @RequestParam(required = false) Long endTime,
 | 
			
		||||
            @RequestParam(required = false, defaultValue = "false") boolean ascOrder
 | 
			
		||||
    ) throws ThingsboardException {
 | 
			
		||||
            @RequestParam(required = false) Long endTime) throws ThingsboardException {
 | 
			
		||||
        checkParameter("EntityId", strEntityId);
 | 
			
		||||
        checkParameter("EntityType", strEntityType);
 | 
			
		||||
        try {
 | 
			
		||||
@ -93,8 +94,7 @@ public class EventController extends BaseController {
 | 
			
		||||
            EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId);
 | 
			
		||||
            checkEntityId(entityId, Operation.READ);
 | 
			
		||||
 | 
			
		||||
            TimePageLink pageLink = createTimePageLink(pageSize, page, "",
 | 
			
		||||
                    "createdTime", ascOrder ? "asc" : "desc", startTime, endTime);
 | 
			
		||||
            TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
 | 
			
		||||
 | 
			
		||||
            return checkNotNull(eventService.findEvents(tenantId, entityId, pageLink));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
 | 
			
		||||
@ -15,10 +15,10 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.dao.sql.event;
 | 
			
		||||
 | 
			
		||||
import org.springframework.data.domain.Page;
 | 
			
		||||
import org.springframework.data.domain.Pageable;
 | 
			
		||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 | 
			
		||||
import org.springframework.data.jpa.repository.Query;
 | 
			
		||||
import org.springframework.data.repository.CrudRepository;
 | 
			
		||||
import org.springframework.data.repository.PagingAndSortingRepository;
 | 
			
		||||
import org.springframework.data.repository.query.Param;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.dao.model.sql.EventEntity;
 | 
			
		||||
@ -30,7 +30,7 @@ import java.util.List;
 | 
			
		||||
 * Created by Valerii Sosliuk on 5/3/2017.
 | 
			
		||||
 */
 | 
			
		||||
@SqlDao
 | 
			
		||||
public interface EventRepository extends CrudRepository<EventEntity, String>, JpaSpecificationExecutor<EventEntity> {
 | 
			
		||||
public interface EventRepository extends PagingAndSortingRepository<EventEntity, String> {
 | 
			
		||||
 | 
			
		||||
    EventEntity findByTenantIdAndEntityTypeAndEntityIdAndEventTypeAndEventUid(String tenantId,
 | 
			
		||||
                                                                              EntityType entityType,
 | 
			
		||||
@ -51,4 +51,34 @@ public interface EventRepository extends CrudRepository<EventEntity, String>, Jp
 | 
			
		||||
                                                    @Param("eventType") String eventType,
 | 
			
		||||
                                                    Pageable pageable);
 | 
			
		||||
 | 
			
		||||
    @Query("SELECT e FROM EventEntity e WHERE " +
 | 
			
		||||
            "e.tenantId = :tenantId " +
 | 
			
		||||
            "AND e.entityType = :entityType AND e.entityId = :entityId " +
 | 
			
		||||
            "AND (:startId IS NULL OR e.id >= :startId) " +
 | 
			
		||||
            "AND (:endId IS NULL OR e.id <= :endId) " +
 | 
			
		||||
            "AND LOWER(e.eventType) LIKE LOWER(CONCAT(:textSearch, '%'))"
 | 
			
		||||
    )
 | 
			
		||||
    Page<EventEntity> findEventsByTenantIdAndEntityId(@Param("tenantId") String tenantId,
 | 
			
		||||
                                                      @Param("entityType") EntityType entityType,
 | 
			
		||||
                                                      @Param("entityId") String entityId,
 | 
			
		||||
                                                      @Param("textSearch") String textSearch,
 | 
			
		||||
                                                      @Param("startId") String startId,
 | 
			
		||||
                                                      @Param("endId") String endId,
 | 
			
		||||
                                                      Pageable pageable);
 | 
			
		||||
 | 
			
		||||
    @Query("SELECT e FROM EventEntity e WHERE " +
 | 
			
		||||
            "e.tenantId = :tenantId " +
 | 
			
		||||
            "AND e.entityType = :entityType AND e.entityId = :entityId " +
 | 
			
		||||
            "AND e.eventType = :eventType " +
 | 
			
		||||
            "AND (:startId IS NULL OR e.id >= :startId) " +
 | 
			
		||||
            "AND (:endId IS NULL OR e.id <= :endId)"
 | 
			
		||||
    )
 | 
			
		||||
    Page<EventEntity> findEventsByTenantIdAndEntityIdAndEventType(@Param("tenantId") String tenantId,
 | 
			
		||||
                                                                  @Param("entityType") EntityType entityType,
 | 
			
		||||
                                                                  @Param("entityId") String entityId,
 | 
			
		||||
                                                                  @Param("eventType") String eventType,
 | 
			
		||||
                                                                  @Param("startId") String startId,
 | 
			
		||||
                                                                  @Param("endId") String endId,
 | 
			
		||||
                                                                  Pageable pageable);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,8 +21,6 @@ import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.apache.commons.lang3.StringUtils;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.data.domain.PageRequest;
 | 
			
		||||
import org.springframework.data.domain.Pageable;
 | 
			
		||||
import org.springframework.data.domain.Sort;
 | 
			
		||||
import org.springframework.data.jpa.domain.Specification;
 | 
			
		||||
import org.springframework.data.repository.CrudRepository;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
@ -40,13 +38,11 @@ import org.thingsboard.server.dao.sql.JpaAbstractSearchTimeDao;
 | 
			
		||||
import org.thingsboard.server.dao.util.SqlDao;
 | 
			
		||||
 | 
			
		||||
import javax.persistence.criteria.Predicate;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
import static org.springframework.data.jpa.domain.Specifications.where;
 | 
			
		||||
import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY;
 | 
			
		||||
import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID;
 | 
			
		||||
import static org.thingsboard.server.dao.DaoUtil.endTimeToId;
 | 
			
		||||
import static org.thingsboard.server.dao.DaoUtil.startTimeToId;
 | 
			
		||||
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -109,15 +105,30 @@ public class JpaBaseEventDao extends JpaAbstractSearchTimeDao<EventEntity, Event
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PageData<Event> findEvents(UUID tenantId, EntityId entityId, TimePageLink pageLink) {
 | 
			
		||||
        return findEvents(tenantId, entityId, null, pageLink);
 | 
			
		||||
        return DaoUtil.toPageData(
 | 
			
		||||
                eventRepository
 | 
			
		||||
                        .findEventsByTenantIdAndEntityId(
 | 
			
		||||
                                fromTimeUUID(tenantId),
 | 
			
		||||
                                entityId.getEntityType(),
 | 
			
		||||
                                fromTimeUUID(entityId.getId()),
 | 
			
		||||
                                Objects.toString(pageLink.getTextSearch(), ""),
 | 
			
		||||
                                startTimeToId(pageLink.getStartTime()),
 | 
			
		||||
                                endTimeToId(pageLink.getEndTime()),
 | 
			
		||||
                                DaoUtil.toPageable(pageLink)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PageData<Event> findEvents(UUID tenantId, EntityId entityId, String eventType, TimePageLink pageLink) {
 | 
			
		||||
        Specification<EventEntity> timeSearchSpec = JpaAbstractSearchTimeDao.getTimeSearchPageSpec(pageLink, "id");
 | 
			
		||||
        Specification<EventEntity> fieldsSpec = getEntityFieldsSpec(tenantId, entityId, eventType);
 | 
			
		||||
        Pageable pageable = DaoUtil.toPageable(pageLink);
 | 
			
		||||
        return DaoUtil.toPageData(eventRepository.findAll(where(timeSearchSpec).and(fieldsSpec), pageable));
 | 
			
		||||
        return DaoUtil.toPageData(
 | 
			
		||||
                eventRepository
 | 
			
		||||
                        .findEventsByTenantIdAndEntityIdAndEventType(
 | 
			
		||||
                                fromTimeUUID(tenantId),
 | 
			
		||||
                                entityId.getEntityType(),
 | 
			
		||||
                                fromTimeUUID(entityId.getId()),
 | 
			
		||||
                                eventType,
 | 
			
		||||
                                startTimeToId(pageLink.getStartTime()),
 | 
			
		||||
                                endTimeToId(pageLink.getEndTime()),
 | 
			
		||||
                                DaoUtil.toPageable(pageLink)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										41
									
								
								ui-ngx/src/app/core/http/event.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								ui-ngx/src/app/core/http/event.service.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2019 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 { defaultHttpOptions } from './http-utils';
 | 
			
		||||
import { Observable } from 'rxjs/index';
 | 
			
		||||
import { HttpClient } from '@angular/common/http';
 | 
			
		||||
import { TimePageLink } from '@shared/models/page/page-link';
 | 
			
		||||
import { PageData } from '@shared/models/page/page-data';
 | 
			
		||||
import { EntityId } from '@shared/models/id/entity-id';
 | 
			
		||||
import { DebugEventType, Event, EventType } from '@shared/models/event.models';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
export class EventService {
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private http: HttpClient
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  public getEvents(entityId: EntityId, eventType: EventType | DebugEventType, tenantId: string, pageLink: TimePageLink,
 | 
			
		||||
                   ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<PageData<Event>> {
 | 
			
		||||
    return this.http.get<PageData<Event>>(`/api/events/${entityId.entityType}/${entityId.id}/${eventType}` +
 | 
			
		||||
              `${pageLink.toQuery()}&tenantId=${tenantId}`,
 | 
			
		||||
      defaultHttpOptions(ignoreLoading, ignoreErrors));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -37,14 +37,15 @@
 | 
			
		||||
        <mat-toolbar class="mat-table-toolbar" [fxShow]="!textSearchMode && dataSource.selection.isEmpty()">
 | 
			
		||||
          <div class="mat-toolbar-tools">
 | 
			
		||||
            <span *ngIf="entitiesTableConfig.tableTitle" class="tb-entity-table-title">{{ entitiesTableConfig.tableTitle }}</span>
 | 
			
		||||
            <tb-anchor #entityTableHeader></tb-anchor>
 | 
			
		||||
            <tb-timewindow *ngIf="entitiesTableConfig.useTimePageLink" [(ngModel)]="timewindow"
 | 
			
		||||
                            (ngModelChange)="onTimewindowChange()"
 | 
			
		||||
                            asButton historyOnly></tb-timewindow>
 | 
			
		||||
            <tb-anchor #entityTableHeader></tb-anchor>
 | 
			
		||||
            <span fxFlex *ngIf="!this.entitiesTableConfig.headerComponent"></span>
 | 
			
		||||
            <span fxFlex *ngIf="!entitiesTableConfig.headerComponent ||
 | 
			
		||||
                                entitiesTableConfig.useTimePageLink"></span>
 | 
			
		||||
            <div [fxShow]="addEnabled()">
 | 
			
		||||
              <button mat-button mat-icon-button [disabled]="isLoading$ | async"
 | 
			
		||||
                      *ngIf="!this.entitiesTableConfig.addActionDescriptors.length; else addActions"
 | 
			
		||||
                      *ngIf="!entitiesTableConfig.addActionDescriptors.length; else addActions"
 | 
			
		||||
                      (click)="addEntity($event)"
 | 
			
		||||
                      matTooltip="{{ translations.add | translate }}"
 | 
			
		||||
                      matTooltipPosition="above">
 | 
			
		||||
@ -52,12 +53,12 @@
 | 
			
		||||
              </button>
 | 
			
		||||
              <ng-template #addActions>
 | 
			
		||||
                <button mat-button mat-icon-button [disabled]="isLoading$ | async"
 | 
			
		||||
                        *ngIf="this.entitiesTableConfig.addActionDescriptors.length === 1; else addActionsMenu"
 | 
			
		||||
                        [fxShow]="this.entitiesTableConfig.addActionDescriptors[0].isEnabled()"
 | 
			
		||||
                        (click)="this.entitiesTableConfig.addActionDescriptors[0].onAction($event)"
 | 
			
		||||
                        matTooltip="{{ this.entitiesTableConfig.addActionDescriptors[0].name }}"
 | 
			
		||||
                        *ngIf="entitiesTableConfig.addActionDescriptors.length === 1; else addActionsMenu"
 | 
			
		||||
                        [fxShow]="entitiesTableConfig.addActionDescriptors[0].isEnabled()"
 | 
			
		||||
                        (click)="entitiesTableConfig.addActionDescriptors[0].onAction($event)"
 | 
			
		||||
                        matTooltip="{{ entitiesTableConfig.addActionDescriptors[0].name }}"
 | 
			
		||||
                        matTooltipPosition="above">
 | 
			
		||||
                  <mat-icon>{{this.entitiesTableConfig.addActionDescriptors[0].icon}}</mat-icon>
 | 
			
		||||
                  <mat-icon>{{entitiesTableConfig.addActionDescriptors[0].icon}}</mat-icon>
 | 
			
		||||
                </button>
 | 
			
		||||
                <ng-template #addActionsMenu>
 | 
			
		||||
                  <button mat-button mat-icon-button [disabled]="isLoading$ | async"
 | 
			
		||||
@ -67,7 +68,7 @@
 | 
			
		||||
                    <mat-icon>add</mat-icon>
 | 
			
		||||
                  </button>
 | 
			
		||||
                  <mat-menu #addActionsMenu="matMenu" xPosition="before">
 | 
			
		||||
                    <button mat-menu-item *ngFor="let actionDescriptor of this.entitiesTableConfig.addActionDescriptors"
 | 
			
		||||
                    <button mat-menu-item *ngFor="let actionDescriptor of entitiesTableConfig.addActionDescriptors"
 | 
			
		||||
                            [disabled]="isLoading$ | async"
 | 
			
		||||
                            [fxShow]="actionDescriptor.isEnabled()"
 | 
			
		||||
                            (click)="actionDescriptor.onAction($event)">
 | 
			
		||||
@ -152,10 +153,19 @@
 | 
			
		||||
              </mat-cell>
 | 
			
		||||
            </ng-container>
 | 
			
		||||
            <ng-container [matColumnDef]="column.key" *ngFor="let column of columns; trackBy: trackByColumnKey; let col = index">
 | 
			
		||||
              <mat-header-cell *matHeaderCellDef [ngStyle]="{maxWidth: column.maxWidth}" mat-sort-header [disabled]="!column.sortable"> {{ column.title | translate }} </mat-header-cell>
 | 
			
		||||
              <mat-header-cell *matHeaderCellDef [ngStyle]="headerCellStyle(column, col)" mat-sort-header [disabled]="!column.sortable"> {{ column.title | translate }} </mat-header-cell>
 | 
			
		||||
              <mat-cell *matCellDef="let entity; let row = index"
 | 
			
		||||
                        [innerHTML]="cellContent(entity, column, row, col)"
 | 
			
		||||
                        [ngStyle]="cellStyle(entity, column, row, col)"></mat-cell>
 | 
			
		||||
                        [ngStyle]="cellStyle(entity, column, row, col)">
 | 
			
		||||
                <button *ngIf="column.actionDescriptor; let actionDescriptor" mat-button mat-icon-button [disabled]="isLoading$ | async"
 | 
			
		||||
                        [fxShow]="actionDescriptor.isEnabled(entity)"
 | 
			
		||||
                        matTooltip="{{ actionDescriptor.nameFunction ? actionDescriptor.nameFunction(entity) : actionDescriptor.name }}"
 | 
			
		||||
                        matTooltipPosition="above"
 | 
			
		||||
                        (click)="actionDescriptor.onAction($event, entity)">
 | 
			
		||||
                  <mat-icon [svgIcon]="actionDescriptor.mdiIcon" [ngStyle]="actionDescriptor.style">
 | 
			
		||||
                    {{actionDescriptor.icon}}</mat-icon>
 | 
			
		||||
                </button>
 | 
			
		||||
              </mat-cell>
 | 
			
		||||
            </ng-container>
 | 
			
		||||
            <ng-container matColumnDef="actions" stickyEnd>
 | 
			
		||||
              <mat-header-cell *matHeaderCellDef [ngStyle.gt-md]="{ minWidth: (cellActionDescriptors.length * 40) + 'px', maxWidth: (cellActionDescriptors.length * 40) + 'px' }">
 | 
			
		||||
 | 
			
		||||
@ -42,7 +42,8 @@ import {
 | 
			
		||||
  EntityTableColumn,
 | 
			
		||||
  EntityTableConfig,
 | 
			
		||||
  GroupActionDescriptor,
 | 
			
		||||
  HeaderActionDescriptor
 | 
			
		||||
  HeaderActionDescriptor,
 | 
			
		||||
  EntityColumn
 | 
			
		||||
} from '@home/models/entity/entities-table-config.models';
 | 
			
		||||
import { EntityTypeTranslation } from '@shared/models/entity-type.models';
 | 
			
		||||
import { DialogService } from '@core/services/dialog.service';
 | 
			
		||||
@ -72,8 +73,10 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn
 | 
			
		||||
  groupActionDescriptors: Array<GroupActionDescriptor<BaseData<HasId>>>;
 | 
			
		||||
  cellActionDescriptors: Array<CellActionDescriptor<BaseData<HasId>>>;
 | 
			
		||||
 | 
			
		||||
  columns: Array<EntityTableColumn<BaseData<HasId>>>;
 | 
			
		||||
  displayedColumns: string[] = [];
 | 
			
		||||
  columns: Array<EntityColumn<BaseData<HasId>>>;
 | 
			
		||||
  displayedColumns: string[];
 | 
			
		||||
 | 
			
		||||
  headerCellStyleCache: Array<any> = [];
 | 
			
		||||
 | 
			
		||||
  cellContentCache: Array<SafeHtml> = [];
 | 
			
		||||
 | 
			
		||||
@ -143,22 +146,12 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    this.columns = [...this.entitiesTableConfig.columns];
 | 
			
		||||
 | 
			
		||||
    const enabledGroupActionDescriptors =
 | 
			
		||||
      this.groupActionDescriptors.filter((descriptor) => descriptor.isEnabled);
 | 
			
		||||
 | 
			
		||||
    this.selectionEnabled = this.entitiesTableConfig.selectionEnabled && enabledGroupActionDescriptors.length;
 | 
			
		||||
 | 
			
		||||
    if (this.selectionEnabled) {
 | 
			
		||||
      this.displayedColumns.push('select');
 | 
			
		||||
    }
 | 
			
		||||
    this.columns.forEach(
 | 
			
		||||
      (column) => {
 | 
			
		||||
        this.displayedColumns.push(column.key);
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
    this.displayedColumns.push('actions');
 | 
			
		||||
    this.columnsUpdated();
 | 
			
		||||
 | 
			
		||||
    const sortOrder: SortOrder = { property: this.entitiesTableConfig.defaultSortOrder.property,
 | 
			
		||||
                                   direction: this.entitiesTableConfig.defaultSortOrder.direction };
 | 
			
		||||
@ -235,6 +228,7 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private dataLoaded() {
 | 
			
		||||
    this.headerCellStyleCache.length = 0;
 | 
			
		||||
    this.cellContentCache.length = 0;
 | 
			
		||||
    this.cellStyleCache.length = 0;
 | 
			
		||||
  }
 | 
			
		||||
@ -365,21 +359,65 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cellContent(entity: BaseData<HasId>, column: EntityTableColumn<BaseData<HasId>>, row: number, col: number) {
 | 
			
		||||
    const index = row * this.columns.length + col;
 | 
			
		||||
    let res = this.cellContentCache[index];
 | 
			
		||||
  columnsUpdated(resetData: boolean = false) {
 | 
			
		||||
    this.columns = [...this.entitiesTableConfig.columns];
 | 
			
		||||
 | 
			
		||||
    this.displayedColumns = [];
 | 
			
		||||
 | 
			
		||||
    if (this.selectionEnabled) {
 | 
			
		||||
      this.displayedColumns.push('select');
 | 
			
		||||
    }
 | 
			
		||||
    this.columns.forEach(
 | 
			
		||||
      (column) => {
 | 
			
		||||
        this.displayedColumns.push(column.key);
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
    this.displayedColumns.push('actions');
 | 
			
		||||
    this.headerCellStyleCache.length = 0;
 | 
			
		||||
    this.cellContentCache.length = 0;
 | 
			
		||||
    this.cellStyleCache.length = 0;
 | 
			
		||||
    if (resetData) {
 | 
			
		||||
      this.dataSource.reset();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  headerCellStyle(column: EntityColumn<BaseData<HasId>>, col: number) {
 | 
			
		||||
    const index = col;
 | 
			
		||||
    let res = this.headerCellStyleCache[index];
 | 
			
		||||
    if (!res) {
 | 
			
		||||
      res = this.domSanitizer.bypassSecurityTrustHtml(column.cellContentFunction(entity, column.key));
 | 
			
		||||
      this.cellContentCache[index] = res;
 | 
			
		||||
      if (column instanceof EntityTableColumn) {
 | 
			
		||||
        res = {...column.headerCellStyleFunction(column.key), ...{maxWidth: column.maxWidth}};
 | 
			
		||||
      } else {
 | 
			
		||||
        res = {maxWidth: column.maxWidth};
 | 
			
		||||
      }
 | 
			
		||||
      this.headerCellStyleCache[index] = res;
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cellStyle(entity: BaseData<HasId>, column: EntityTableColumn<BaseData<HasId>>, row: number, col: number) {
 | 
			
		||||
  cellContent(entity: BaseData<HasId>, column: EntityColumn<BaseData<HasId>>, row: number, col: number) {
 | 
			
		||||
    if (column instanceof EntityTableColumn) {
 | 
			
		||||
      const index = row * this.columns.length + col;
 | 
			
		||||
      let res = this.cellContentCache[index];
 | 
			
		||||
      if (!res) {
 | 
			
		||||
        res = this.domSanitizer.bypassSecurityTrustHtml(column.cellContentFunction(entity, column.key));
 | 
			
		||||
        this.cellContentCache[index] = res;
 | 
			
		||||
      }
 | 
			
		||||
      return res;
 | 
			
		||||
    } else {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cellStyle(entity: BaseData<HasId>, column: EntityColumn<BaseData<HasId>>, row: number, col: number) {
 | 
			
		||||
    const index = row * this.columns.length + col;
 | 
			
		||||
    let res = this.cellStyleCache[index];
 | 
			
		||||
    if (!res) {
 | 
			
		||||
      res = {...column.cellStyleFunction(entity, column.key), ...{maxWidth: column.maxWidth}};
 | 
			
		||||
      if (column instanceof EntityTableColumn) {
 | 
			
		||||
        res = {...column.cellStyleFunction(entity, column.key), ...{maxWidth: column.maxWidth}};
 | 
			
		||||
      } else {
 | 
			
		||||
        res = {maxWidth: column.maxWidth};
 | 
			
		||||
      }
 | 
			
		||||
      this.cellStyleCache[index] = res;
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
 | 
			
		||||
@ -37,6 +37,8 @@ import { selectAuthUser, getCurrentAuthUser } from '@core/auth/auth.selectors';
 | 
			
		||||
import { AuthUser } from '@shared/models/user.model';
 | 
			
		||||
import { EntityType } from '@shared/models/entity-type.models';
 | 
			
		||||
import { AuditLogMode } from '@shared/models/audit-log.models';
 | 
			
		||||
import { DebugEventType, EventType } from '@shared/models/event.models';
 | 
			
		||||
import { NULL_UUID } from '@shared/models/id/has-uuid';
 | 
			
		||||
 | 
			
		||||
export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends PageComponent implements OnInit, AfterViewInit {
 | 
			
		||||
 | 
			
		||||
@ -46,8 +48,14 @@ export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends Pag
 | 
			
		||||
 | 
			
		||||
  auditLogModes = AuditLogMode;
 | 
			
		||||
 | 
			
		||||
  eventTypes = EventType;
 | 
			
		||||
 | 
			
		||||
  debugEventTypes = DebugEventType;
 | 
			
		||||
 | 
			
		||||
  authUser: AuthUser;
 | 
			
		||||
 | 
			
		||||
  nullUid = NULL_UUID;
 | 
			
		||||
 | 
			
		||||
  entityValue: T;
 | 
			
		||||
 | 
			
		||||
  @ViewChildren(MatTab) entityTabs: QueryList<MatTab>;
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,212 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2019 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 {
 | 
			
		||||
  DateEntityTableColumn,
 | 
			
		||||
  EntityActionTableColumn,
 | 
			
		||||
  EntityTableColumn,
 | 
			
		||||
  EntityTableConfig
 | 
			
		||||
} from '@home/models/entity/entities-table-config.models';
 | 
			
		||||
import { DebugEventType, Event, EventType } from '@shared/models/event.models';
 | 
			
		||||
import { TimePageLink } from '@shared/models/page/page-link';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import { DatePipe } from '@angular/common';
 | 
			
		||||
import { MatDialog } from '@angular/material/dialog';
 | 
			
		||||
import { EntityId } from '@shared/models/id/entity-id';
 | 
			
		||||
import { EventService } from '@app/core/http/event.service';
 | 
			
		||||
import { EventTableHeaderComponent } from '@home/components/event/event-table-header.component';
 | 
			
		||||
import { EntityTypeResource } from '@shared/models/entity-type.models';
 | 
			
		||||
import { Observable } from 'rxjs';
 | 
			
		||||
import { PageData } from '@shared/models/page/page-data';
 | 
			
		||||
import { Direction } from '@shared/models/page/sort-order';
 | 
			
		||||
import { MsgDataType } from '@shared/models/rule-node.models';
 | 
			
		||||
import { DialogService } from '@core/services/dialog.service';
 | 
			
		||||
 | 
			
		||||
export class EventTableConfig extends EntityTableConfig<Event, TimePageLink> {
 | 
			
		||||
 | 
			
		||||
  eventTypeValue: EventType | DebugEventType;
 | 
			
		||||
 | 
			
		||||
  set eventType(eventType: EventType | DebugEventType) {
 | 
			
		||||
    if (this.eventTypeValue !== eventType) {
 | 
			
		||||
      this.eventTypeValue = eventType;
 | 
			
		||||
      this.updateColumns(true);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get eventType(): EventType | DebugEventType {
 | 
			
		||||
    return this.eventTypeValue;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  eventTypes: Array<EventType | DebugEventType>;
 | 
			
		||||
 | 
			
		||||
  constructor(private eventService: EventService,
 | 
			
		||||
              private dialogService: DialogService,
 | 
			
		||||
              private translate: TranslateService,
 | 
			
		||||
              private datePipe: DatePipe,
 | 
			
		||||
              private dialog: MatDialog,
 | 
			
		||||
              public entityId: EntityId,
 | 
			
		||||
              public tenantId: string,
 | 
			
		||||
              private defaultEventType: EventType | DebugEventType,
 | 
			
		||||
              private disabledEventTypes: Array<EventType | DebugEventType> = null,
 | 
			
		||||
              private debugEventTypes: Array<DebugEventType> = null) {
 | 
			
		||||
    super();
 | 
			
		||||
    this.loadDataOnInit = false;
 | 
			
		||||
    this.tableTitle = '';
 | 
			
		||||
    this.useTimePageLink = true;
 | 
			
		||||
    this.detailsPanelEnabled = false;
 | 
			
		||||
    this.selectionEnabled = false;
 | 
			
		||||
    this.searchEnabled = false;
 | 
			
		||||
    this.addEnabled = false;
 | 
			
		||||
    this.entitiesDeleteEnabled = false;
 | 
			
		||||
 | 
			
		||||
    this.headerComponent = EventTableHeaderComponent;
 | 
			
		||||
 | 
			
		||||
    this.eventTypes = Object.keys(EventType).map(type => EventType[type]);
 | 
			
		||||
 | 
			
		||||
    if (disabledEventTypes && disabledEventTypes.length) {
 | 
			
		||||
      this.eventTypes = this.eventTypes.filter(type => disabledEventTypes.indexOf(type) === -1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (debugEventTypes && debugEventTypes.length) {
 | 
			
		||||
      this.eventTypes = [...this.eventTypes, ...debugEventTypes];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.eventTypeValue = defaultEventType;
 | 
			
		||||
 | 
			
		||||
    this.entityTranslations = {
 | 
			
		||||
      noEntities: 'event.no-events-prompt'
 | 
			
		||||
    };
 | 
			
		||||
    this.entityResources = {
 | 
			
		||||
    } as EntityTypeResource;
 | 
			
		||||
    this.entitiesFetchFunction = pageLink => this.fetchEvents(pageLink);
 | 
			
		||||
 | 
			
		||||
    this.defaultSortOrder = {property: 'createdTime', direction: Direction.DESC};
 | 
			
		||||
 | 
			
		||||
    this.updateColumns();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fetchEvents(pageLink: TimePageLink): Observable<PageData<Event>> {
 | 
			
		||||
    return this.eventService.getEvents(this.entityId, this.eventType, this.tenantId, pageLink);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  updateColumns(updateTableColumns: boolean = false): void {
 | 
			
		||||
    this.columns = [];
 | 
			
		||||
    this.columns.push(
 | 
			
		||||
      new DateEntityTableColumn<Event>('createdTime', 'event.event-time', this.datePipe, '150px'),
 | 
			
		||||
      new EntityTableColumn<Event>('server', 'event.server', '150px',
 | 
			
		||||
        (entity) => entity.body.server, entity => ({}), false));
 | 
			
		||||
    switch (this.eventType) {
 | 
			
		||||
      case EventType.ERROR:
 | 
			
		||||
        this.columns.push(
 | 
			
		||||
        new EntityTableColumn<Event>('method', 'event.method', '100%',
 | 
			
		||||
          (entity) => entity.body.method, entity => ({}), false),
 | 
			
		||||
          new EntityActionTableColumn<Event>('error', 'event.error',
 | 
			
		||||
            {
 | 
			
		||||
              name: this.translate.instant('action.view'),
 | 
			
		||||
              icon: 'more_horiz',
 | 
			
		||||
              isEnabled: (entity) => entity.body.error && entity.body.error.length > 0,
 | 
			
		||||
              onAction: ($event, entity) => this.showContent($event, entity.body.error, 'event.error')
 | 
			
		||||
            },
 | 
			
		||||
            '100px')
 | 
			
		||||
        );
 | 
			
		||||
        break;
 | 
			
		||||
      case EventType.LC_EVENT:
 | 
			
		||||
        this.columns.push(
 | 
			
		||||
          new EntityTableColumn<Event>('method', 'event.event', '100%',
 | 
			
		||||
            (entity) => entity.body.event, entity => ({}), false),
 | 
			
		||||
          new EntityTableColumn<Event>('status', 'event.status', '100%',
 | 
			
		||||
            (entity) =>
 | 
			
		||||
              this.translate.instant(entity.body.success ? 'event.success' : 'event.failed'), entity => ({}), false),
 | 
			
		||||
          new EntityActionTableColumn<Event>('error', 'event.error',
 | 
			
		||||
            {
 | 
			
		||||
              name: this.translate.instant('action.view'),
 | 
			
		||||
              icon: 'more_horiz',
 | 
			
		||||
              isEnabled: (entity) => entity.body.error && entity.body.error.length > 0,
 | 
			
		||||
              onAction: ($event, entity) => this.showContent($event, entity.body.error, 'event.error')
 | 
			
		||||
            },
 | 
			
		||||
            '100px')
 | 
			
		||||
        );
 | 
			
		||||
        break;
 | 
			
		||||
      case EventType.STATS:
 | 
			
		||||
        this.columns.push(
 | 
			
		||||
          new EntityTableColumn<Event>('messagesProcessed', 'event.messages-processed', '100%',
 | 
			
		||||
            (entity) => entity.body.messagesProcessed + '',
 | 
			
		||||
              entity => ({justifyContent: 'flex-end'}),
 | 
			
		||||
            false,
 | 
			
		||||
            key => ({justifyContent: 'flex-end'})),
 | 
			
		||||
          new EntityTableColumn<Event>('errorsOccurred', 'event.errors-occurred', '100%',
 | 
			
		||||
            (entity) => entity.body.errorsOccurred + '',
 | 
			
		||||
              entity => ({justifyContent: 'flex-end'}),
 | 
			
		||||
            false,
 | 
			
		||||
            key => ({justifyContent: 'flex-end'}))
 | 
			
		||||
        );
 | 
			
		||||
        break;
 | 
			
		||||
      case DebugEventType.DEBUG_RULE_NODE:
 | 
			
		||||
      case DebugEventType.DEBUG_RULE_CHAIN:
 | 
			
		||||
        this.columns.push(
 | 
			
		||||
          new EntityTableColumn<Event>('type', 'event.type', '100%',
 | 
			
		||||
            (entity) => entity.body.type, entity => ({}), false),
 | 
			
		||||
          new EntityTableColumn<Event>('entity', 'event.entity', '100%',
 | 
			
		||||
            (entity) => entity.body.entityName, entity => ({}), false),
 | 
			
		||||
          new EntityTableColumn<Event>('msgId', 'event.message-id', '100%',
 | 
			
		||||
            (entity) => entity.body.msgId, entity => ({}), false),
 | 
			
		||||
          new EntityTableColumn<Event>('msgType', 'event.message-type', '100%',
 | 
			
		||||
            (entity) => entity.body.msgType, entity => ({}), false),
 | 
			
		||||
          new EntityTableColumn<Event>('relationType', 'event.relation-type', '100%',
 | 
			
		||||
            (entity) => entity.body.relationType, entity => ({}), false),
 | 
			
		||||
          new EntityActionTableColumn<Event>('data', 'event.data',
 | 
			
		||||
            {
 | 
			
		||||
              name: this.translate.instant('action.view'),
 | 
			
		||||
              icon: 'more_horiz',
 | 
			
		||||
              isEnabled: (entity) => entity.body.data && entity.body.data.length > 0,
 | 
			
		||||
              onAction: ($event, entity) => this.showContent($event, entity.body.data,
 | 
			
		||||
                'event.data', entity.body.dataType)
 | 
			
		||||
            },
 | 
			
		||||
            '60px'),
 | 
			
		||||
          new EntityActionTableColumn<Event>('metadata', 'event.metadata',
 | 
			
		||||
            {
 | 
			
		||||
              name: this.translate.instant('action.view'),
 | 
			
		||||
              icon: 'more_horiz',
 | 
			
		||||
              isEnabled: (entity) => entity.body.metadata && entity.body.metadata.length > 0,
 | 
			
		||||
              onAction: ($event, entity) => this.showContent($event, entity.body.metadata,
 | 
			
		||||
                'event.metadata', MsgDataType.JSON)
 | 
			
		||||
            },
 | 
			
		||||
            '60px'),
 | 
			
		||||
          new EntityActionTableColumn<Event>('error', 'event.error',
 | 
			
		||||
            {
 | 
			
		||||
              name: this.translate.instant('action.view'),
 | 
			
		||||
              icon: 'more_horiz',
 | 
			
		||||
              isEnabled: (entity) => entity.body.error && entity.body.error.length > 0,
 | 
			
		||||
              onAction: ($event, entity) => this.showContent($event, entity.body.error,
 | 
			
		||||
                'event.error')
 | 
			
		||||
            },
 | 
			
		||||
            '60px')
 | 
			
		||||
        );
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    if (updateTableColumns) {
 | 
			
		||||
      this.table.columnsUpdated(true);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  showContent($event: MouseEvent, content: string, title: string, contentType: MsgDataType = null): void {
 | 
			
		||||
    if ($event) {
 | 
			
		||||
      $event.stopPropagation();
 | 
			
		||||
    }
 | 
			
		||||
    // TODO:
 | 
			
		||||
    this.dialogService.todo();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,27 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2019 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.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<mat-form-field class="mat-block" style="width: 200px;">
 | 
			
		||||
  <mat-label translate>event.event-type</mat-label>
 | 
			
		||||
  <mat-select matInput [ngModel]="eventTableConfig.eventType"
 | 
			
		||||
              (ngModelChange)="eventTypeChanged($event)">
 | 
			
		||||
    <mat-option *ngFor="let type of eventTableConfig.eventTypes" [value]="type">
 | 
			
		||||
      {{ eventTypeTranslationsMap.get(type) | translate }}
 | 
			
		||||
    </mat-option>
 | 
			
		||||
  </mat-select>
 | 
			
		||||
</mat-form-field>
 | 
			
		||||
@ -0,0 +1,35 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2019 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.
 | 
			
		||||
 */
 | 
			
		||||
:host {
 | 
			
		||||
/*  flex: 1;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: flex-start; */
 | 
			
		||||
  padding-right: 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:host ::ng-deep {
 | 
			
		||||
  mat-form-field {
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
 | 
			
		||||
    .mat-form-field-wrapper {
 | 
			
		||||
      padding-bottom: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .mat-form-field-underline {
 | 
			
		||||
      bottom: 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,45 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2019 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 { Component } from '@angular/core';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { EntityTableHeaderComponent } from '../../components/entity/entity-table-header.component';
 | 
			
		||||
import { DebugEventType, Event, EventType, eventTypeTranslations } from '@app/shared/models/event.models';
 | 
			
		||||
import { EventTableConfig } from '@home/components/event/event-table-config';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-event-table-header',
 | 
			
		||||
  templateUrl: './event-table-header.component.html',
 | 
			
		||||
  styleUrls: ['./event-table-header.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class EventTableHeaderComponent extends EntityTableHeaderComponent<Event> {
 | 
			
		||||
 | 
			
		||||
  eventTypeTranslationsMap = eventTypeTranslations;
 | 
			
		||||
 | 
			
		||||
  get eventTableConfig(): EventTableConfig {
 | 
			
		||||
    return this.entitiesTableConfig as EventTableConfig;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  constructor(protected store: Store<AppState>) {
 | 
			
		||||
    super(store);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  eventTypeChanged(eventType: EventType | DebugEventType) {
 | 
			
		||||
    this.eventTableConfig.eventType = eventType;
 | 
			
		||||
    this.eventTableConfig.table.updateData();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,18 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2019 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.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<tb-entities-table [entitiesTableConfig]="eventTableConfig"></tb-entities-table>
 | 
			
		||||
@ -0,0 +1,22 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2019 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.
 | 
			
		||||
 */
 | 
			
		||||
:host ::ng-deep {
 | 
			
		||||
  tb-entities-table {
 | 
			
		||||
    .mat-drawer-container {
 | 
			
		||||
      background-color: white;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,112 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2019 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 { Component, Input, OnInit, ViewChild } from '@angular/core';
 | 
			
		||||
import { AuditLogService } from '@core/http/audit-log.service';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import { DatePipe } from '@angular/common';
 | 
			
		||||
import { MatDialog } from '@angular/material';
 | 
			
		||||
import { AuditLogMode } from '@shared/models/audit-log.models';
 | 
			
		||||
import { EntityId } from '@shared/models/id/entity-id';
 | 
			
		||||
import { UserId } from '@shared/models/id/user-id';
 | 
			
		||||
import { CustomerId } from '@shared/models/id/customer-id';
 | 
			
		||||
import { AuditLogTableConfig } from '@home/components/audit-log/audit-log-table-config';
 | 
			
		||||
import { EntitiesTableComponent } from '@home/components/entity/entities-table.component';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { Authority } from '@shared/models/authority.enum';
 | 
			
		||||
import { getCurrentAuthUser } from '@core/auth/auth.selectors';
 | 
			
		||||
import { EventTableConfig } from './event-table-config';
 | 
			
		||||
import { EventService } from '@core/http/event.service';
 | 
			
		||||
import { DialogService } from '@core/services/dialog.service';
 | 
			
		||||
import { DebugEventType, EventType } from '@shared/models/event.models';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-event-table',
 | 
			
		||||
  templateUrl: './event-table.component.html',
 | 
			
		||||
  styleUrls: ['./event-table.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class EventTableComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  tenantId: string;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  defaultEventType: EventType | DebugEventType;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  disabledEventTypes: Array<EventType | DebugEventType>;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  debugEventTypes: Array<DebugEventType>;
 | 
			
		||||
 | 
			
		||||
  activeValue = false;
 | 
			
		||||
  dirtyValue = false;
 | 
			
		||||
  entityIdValue: EntityId;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  set active(active: boolean) {
 | 
			
		||||
    if (this.activeValue !== active) {
 | 
			
		||||
      this.activeValue = active;
 | 
			
		||||
      if (this.activeValue && this.dirtyValue) {
 | 
			
		||||
        this.dirtyValue = false;
 | 
			
		||||
        this.entitiesTable.updateData();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  set entityId(entityId: EntityId) {
 | 
			
		||||
    this.entityIdValue = entityId;
 | 
			
		||||
    if (this.eventTableConfig && this.eventTableConfig.entityId !== entityId) {
 | 
			
		||||
      this.eventTableConfig.eventType = this.defaultEventType;
 | 
			
		||||
      this.eventTableConfig.entityId = entityId;
 | 
			
		||||
      this.entitiesTable.resetSortAndFilter(this.activeValue);
 | 
			
		||||
      if (!this.activeValue) {
 | 
			
		||||
        this.dirtyValue = true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @ViewChild(EntitiesTableComponent, {static: true}) entitiesTable: EntitiesTableComponent;
 | 
			
		||||
 | 
			
		||||
  eventTableConfig: EventTableConfig;
 | 
			
		||||
 | 
			
		||||
  constructor(private eventService: EventService,
 | 
			
		||||
              private dialogService: DialogService,
 | 
			
		||||
              private translate: TranslateService,
 | 
			
		||||
              private datePipe: DatePipe,
 | 
			
		||||
              private dialog: MatDialog,
 | 
			
		||||
              private store: Store<AppState>) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.dirtyValue = !this.activeValue;
 | 
			
		||||
    this.eventTableConfig = new EventTableConfig(
 | 
			
		||||
      this.eventService,
 | 
			
		||||
      this.dialogService,
 | 
			
		||||
      this.translate,
 | 
			
		||||
      this.datePipe,
 | 
			
		||||
      this.dialog,
 | 
			
		||||
      this.entityIdValue,
 | 
			
		||||
      this.tenantId,
 | 
			
		||||
      this.defaultEventType,
 | 
			
		||||
      this.disabledEventTypes,
 | 
			
		||||
      this.debugEventTypes
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -24,11 +24,14 @@ import {EntityDetailsPanelComponent} from './entity/entity-details-panel.compone
 | 
			
		||||
import {ContactComponent} from './contact.component';
 | 
			
		||||
import { AuditLogDetailsDialogComponent } from './audit-log/audit-log-details-dialog.component';
 | 
			
		||||
import { AuditLogTableComponent } from './audit-log/audit-log-table.component';
 | 
			
		||||
import { EventTableHeaderComponent } from '@home/components/event/event-table-header.component';
 | 
			
		||||
import { EventTableComponent } from '@home/components/event/event-table.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  entryComponents: [
 | 
			
		||||
    AddEntityDialogComponent,
 | 
			
		||||
    AuditLogDetailsDialogComponent
 | 
			
		||||
    AuditLogDetailsDialogComponent,
 | 
			
		||||
    EventTableHeaderComponent
 | 
			
		||||
  ],
 | 
			
		||||
  declarations:
 | 
			
		||||
    [
 | 
			
		||||
@ -38,7 +41,9 @@ import { AuditLogTableComponent } from './audit-log/audit-log-table.component';
 | 
			
		||||
      EntityDetailsPanelComponent,
 | 
			
		||||
      ContactComponent,
 | 
			
		||||
      AuditLogTableComponent,
 | 
			
		||||
      AuditLogDetailsDialogComponent
 | 
			
		||||
      AuditLogDetailsDialogComponent,
 | 
			
		||||
      EventTableHeaderComponent,
 | 
			
		||||
      EventTableComponent
 | 
			
		||||
    ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
@ -50,7 +55,8 @@ import { AuditLogTableComponent } from './audit-log/audit-log-table.component';
 | 
			
		||||
    DetailsPanelComponent,
 | 
			
		||||
    EntityDetailsPanelComponent,
 | 
			
		||||
    ContactComponent,
 | 
			
		||||
    AuditLogTableComponent
 | 
			
		||||
    AuditLogTableComponent,
 | 
			
		||||
    EventTableComponent
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export class HomeComponentsModule { }
 | 
			
		||||
 | 
			
		||||
@ -50,6 +50,13 @@ export class EntitiesDataSource<T extends BaseData<HasId>, P extends PageLink =
 | 
			
		||||
    this.pageDataSubject.complete();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  reset() {
 | 
			
		||||
    const pageData = emptyPageData<T>();
 | 
			
		||||
    this.entitiesSubject.next(pageData.data);
 | 
			
		||||
    this.pageDataSubject.next(pageData);
 | 
			
		||||
    this.dataLoadedFunction();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  loadEntities(pageLink: P): Observable<PageData<T>> {
 | 
			
		||||
    const result = new ReplaySubject<PageData<T>>();
 | 
			
		||||
    this.fetchFunction(pageLink).pipe(
 | 
			
		||||
 | 
			
		||||
@ -41,6 +41,7 @@ export type EntityActionFunction<T extends BaseData<HasId>> = (action: EntityAct
 | 
			
		||||
export type CreateEntityOperation<T extends BaseData<HasId>> = () => Observable<T>;
 | 
			
		||||
 | 
			
		||||
export type CellContentFunction<T extends BaseData<HasId>> = (entity: T, key: string) => string;
 | 
			
		||||
export type HeaderCellStyleFunction<T extends BaseData<HasId>> = (key: string) => object;
 | 
			
		||||
export type CellStyleFunction<T extends BaseData<HasId>> = (entity: T, key: string) => object;
 | 
			
		||||
 | 
			
		||||
export interface CellActionDescriptor<T extends BaseData<HasId>> {
 | 
			
		||||
@ -67,13 +68,35 @@ export interface HeaderActionDescriptor {
 | 
			
		||||
  onAction: ($event: MouseEvent) => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class EntityTableColumn<T extends BaseData<HasId>> {
 | 
			
		||||
export type EntityTableColumnType = 'content' | 'action';
 | 
			
		||||
 | 
			
		||||
export class BaseEntityTableColumn<T extends BaseData<HasId>> {
 | 
			
		||||
  constructor(public type: EntityTableColumnType,
 | 
			
		||||
              public key: string,
 | 
			
		||||
              public title: string,
 | 
			
		||||
              public maxWidth: string = '100%',
 | 
			
		||||
              public sortable: boolean = true) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class EntityTableColumn<T extends BaseData<HasId>> extends BaseEntityTableColumn<T> {
 | 
			
		||||
  constructor(public key: string,
 | 
			
		||||
              public title: string,
 | 
			
		||||
              public maxWidth: string = '100%',
 | 
			
		||||
              public cellContentFunction: CellContentFunction<T> = (entity, property) => entity[property],
 | 
			
		||||
              public cellStyleFunction: CellStyleFunction<T> = () => ({}),
 | 
			
		||||
              public sortable: boolean = true) {
 | 
			
		||||
              public sortable: boolean = true,
 | 
			
		||||
              public headerCellStyleFunction: HeaderCellStyleFunction<T> = () => ({})) {
 | 
			
		||||
    super('content', key, title, maxWidth, sortable);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class EntityActionTableColumn<T extends BaseData<HasId>> extends BaseEntityTableColumn<T> {
 | 
			
		||||
  constructor(public key: string,
 | 
			
		||||
              public title: string,
 | 
			
		||||
              public actionDescriptor: CellActionDescriptor<T>,
 | 
			
		||||
              public maxWidth: string = '100%') {
 | 
			
		||||
    super('action', key, title, maxWidth, false);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -92,6 +115,8 @@ 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> {
 | 
			
		||||
 | 
			
		||||
  constructor() {}
 | 
			
		||||
@ -116,7 +141,7 @@ export class EntityTableConfig<T extends BaseData<HasId>, P extends PageLink = P
 | 
			
		||||
  entityTabsComponent: Type<EntityTabsComponent<T>>;
 | 
			
		||||
  addDialogStyle = {};
 | 
			
		||||
  defaultSortOrder: SortOrder = {property: 'createdTime', direction: Direction.ASC};
 | 
			
		||||
  columns: Array<EntityTableColumn<T>> = [];
 | 
			
		||||
  columns: Array<EntityColumn<T>> = [];
 | 
			
		||||
  cellActionDescriptors: Array<CellActionDescriptor<T>> = [];
 | 
			
		||||
  groupActionDescriptors: Array<GroupActionDescriptor<T>> = [];
 | 
			
		||||
  headerActionDescriptors: Array<HeaderActionDescriptor> = [];
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,11 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<mat-tab *ngIf="entity"
 | 
			
		||||
         label="{{ 'asset.events' | translate }}" #eventsTab="matTab">
 | 
			
		||||
  <tb-event-table [active]="eventsTab.isActive" [defaultEventType]="eventTypes.ERROR" [tenantId]="entity.tenantId.id"
 | 
			
		||||
                  [entityId]="entity.id"></tb-event-table>
 | 
			
		||||
</mat-tab>
 | 
			
		||||
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
 | 
			
		||||
         label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
 | 
			
		||||
  <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table>
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,11 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<mat-tab *ngIf="entity"
 | 
			
		||||
         label="{{ 'customer.events' | translate }}" #eventsTab="matTab">
 | 
			
		||||
  <tb-event-table [active]="eventsTab.isActive" [defaultEventType]="eventTypes.ERROR" [tenantId]="entity.tenantId.id"
 | 
			
		||||
                  [entityId]="entity.id"></tb-event-table>
 | 
			
		||||
</mat-tab>
 | 
			
		||||
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
 | 
			
		||||
         label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
 | 
			
		||||
  <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.CUSTOMER" [customerId]="entity.id" detailsMode="true"></tb-audit-log-table>
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,11 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<mat-tab *ngIf="entity"
 | 
			
		||||
         label="{{ 'device.events' | translate }}" #eventsTab="matTab">
 | 
			
		||||
  <tb-event-table [active]="eventsTab.isActive" [defaultEventType]="eventTypes.ERROR" [tenantId]="entity.tenantId.id"
 | 
			
		||||
                  [entityId]="entity.id"></tb-event-table>
 | 
			
		||||
</mat-tab>
 | 
			
		||||
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
 | 
			
		||||
         label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
 | 
			
		||||
  <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table>
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,11 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<mat-tab *ngIf="entity"
 | 
			
		||||
         label="{{ 'entity-view.events' | translate }}" #eventsTab="matTab">
 | 
			
		||||
  <tb-event-table [active]="eventsTab.isActive" [defaultEventType]="eventTypes.ERROR" [tenantId]="entity.tenantId.id"
 | 
			
		||||
                  [entityId]="entity.id"></tb-event-table>
 | 
			
		||||
</mat-tab>
 | 
			
		||||
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
 | 
			
		||||
         label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
 | 
			
		||||
  <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table>
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,14 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<mat-tab *ngIf="entity"
 | 
			
		||||
         label="{{ 'rulechain.events' | translate }}" #eventsTab="matTab">
 | 
			
		||||
  <tb-event-table [active]="eventsTab.isActive"
 | 
			
		||||
                  [debugEventTypes]="[debugEventTypes.DEBUG_RULE_CHAIN]"
 | 
			
		||||
                  [defaultEventType]="debugEventTypes.DEBUG_RULE_CHAIN"
 | 
			
		||||
                  [tenantId]="entity.tenantId.id"
 | 
			
		||||
                  [entityId]="entity.id"></tb-event-table>
 | 
			
		||||
</mat-tab>
 | 
			
		||||
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
 | 
			
		||||
         label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
 | 
			
		||||
  <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table>
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,22 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2019 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.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<mat-tab *ngIf="entity"
 | 
			
		||||
         label="{{ 'tenant.events' | translate }}" #eventsTab="matTab">
 | 
			
		||||
  <tb-event-table [active]="eventsTab.isActive" [defaultEventType]="eventTypes.ERROR" [tenantId]="nullUid"
 | 
			
		||||
                  [entityId]="entity.id"></tb-event-table>
 | 
			
		||||
</mat-tab>
 | 
			
		||||
@ -0,0 +1,38 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2019 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 { Component } from '@angular/core';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { EntityTabsComponent } from '../../components/entity/entity-tabs.component';
 | 
			
		||||
import { Tenant } from '@shared/models/tenant.model';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-tenant-tabs',
 | 
			
		||||
  templateUrl: './tenant-tabs.component.html',
 | 
			
		||||
  styleUrls: []
 | 
			
		||||
})
 | 
			
		||||
export class TenantTabsComponent extends EntityTabsComponent<Tenant> {
 | 
			
		||||
 | 
			
		||||
  constructor(protected store: Store<AppState>) {
 | 
			
		||||
    super(store);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    super.ngOnInit();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -20,13 +20,16 @@ import { SharedModule } from '@shared/shared.module';
 | 
			
		||||
import {TenantComponent} from '@modules/home/pages/tenant/tenant.component';
 | 
			
		||||
import {TenantRoutingModule} from '@modules/home/pages/tenant/tenant-routing.module';
 | 
			
		||||
import {HomeComponentsModule} from '@modules/home/components/home-components.module';
 | 
			
		||||
import { TenantTabsComponent } from '@home/pages/tenant/tenant-tabs.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  entryComponents: [
 | 
			
		||||
    TenantComponent
 | 
			
		||||
    TenantComponent,
 | 
			
		||||
    TenantTabsComponent
 | 
			
		||||
  ],
 | 
			
		||||
  declarations: [
 | 
			
		||||
    TenantComponent
 | 
			
		||||
    TenantComponent,
 | 
			
		||||
    TenantTabsComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,7 @@ import {
 | 
			
		||||
import { TenantComponent } from '@modules/home/pages/tenant/tenant.component';
 | 
			
		||||
import { EntityAction } from '@home/models/entity/entity-component.models';
 | 
			
		||||
import { User } from '@shared/models/user.model';
 | 
			
		||||
import { TenantTabsComponent } from '@home/pages/tenant/tenant-tabs.component';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class TenantsTableConfigResolver implements Resolve<EntityTableConfig<Tenant>> {
 | 
			
		||||
@ -48,6 +49,7 @@ export class TenantsTableConfigResolver implements Resolve<EntityTableConfig<Ten
 | 
			
		||||
 | 
			
		||||
    this.config.entityType = EntityType.TENANT;
 | 
			
		||||
    this.config.entityComponent = TenantComponent;
 | 
			
		||||
    this.config.entityTabsComponent = TenantTabsComponent;
 | 
			
		||||
    this.config.entityTranslations = entityTypeTranslations.get(EntityType.TENANT);
 | 
			
		||||
    this.config.entityResources = entityTypeResources.get(EntityType.TENANT);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,21 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2019 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.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
 | 
			
		||||
         label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
 | 
			
		||||
  <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.USER" [userId]="entity.id" detailsMode="true"></tb-audit-log-table>
 | 
			
		||||
</mat-tab>
 | 
			
		||||
@ -0,0 +1,38 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2019 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 { Component } from '@angular/core';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { EntityTabsComponent } from '../../components/entity/entity-tabs.component';
 | 
			
		||||
import { User } from '@app/shared/models/user.model';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-user-tabs',
 | 
			
		||||
  templateUrl: './user-tabs.component.html',
 | 
			
		||||
  styleUrls: []
 | 
			
		||||
})
 | 
			
		||||
export class UserTabsComponent extends EntityTabsComponent<User> {
 | 
			
		||||
 | 
			
		||||
  constructor(protected store: Store<AppState>) {
 | 
			
		||||
    super(store);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    super.ngOnInit();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -22,15 +22,18 @@ import { UserRoutingModule } from '@modules/home/pages/user/user-routing.module'
 | 
			
		||||
import { AddUserDialogComponent } from '@modules/home/pages/user/add-user-dialog.component';
 | 
			
		||||
import { ActivationLinkDialogComponent } from '@modules/home/pages/user/activation-link-dialog.component';
 | 
			
		||||
import {HomeComponentsModule} from '@modules/home/components/home-components.module';
 | 
			
		||||
import { UserTabsComponent } from '@home/pages/user/user-tabs.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  entryComponents: [
 | 
			
		||||
    UserComponent,
 | 
			
		||||
    UserTabsComponent,
 | 
			
		||||
    AddUserDialogComponent,
 | 
			
		||||
    ActivationLinkDialogComponent
 | 
			
		||||
  ],
 | 
			
		||||
  declarations: [
 | 
			
		||||
    UserComponent,
 | 
			
		||||
    UserTabsComponent,
 | 
			
		||||
    AddUserDialogComponent,
 | 
			
		||||
    ActivationLinkDialogComponent
 | 
			
		||||
  ],
 | 
			
		||||
 | 
			
		||||
@ -57,6 +57,7 @@ import { NULL_UUID } from '@shared/models/id/has-uuid';
 | 
			
		||||
import { Customer } from '@shared/models/customer.model';
 | 
			
		||||
import {TenantService} from '@app/core/http/tenant.service';
 | 
			
		||||
import {TenantId} from '@app/shared/models/id/tenant-id';
 | 
			
		||||
import { UserTabsComponent } from '@home/pages/user/user-tabs.component';
 | 
			
		||||
 | 
			
		||||
export interface UsersTableRouteData {
 | 
			
		||||
  authority: Authority;
 | 
			
		||||
@ -83,6 +84,7 @@ export class UsersTableConfigResolver implements Resolve<EntityTableConfig<User>
 | 
			
		||||
 | 
			
		||||
    this.config.entityType = EntityType.USER;
 | 
			
		||||
    this.config.entityComponent = UserComponent;
 | 
			
		||||
    this.config.entityTabsComponent = UserTabsComponent;
 | 
			
		||||
    this.config.entityTranslations = entityTypeTranslations.get(EntityType.USER);
 | 
			
		||||
    this.config.entityResources = entityTypeResources.get(EntityType.USER);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										89
									
								
								ui-ngx/src/app/shared/models/event.models.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								ui-ngx/src/app/shared/models/event.models.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2019 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 { ActionStatus, ActionType } from '@shared/models/audit-log.models';
 | 
			
		||||
import { BaseData } from '@shared/models/base-data';
 | 
			
		||||
import { AuditLogId } from '@shared/models/id/audit-log-id';
 | 
			
		||||
import { TenantId } from '@shared/models/id/tenant-id';
 | 
			
		||||
import { CustomerId } from '@shared/models/id/customer-id';
 | 
			
		||||
import { EntityId } from '@shared/models/id/entity-id';
 | 
			
		||||
import { UserId } from '@shared/models/id/user-id';
 | 
			
		||||
import { EventId } from './id/event-id';
 | 
			
		||||
import { MsgDataType } from './rule-node.models';
 | 
			
		||||
 | 
			
		||||
export enum EventType {
 | 
			
		||||
  ERROR = 'ERROR',
 | 
			
		||||
  LC_EVENT = 'LC_EVENT',
 | 
			
		||||
  STATS = 'STATS'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum DebugEventType {
 | 
			
		||||
  DEBUG_RULE_NODE = 'DEBUG_RULE_NODE',
 | 
			
		||||
  DEBUG_RULE_CHAIN = 'DEBUG_RULE_CHAIN'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const eventTypeTranslations = new Map<EventType | DebugEventType, string>(
 | 
			
		||||
  [
 | 
			
		||||
    [EventType.ERROR, 'event.type-error'],
 | 
			
		||||
    [EventType.LC_EVENT, 'event.type-lc-event'],
 | 
			
		||||
    [EventType.STATS, 'event.type-stats'],
 | 
			
		||||
    [DebugEventType.DEBUG_RULE_NODE, 'event.type-debug-rule-node'],
 | 
			
		||||
    [DebugEventType.DEBUG_RULE_CHAIN, 'event.type-debug-rule-chain'],
 | 
			
		||||
  ]
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export interface BaseEventBody {
 | 
			
		||||
  server: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ErrorEventBody extends BaseEventBody {
 | 
			
		||||
  method: string;
 | 
			
		||||
  error: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface LcEventEventBody extends BaseEventBody {
 | 
			
		||||
  event: string;
 | 
			
		||||
  success: boolean;
 | 
			
		||||
  error: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface StatsEventBody extends BaseEventBody {
 | 
			
		||||
  messagesProcessed: number;
 | 
			
		||||
  errorsOccurred: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface DebugRuleNodeEventBody extends BaseEventBody {
 | 
			
		||||
  type: string;
 | 
			
		||||
  entityId: string;
 | 
			
		||||
  entityName: string;
 | 
			
		||||
  msgId: string;
 | 
			
		||||
  msgType: string;
 | 
			
		||||
  relationType: string;
 | 
			
		||||
  dataType: MsgDataType;
 | 
			
		||||
  data: string;
 | 
			
		||||
  metadata: string;
 | 
			
		||||
  error: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type EventBody = ErrorEventBody & LcEventEventBody & StatsEventBody & DebugRuleNodeEventBody;
 | 
			
		||||
 | 
			
		||||
export interface Event extends BaseData<EventId> {
 | 
			
		||||
  tenantId: TenantId;
 | 
			
		||||
  entityId: EntityId;
 | 
			
		||||
  type: string;
 | 
			
		||||
  uid: string;
 | 
			
		||||
  body: EventBody;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								ui-ngx/src/app/shared/models/id/event-id.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								ui-ngx/src/app/shared/models/id/event-id.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2019 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 { HasUUID } from '@shared/models/id/has-uuid';
 | 
			
		||||
 | 
			
		||||
export class EventId implements HasUUID {
 | 
			
		||||
  id: string;
 | 
			
		||||
  constructor(id: string) {
 | 
			
		||||
    this.id = id;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -21,6 +21,12 @@ import {CustomerId} from '@shared/models/id/customer-id';
 | 
			
		||||
import {RuleChainId} from '@shared/models/id/rule-chain-id';
 | 
			
		||||
import {RuleNodeId} from '@shared/models/id/rule-node-id';
 | 
			
		||||
 | 
			
		||||
export enum MsgDataType {
 | 
			
		||||
  JSON = 'JSON',
 | 
			
		||||
  TEXT = 'TEXT',
 | 
			
		||||
  BINARY = 'BINARY'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RuleNodeConfiguration {
 | 
			
		||||
  todo: Array<any>;
 | 
			
		||||
  // TODO:
 | 
			
		||||
 | 
			
		||||
@ -308,7 +308,7 @@ $tb-dark-theme: get-tb-dark-theme(
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .mat-cell, .mat-header-cell {
 | 
			
		||||
    min-width: 80px;
 | 
			
		||||
    min-width: 40px;
 | 
			
		||||
    &:last-child {
 | 
			
		||||
      padding: 0 12px 0 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user