Showing
34 changed files
with
990 additions
and
67 deletions
... | ... | @@ -53,10 +53,11 @@ public class EventController extends BaseController { |
53 | 53 | @RequestParam("tenantId") String strTenantId, |
54 | 54 | @RequestParam int pageSize, |
55 | 55 | @RequestParam int page, |
56 | + @RequestParam(required = false) String textSearch, | |
57 | + @RequestParam(required = false) String sortProperty, | |
58 | + @RequestParam(required = false) String sortOrder, | |
56 | 59 | @RequestParam(required = false) Long startTime, |
57 | - @RequestParam(required = false) Long endTime, | |
58 | - @RequestParam(required = false, defaultValue = "false") boolean ascOrder | |
59 | - ) throws ThingsboardException { | |
60 | + @RequestParam(required = false) Long endTime) throws ThingsboardException { | |
60 | 61 | checkParameter("EntityId", strEntityId); |
61 | 62 | checkParameter("EntityType", strEntityType); |
62 | 63 | try { |
... | ... | @@ -64,8 +65,7 @@ public class EventController extends BaseController { |
64 | 65 | |
65 | 66 | EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); |
66 | 67 | checkEntityId(entityId, Operation.READ); |
67 | - TimePageLink pageLink = createTimePageLink(pageSize, page, "", | |
68 | - "createdTime", ascOrder ? "asc" : "desc", startTime, endTime); | |
68 | + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); | |
69 | 69 | return checkNotNull(eventService.findEvents(tenantId, entityId, eventType, pageLink)); |
70 | 70 | } catch (Exception e) { |
71 | 71 | throw handleException(e); |
... | ... | @@ -81,10 +81,11 @@ public class EventController extends BaseController { |
81 | 81 | @RequestParam("tenantId") String strTenantId, |
82 | 82 | @RequestParam int pageSize, |
83 | 83 | @RequestParam int page, |
84 | + @RequestParam(required = false) String textSearch, | |
85 | + @RequestParam(required = false) String sortProperty, | |
86 | + @RequestParam(required = false) String sortOrder, | |
84 | 87 | @RequestParam(required = false) Long startTime, |
85 | - @RequestParam(required = false) Long endTime, | |
86 | - @RequestParam(required = false, defaultValue = "false") boolean ascOrder | |
87 | - ) throws ThingsboardException { | |
88 | + @RequestParam(required = false) Long endTime) throws ThingsboardException { | |
88 | 89 | checkParameter("EntityId", strEntityId); |
89 | 90 | checkParameter("EntityType", strEntityType); |
90 | 91 | try { |
... | ... | @@ -93,8 +94,7 @@ public class EventController extends BaseController { |
93 | 94 | EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); |
94 | 95 | checkEntityId(entityId, Operation.READ); |
95 | 96 | |
96 | - TimePageLink pageLink = createTimePageLink(pageSize, page, "", | |
97 | - "createdTime", ascOrder ? "asc" : "desc", startTime, endTime); | |
97 | + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); | |
98 | 98 | |
99 | 99 | return checkNotNull(eventService.findEvents(tenantId, entityId, pageLink)); |
100 | 100 | } catch (Exception e) { | ... | ... |
... | ... | @@ -15,10 +15,10 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.dao.sql.event; |
17 | 17 | |
18 | +import org.springframework.data.domain.Page; | |
18 | 19 | import org.springframework.data.domain.Pageable; |
19 | -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; | |
20 | 20 | import org.springframework.data.jpa.repository.Query; |
21 | -import org.springframework.data.repository.CrudRepository; | |
21 | +import org.springframework.data.repository.PagingAndSortingRepository; | |
22 | 22 | import org.springframework.data.repository.query.Param; |
23 | 23 | import org.thingsboard.server.common.data.EntityType; |
24 | 24 | import org.thingsboard.server.dao.model.sql.EventEntity; |
... | ... | @@ -30,7 +30,7 @@ import java.util.List; |
30 | 30 | * Created by Valerii Sosliuk on 5/3/2017. |
31 | 31 | */ |
32 | 32 | @SqlDao |
33 | -public interface EventRepository extends CrudRepository<EventEntity, String>, JpaSpecificationExecutor<EventEntity> { | |
33 | +public interface EventRepository extends PagingAndSortingRepository<EventEntity, String> { | |
34 | 34 | |
35 | 35 | EventEntity findByTenantIdAndEntityTypeAndEntityIdAndEventTypeAndEventUid(String tenantId, |
36 | 36 | EntityType entityType, |
... | ... | @@ -51,4 +51,34 @@ public interface EventRepository extends CrudRepository<EventEntity, String>, Jp |
51 | 51 | @Param("eventType") String eventType, |
52 | 52 | Pageable pageable); |
53 | 53 | |
54 | + @Query("SELECT e FROM EventEntity e WHERE " + | |
55 | + "e.tenantId = :tenantId " + | |
56 | + "AND e.entityType = :entityType AND e.entityId = :entityId " + | |
57 | + "AND (:startId IS NULL OR e.id >= :startId) " + | |
58 | + "AND (:endId IS NULL OR e.id <= :endId) " + | |
59 | + "AND LOWER(e.eventType) LIKE LOWER(CONCAT(:textSearch, '%'))" | |
60 | + ) | |
61 | + Page<EventEntity> findEventsByTenantIdAndEntityId(@Param("tenantId") String tenantId, | |
62 | + @Param("entityType") EntityType entityType, | |
63 | + @Param("entityId") String entityId, | |
64 | + @Param("textSearch") String textSearch, | |
65 | + @Param("startId") String startId, | |
66 | + @Param("endId") String endId, | |
67 | + Pageable pageable); | |
68 | + | |
69 | + @Query("SELECT e FROM EventEntity e WHERE " + | |
70 | + "e.tenantId = :tenantId " + | |
71 | + "AND e.entityType = :entityType AND e.entityId = :entityId " + | |
72 | + "AND e.eventType = :eventType " + | |
73 | + "AND (:startId IS NULL OR e.id >= :startId) " + | |
74 | + "AND (:endId IS NULL OR e.id <= :endId)" | |
75 | + ) | |
76 | + Page<EventEntity> findEventsByTenantIdAndEntityIdAndEventType(@Param("tenantId") String tenantId, | |
77 | + @Param("entityType") EntityType entityType, | |
78 | + @Param("entityId") String entityId, | |
79 | + @Param("eventType") String eventType, | |
80 | + @Param("startId") String startId, | |
81 | + @Param("endId") String endId, | |
82 | + Pageable pageable); | |
83 | + | |
54 | 84 | } | ... | ... |
... | ... | @@ -21,8 +21,6 @@ import lombok.extern.slf4j.Slf4j; |
21 | 21 | import org.apache.commons.lang3.StringUtils; |
22 | 22 | import org.springframework.beans.factory.annotation.Autowired; |
23 | 23 | import org.springframework.data.domain.PageRequest; |
24 | -import org.springframework.data.domain.Pageable; | |
25 | -import org.springframework.data.domain.Sort; | |
26 | 24 | import org.springframework.data.jpa.domain.Specification; |
27 | 25 | import org.springframework.data.repository.CrudRepository; |
28 | 26 | import org.springframework.stereotype.Component; |
... | ... | @@ -40,13 +38,11 @@ import org.thingsboard.server.dao.sql.JpaAbstractSearchTimeDao; |
40 | 38 | import org.thingsboard.server.dao.util.SqlDao; |
41 | 39 | |
42 | 40 | import javax.persistence.criteria.Predicate; |
43 | -import java.util.ArrayList; | |
44 | -import java.util.List; | |
45 | -import java.util.Optional; | |
46 | -import java.util.UUID; | |
41 | +import java.util.*; | |
47 | 42 | |
48 | -import static org.springframework.data.jpa.domain.Specifications.where; | |
49 | -import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY; | |
43 | +import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; | |
44 | +import static org.thingsboard.server.dao.DaoUtil.endTimeToId; | |
45 | +import static org.thingsboard.server.dao.DaoUtil.startTimeToId; | |
50 | 46 | import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; |
51 | 47 | |
52 | 48 | /** |
... | ... | @@ -109,15 +105,30 @@ public class JpaBaseEventDao extends JpaAbstractSearchTimeDao<EventEntity, Event |
109 | 105 | |
110 | 106 | @Override |
111 | 107 | public PageData<Event> findEvents(UUID tenantId, EntityId entityId, TimePageLink pageLink) { |
112 | - return findEvents(tenantId, entityId, null, pageLink); | |
108 | + return DaoUtil.toPageData( | |
109 | + eventRepository | |
110 | + .findEventsByTenantIdAndEntityId( | |
111 | + fromTimeUUID(tenantId), | |
112 | + entityId.getEntityType(), | |
113 | + fromTimeUUID(entityId.getId()), | |
114 | + Objects.toString(pageLink.getTextSearch(), ""), | |
115 | + startTimeToId(pageLink.getStartTime()), | |
116 | + endTimeToId(pageLink.getEndTime()), | |
117 | + DaoUtil.toPageable(pageLink))); | |
113 | 118 | } |
114 | 119 | |
115 | 120 | @Override |
116 | 121 | public PageData<Event> findEvents(UUID tenantId, EntityId entityId, String eventType, TimePageLink pageLink) { |
117 | - Specification<EventEntity> timeSearchSpec = JpaAbstractSearchTimeDao.getTimeSearchPageSpec(pageLink, "id"); | |
118 | - Specification<EventEntity> fieldsSpec = getEntityFieldsSpec(tenantId, entityId, eventType); | |
119 | - Pageable pageable = DaoUtil.toPageable(pageLink); | |
120 | - return DaoUtil.toPageData(eventRepository.findAll(where(timeSearchSpec).and(fieldsSpec), pageable)); | |
122 | + return DaoUtil.toPageData( | |
123 | + eventRepository | |
124 | + .findEventsByTenantIdAndEntityIdAndEventType( | |
125 | + fromTimeUUID(tenantId), | |
126 | + entityId.getEntityType(), | |
127 | + fromTimeUUID(entityId.getId()), | |
128 | + eventType, | |
129 | + startTimeToId(pageLink.getStartTime()), | |
130 | + endTimeToId(pageLink.getEndTime()), | |
131 | + DaoUtil.toPageable(pageLink))); | |
121 | 132 | } |
122 | 133 | |
123 | 134 | @Override | ... | ... |
ui-ngx/src/app/core/http/event.service.ts
0 → 100644
1 | +/// | |
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { Injectable } from '@angular/core'; | |
18 | +import { defaultHttpOptions } from './http-utils'; | |
19 | +import { Observable } from 'rxjs/index'; | |
20 | +import { HttpClient } from '@angular/common/http'; | |
21 | +import { TimePageLink } from '@shared/models/page/page-link'; | |
22 | +import { PageData } from '@shared/models/page/page-data'; | |
23 | +import { EntityId } from '@shared/models/id/entity-id'; | |
24 | +import { DebugEventType, Event, EventType } from '@shared/models/event.models'; | |
25 | + | |
26 | +@Injectable({ | |
27 | + providedIn: 'root' | |
28 | +}) | |
29 | +export class EventService { | |
30 | + | |
31 | + constructor( | |
32 | + private http: HttpClient | |
33 | + ) { } | |
34 | + | |
35 | + public getEvents(entityId: EntityId, eventType: EventType | DebugEventType, tenantId: string, pageLink: TimePageLink, | |
36 | + ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<PageData<Event>> { | |
37 | + return this.http.get<PageData<Event>>(`/api/events/${entityId.entityType}/${entityId.id}/${eventType}` + | |
38 | + `${pageLink.toQuery()}&tenantId=${tenantId}`, | |
39 | + defaultHttpOptions(ignoreLoading, ignoreErrors)); | |
40 | + } | |
41 | +} | ... | ... |
... | ... | @@ -37,14 +37,15 @@ |
37 | 37 | <mat-toolbar class="mat-table-toolbar" [fxShow]="!textSearchMode && dataSource.selection.isEmpty()"> |
38 | 38 | <div class="mat-toolbar-tools"> |
39 | 39 | <span *ngIf="entitiesTableConfig.tableTitle" class="tb-entity-table-title">{{ entitiesTableConfig.tableTitle }}</span> |
40 | + <tb-anchor #entityTableHeader></tb-anchor> | |
40 | 41 | <tb-timewindow *ngIf="entitiesTableConfig.useTimePageLink" [(ngModel)]="timewindow" |
41 | 42 | (ngModelChange)="onTimewindowChange()" |
42 | 43 | asButton historyOnly></tb-timewindow> |
43 | - <tb-anchor #entityTableHeader></tb-anchor> | |
44 | - <span fxFlex *ngIf="!this.entitiesTableConfig.headerComponent"></span> | |
44 | + <span fxFlex *ngIf="!entitiesTableConfig.headerComponent || | |
45 | + entitiesTableConfig.useTimePageLink"></span> | |
45 | 46 | <div [fxShow]="addEnabled()"> |
46 | 47 | <button mat-button mat-icon-button [disabled]="isLoading$ | async" |
47 | - *ngIf="!this.entitiesTableConfig.addActionDescriptors.length; else addActions" | |
48 | + *ngIf="!entitiesTableConfig.addActionDescriptors.length; else addActions" | |
48 | 49 | (click)="addEntity($event)" |
49 | 50 | matTooltip="{{ translations.add | translate }}" |
50 | 51 | matTooltipPosition="above"> |
... | ... | @@ -52,12 +53,12 @@ |
52 | 53 | </button> |
53 | 54 | <ng-template #addActions> |
54 | 55 | <button mat-button mat-icon-button [disabled]="isLoading$ | async" |
55 | - *ngIf="this.entitiesTableConfig.addActionDescriptors.length === 1; else addActionsMenu" | |
56 | - [fxShow]="this.entitiesTableConfig.addActionDescriptors[0].isEnabled()" | |
57 | - (click)="this.entitiesTableConfig.addActionDescriptors[0].onAction($event)" | |
58 | - matTooltip="{{ this.entitiesTableConfig.addActionDescriptors[0].name }}" | |
56 | + *ngIf="entitiesTableConfig.addActionDescriptors.length === 1; else addActionsMenu" | |
57 | + [fxShow]="entitiesTableConfig.addActionDescriptors[0].isEnabled()" | |
58 | + (click)="entitiesTableConfig.addActionDescriptors[0].onAction($event)" | |
59 | + matTooltip="{{ entitiesTableConfig.addActionDescriptors[0].name }}" | |
59 | 60 | matTooltipPosition="above"> |
60 | - <mat-icon>{{this.entitiesTableConfig.addActionDescriptors[0].icon}}</mat-icon> | |
61 | + <mat-icon>{{entitiesTableConfig.addActionDescriptors[0].icon}}</mat-icon> | |
61 | 62 | </button> |
62 | 63 | <ng-template #addActionsMenu> |
63 | 64 | <button mat-button mat-icon-button [disabled]="isLoading$ | async" |
... | ... | @@ -67,7 +68,7 @@ |
67 | 68 | <mat-icon>add</mat-icon> |
68 | 69 | </button> |
69 | 70 | <mat-menu #addActionsMenu="matMenu" xPosition="before"> |
70 | - <button mat-menu-item *ngFor="let actionDescriptor of this.entitiesTableConfig.addActionDescriptors" | |
71 | + <button mat-menu-item *ngFor="let actionDescriptor of entitiesTableConfig.addActionDescriptors" | |
71 | 72 | [disabled]="isLoading$ | async" |
72 | 73 | [fxShow]="actionDescriptor.isEnabled()" |
73 | 74 | (click)="actionDescriptor.onAction($event)"> |
... | ... | @@ -152,10 +153,19 @@ |
152 | 153 | </mat-cell> |
153 | 154 | </ng-container> |
154 | 155 | <ng-container [matColumnDef]="column.key" *ngFor="let column of columns; trackBy: trackByColumnKey; let col = index"> |
155 | - <mat-header-cell *matHeaderCellDef [ngStyle]="{maxWidth: column.maxWidth}" mat-sort-header [disabled]="!column.sortable"> {{ column.title | translate }} </mat-header-cell> | |
156 | + <mat-header-cell *matHeaderCellDef [ngStyle]="headerCellStyle(column, col)" mat-sort-header [disabled]="!column.sortable"> {{ column.title | translate }} </mat-header-cell> | |
156 | 157 | <mat-cell *matCellDef="let entity; let row = index" |
157 | 158 | [innerHTML]="cellContent(entity, column, row, col)" |
158 | - [ngStyle]="cellStyle(entity, column, row, col)"></mat-cell> | |
159 | + [ngStyle]="cellStyle(entity, column, row, col)"> | |
160 | + <button *ngIf="column.actionDescriptor; let actionDescriptor" mat-button mat-icon-button [disabled]="isLoading$ | async" | |
161 | + [fxShow]="actionDescriptor.isEnabled(entity)" | |
162 | + matTooltip="{{ actionDescriptor.nameFunction ? actionDescriptor.nameFunction(entity) : actionDescriptor.name }}" | |
163 | + matTooltipPosition="above" | |
164 | + (click)="actionDescriptor.onAction($event, entity)"> | |
165 | + <mat-icon [svgIcon]="actionDescriptor.mdiIcon" [ngStyle]="actionDescriptor.style"> | |
166 | + {{actionDescriptor.icon}}</mat-icon> | |
167 | + </button> | |
168 | + </mat-cell> | |
159 | 169 | </ng-container> |
160 | 170 | <ng-container matColumnDef="actions" stickyEnd> |
161 | 171 | <mat-header-cell *matHeaderCellDef [ngStyle.gt-md]="{ minWidth: (cellActionDescriptors.length * 40) + 'px', maxWidth: (cellActionDescriptors.length * 40) + 'px' }"> | ... | ... |
... | ... | @@ -42,7 +42,8 @@ import { |
42 | 42 | EntityTableColumn, |
43 | 43 | EntityTableConfig, |
44 | 44 | GroupActionDescriptor, |
45 | - HeaderActionDescriptor | |
45 | + HeaderActionDescriptor, | |
46 | + EntityColumn | |
46 | 47 | } from '@home/models/entity/entities-table-config.models'; |
47 | 48 | import { EntityTypeTranslation } from '@shared/models/entity-type.models'; |
48 | 49 | import { DialogService } from '@core/services/dialog.service'; |
... | ... | @@ -72,8 +73,10 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn |
72 | 73 | groupActionDescriptors: Array<GroupActionDescriptor<BaseData<HasId>>>; |
73 | 74 | cellActionDescriptors: Array<CellActionDescriptor<BaseData<HasId>>>; |
74 | 75 | |
75 | - columns: Array<EntityTableColumn<BaseData<HasId>>>; | |
76 | - displayedColumns: string[] = []; | |
76 | + columns: Array<EntityColumn<BaseData<HasId>>>; | |
77 | + displayedColumns: string[]; | |
78 | + | |
79 | + headerCellStyleCache: Array<any> = []; | |
77 | 80 | |
78 | 81 | cellContentCache: Array<SafeHtml> = []; |
79 | 82 | |
... | ... | @@ -143,22 +146,12 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn |
143 | 146 | } |
144 | 147 | ); |
145 | 148 | |
146 | - this.columns = [...this.entitiesTableConfig.columns]; | |
147 | - | |
148 | 149 | const enabledGroupActionDescriptors = |
149 | 150 | this.groupActionDescriptors.filter((descriptor) => descriptor.isEnabled); |
150 | 151 | |
151 | 152 | this.selectionEnabled = this.entitiesTableConfig.selectionEnabled && enabledGroupActionDescriptors.length; |
152 | 153 | |
153 | - if (this.selectionEnabled) { | |
154 | - this.displayedColumns.push('select'); | |
155 | - } | |
156 | - this.columns.forEach( | |
157 | - (column) => { | |
158 | - this.displayedColumns.push(column.key); | |
159 | - } | |
160 | - ); | |
161 | - this.displayedColumns.push('actions'); | |
154 | + this.columnsUpdated(); | |
162 | 155 | |
163 | 156 | const sortOrder: SortOrder = { property: this.entitiesTableConfig.defaultSortOrder.property, |
164 | 157 | direction: this.entitiesTableConfig.defaultSortOrder.direction }; |
... | ... | @@ -235,6 +228,7 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn |
235 | 228 | } |
236 | 229 | |
237 | 230 | private dataLoaded() { |
231 | + this.headerCellStyleCache.length = 0; | |
238 | 232 | this.cellContentCache.length = 0; |
239 | 233 | this.cellStyleCache.length = 0; |
240 | 234 | } |
... | ... | @@ -365,21 +359,65 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn |
365 | 359 | } |
366 | 360 | } |
367 | 361 | |
368 | - cellContent(entity: BaseData<HasId>, column: EntityTableColumn<BaseData<HasId>>, row: number, col: number) { | |
369 | - const index = row * this.columns.length + col; | |
370 | - let res = this.cellContentCache[index]; | |
362 | + columnsUpdated(resetData: boolean = false) { | |
363 | + this.columns = [...this.entitiesTableConfig.columns]; | |
364 | + | |
365 | + this.displayedColumns = []; | |
366 | + | |
367 | + if (this.selectionEnabled) { | |
368 | + this.displayedColumns.push('select'); | |
369 | + } | |
370 | + this.columns.forEach( | |
371 | + (column) => { | |
372 | + this.displayedColumns.push(column.key); | |
373 | + } | |
374 | + ); | |
375 | + this.displayedColumns.push('actions'); | |
376 | + this.headerCellStyleCache.length = 0; | |
377 | + this.cellContentCache.length = 0; | |
378 | + this.cellStyleCache.length = 0; | |
379 | + if (resetData) { | |
380 | + this.dataSource.reset(); | |
381 | + } | |
382 | + } | |
383 | + | |
384 | + headerCellStyle(column: EntityColumn<BaseData<HasId>>, col: number) { | |
385 | + const index = col; | |
386 | + let res = this.headerCellStyleCache[index]; | |
371 | 387 | if (!res) { |
372 | - res = this.domSanitizer.bypassSecurityTrustHtml(column.cellContentFunction(entity, column.key)); | |
373 | - this.cellContentCache[index] = res; | |
388 | + if (column instanceof EntityTableColumn) { | |
389 | + res = {...column.headerCellStyleFunction(column.key), ...{maxWidth: column.maxWidth}}; | |
390 | + } else { | |
391 | + res = {maxWidth: column.maxWidth}; | |
392 | + } | |
393 | + this.headerCellStyleCache[index] = res; | |
374 | 394 | } |
375 | 395 | return res; |
376 | 396 | } |
377 | 397 | |
378 | - cellStyle(entity: BaseData<HasId>, column: EntityTableColumn<BaseData<HasId>>, row: number, col: number) { | |
398 | + cellContent(entity: BaseData<HasId>, column: EntityColumn<BaseData<HasId>>, row: number, col: number) { | |
399 | + if (column instanceof EntityTableColumn) { | |
400 | + const index = row * this.columns.length + col; | |
401 | + let res = this.cellContentCache[index]; | |
402 | + if (!res) { | |
403 | + res = this.domSanitizer.bypassSecurityTrustHtml(column.cellContentFunction(entity, column.key)); | |
404 | + this.cellContentCache[index] = res; | |
405 | + } | |
406 | + return res; | |
407 | + } else { | |
408 | + return null; | |
409 | + } | |
410 | + } | |
411 | + | |
412 | + cellStyle(entity: BaseData<HasId>, column: EntityColumn<BaseData<HasId>>, row: number, col: number) { | |
379 | 413 | const index = row * this.columns.length + col; |
380 | 414 | let res = this.cellStyleCache[index]; |
381 | 415 | if (!res) { |
382 | - res = {...column.cellStyleFunction(entity, column.key), ...{maxWidth: column.maxWidth}}; | |
416 | + if (column instanceof EntityTableColumn) { | |
417 | + res = {...column.cellStyleFunction(entity, column.key), ...{maxWidth: column.maxWidth}}; | |
418 | + } else { | |
419 | + res = {maxWidth: column.maxWidth}; | |
420 | + } | |
383 | 421 | this.cellStyleCache[index] = res; |
384 | 422 | } |
385 | 423 | return res; | ... | ... |
... | ... | @@ -37,6 +37,8 @@ import { selectAuthUser, getCurrentAuthUser } from '@core/auth/auth.selectors'; |
37 | 37 | import { AuthUser } from '@shared/models/user.model'; |
38 | 38 | import { EntityType } from '@shared/models/entity-type.models'; |
39 | 39 | import { AuditLogMode } from '@shared/models/audit-log.models'; |
40 | +import { DebugEventType, EventType } from '@shared/models/event.models'; | |
41 | +import { NULL_UUID } from '@shared/models/id/has-uuid'; | |
40 | 42 | |
41 | 43 | export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends PageComponent implements OnInit, AfterViewInit { |
42 | 44 | |
... | ... | @@ -46,8 +48,14 @@ export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends Pag |
46 | 48 | |
47 | 49 | auditLogModes = AuditLogMode; |
48 | 50 | |
51 | + eventTypes = EventType; | |
52 | + | |
53 | + debugEventTypes = DebugEventType; | |
54 | + | |
49 | 55 | authUser: AuthUser; |
50 | 56 | |
57 | + nullUid = NULL_UUID; | |
58 | + | |
51 | 59 | entityValue: T; |
52 | 60 | |
53 | 61 | @ViewChildren(MatTab) entityTabs: QueryList<MatTab>; | ... | ... |
1 | +/// | |
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { | |
18 | + DateEntityTableColumn, | |
19 | + EntityActionTableColumn, | |
20 | + EntityTableColumn, | |
21 | + EntityTableConfig | |
22 | +} from '@home/models/entity/entities-table-config.models'; | |
23 | +import { DebugEventType, Event, EventType } from '@shared/models/event.models'; | |
24 | +import { TimePageLink } from '@shared/models/page/page-link'; | |
25 | +import { TranslateService } from '@ngx-translate/core'; | |
26 | +import { DatePipe } from '@angular/common'; | |
27 | +import { MatDialog } from '@angular/material/dialog'; | |
28 | +import { EntityId } from '@shared/models/id/entity-id'; | |
29 | +import { EventService } from '@app/core/http/event.service'; | |
30 | +import { EventTableHeaderComponent } from '@home/components/event/event-table-header.component'; | |
31 | +import { EntityTypeResource } from '@shared/models/entity-type.models'; | |
32 | +import { Observable } from 'rxjs'; | |
33 | +import { PageData } from '@shared/models/page/page-data'; | |
34 | +import { Direction } from '@shared/models/page/sort-order'; | |
35 | +import { MsgDataType } from '@shared/models/rule-node.models'; | |
36 | +import { DialogService } from '@core/services/dialog.service'; | |
37 | + | |
38 | +export class EventTableConfig extends EntityTableConfig<Event, TimePageLink> { | |
39 | + | |
40 | + eventTypeValue: EventType | DebugEventType; | |
41 | + | |
42 | + set eventType(eventType: EventType | DebugEventType) { | |
43 | + if (this.eventTypeValue !== eventType) { | |
44 | + this.eventTypeValue = eventType; | |
45 | + this.updateColumns(true); | |
46 | + } | |
47 | + } | |
48 | + | |
49 | + get eventType(): EventType | DebugEventType { | |
50 | + return this.eventTypeValue; | |
51 | + } | |
52 | + | |
53 | + eventTypes: Array<EventType | DebugEventType>; | |
54 | + | |
55 | + constructor(private eventService: EventService, | |
56 | + private dialogService: DialogService, | |
57 | + private translate: TranslateService, | |
58 | + private datePipe: DatePipe, | |
59 | + private dialog: MatDialog, | |
60 | + public entityId: EntityId, | |
61 | + public tenantId: string, | |
62 | + private defaultEventType: EventType | DebugEventType, | |
63 | + private disabledEventTypes: Array<EventType | DebugEventType> = null, | |
64 | + private debugEventTypes: Array<DebugEventType> = null) { | |
65 | + super(); | |
66 | + this.loadDataOnInit = false; | |
67 | + this.tableTitle = ''; | |
68 | + this.useTimePageLink = true; | |
69 | + this.detailsPanelEnabled = false; | |
70 | + this.selectionEnabled = false; | |
71 | + this.searchEnabled = false; | |
72 | + this.addEnabled = false; | |
73 | + this.entitiesDeleteEnabled = false; | |
74 | + | |
75 | + this.headerComponent = EventTableHeaderComponent; | |
76 | + | |
77 | + this.eventTypes = Object.keys(EventType).map(type => EventType[type]); | |
78 | + | |
79 | + if (disabledEventTypes && disabledEventTypes.length) { | |
80 | + this.eventTypes = this.eventTypes.filter(type => disabledEventTypes.indexOf(type) === -1); | |
81 | + } | |
82 | + | |
83 | + if (debugEventTypes && debugEventTypes.length) { | |
84 | + this.eventTypes = [...this.eventTypes, ...debugEventTypes]; | |
85 | + } | |
86 | + | |
87 | + this.eventTypeValue = defaultEventType; | |
88 | + | |
89 | + this.entityTranslations = { | |
90 | + noEntities: 'event.no-events-prompt' | |
91 | + }; | |
92 | + this.entityResources = { | |
93 | + } as EntityTypeResource; | |
94 | + this.entitiesFetchFunction = pageLink => this.fetchEvents(pageLink); | |
95 | + | |
96 | + this.defaultSortOrder = {property: 'createdTime', direction: Direction.DESC}; | |
97 | + | |
98 | + this.updateColumns(); | |
99 | + } | |
100 | + | |
101 | + fetchEvents(pageLink: TimePageLink): Observable<PageData<Event>> { | |
102 | + return this.eventService.getEvents(this.entityId, this.eventType, this.tenantId, pageLink); | |
103 | + } | |
104 | + | |
105 | + updateColumns(updateTableColumns: boolean = false): void { | |
106 | + this.columns = []; | |
107 | + this.columns.push( | |
108 | + new DateEntityTableColumn<Event>('createdTime', 'event.event-time', this.datePipe, '150px'), | |
109 | + new EntityTableColumn<Event>('server', 'event.server', '150px', | |
110 | + (entity) => entity.body.server, entity => ({}), false)); | |
111 | + switch (this.eventType) { | |
112 | + case EventType.ERROR: | |
113 | + this.columns.push( | |
114 | + new EntityTableColumn<Event>('method', 'event.method', '100%', | |
115 | + (entity) => entity.body.method, entity => ({}), false), | |
116 | + new EntityActionTableColumn<Event>('error', 'event.error', | |
117 | + { | |
118 | + name: this.translate.instant('action.view'), | |
119 | + icon: 'more_horiz', | |
120 | + isEnabled: (entity) => entity.body.error && entity.body.error.length > 0, | |
121 | + onAction: ($event, entity) => this.showContent($event, entity.body.error, 'event.error') | |
122 | + }, | |
123 | + '100px') | |
124 | + ); | |
125 | + break; | |
126 | + case EventType.LC_EVENT: | |
127 | + this.columns.push( | |
128 | + new EntityTableColumn<Event>('method', 'event.event', '100%', | |
129 | + (entity) => entity.body.event, entity => ({}), false), | |
130 | + new EntityTableColumn<Event>('status', 'event.status', '100%', | |
131 | + (entity) => | |
132 | + this.translate.instant(entity.body.success ? 'event.success' : 'event.failed'), entity => ({}), false), | |
133 | + new EntityActionTableColumn<Event>('error', 'event.error', | |
134 | + { | |
135 | + name: this.translate.instant('action.view'), | |
136 | + icon: 'more_horiz', | |
137 | + isEnabled: (entity) => entity.body.error && entity.body.error.length > 0, | |
138 | + onAction: ($event, entity) => this.showContent($event, entity.body.error, 'event.error') | |
139 | + }, | |
140 | + '100px') | |
141 | + ); | |
142 | + break; | |
143 | + case EventType.STATS: | |
144 | + this.columns.push( | |
145 | + new EntityTableColumn<Event>('messagesProcessed', 'event.messages-processed', '100%', | |
146 | + (entity) => entity.body.messagesProcessed + '', | |
147 | + entity => ({justifyContent: 'flex-end'}), | |
148 | + false, | |
149 | + key => ({justifyContent: 'flex-end'})), | |
150 | + new EntityTableColumn<Event>('errorsOccurred', 'event.errors-occurred', '100%', | |
151 | + (entity) => entity.body.errorsOccurred + '', | |
152 | + entity => ({justifyContent: 'flex-end'}), | |
153 | + false, | |
154 | + key => ({justifyContent: 'flex-end'})) | |
155 | + ); | |
156 | + break; | |
157 | + case DebugEventType.DEBUG_RULE_NODE: | |
158 | + case DebugEventType.DEBUG_RULE_CHAIN: | |
159 | + this.columns.push( | |
160 | + new EntityTableColumn<Event>('type', 'event.type', '100%', | |
161 | + (entity) => entity.body.type, entity => ({}), false), | |
162 | + new EntityTableColumn<Event>('entity', 'event.entity', '100%', | |
163 | + (entity) => entity.body.entityName, entity => ({}), false), | |
164 | + new EntityTableColumn<Event>('msgId', 'event.message-id', '100%', | |
165 | + (entity) => entity.body.msgId, entity => ({}), false), | |
166 | + new EntityTableColumn<Event>('msgType', 'event.message-type', '100%', | |
167 | + (entity) => entity.body.msgType, entity => ({}), false), | |
168 | + new EntityTableColumn<Event>('relationType', 'event.relation-type', '100%', | |
169 | + (entity) => entity.body.relationType, entity => ({}), false), | |
170 | + new EntityActionTableColumn<Event>('data', 'event.data', | |
171 | + { | |
172 | + name: this.translate.instant('action.view'), | |
173 | + icon: 'more_horiz', | |
174 | + isEnabled: (entity) => entity.body.data && entity.body.data.length > 0, | |
175 | + onAction: ($event, entity) => this.showContent($event, entity.body.data, | |
176 | + 'event.data', entity.body.dataType) | |
177 | + }, | |
178 | + '60px'), | |
179 | + new EntityActionTableColumn<Event>('metadata', 'event.metadata', | |
180 | + { | |
181 | + name: this.translate.instant('action.view'), | |
182 | + icon: 'more_horiz', | |
183 | + isEnabled: (entity) => entity.body.metadata && entity.body.metadata.length > 0, | |
184 | + onAction: ($event, entity) => this.showContent($event, entity.body.metadata, | |
185 | + 'event.metadata', MsgDataType.JSON) | |
186 | + }, | |
187 | + '60px'), | |
188 | + new EntityActionTableColumn<Event>('error', 'event.error', | |
189 | + { | |
190 | + name: this.translate.instant('action.view'), | |
191 | + icon: 'more_horiz', | |
192 | + isEnabled: (entity) => entity.body.error && entity.body.error.length > 0, | |
193 | + onAction: ($event, entity) => this.showContent($event, entity.body.error, | |
194 | + 'event.error') | |
195 | + }, | |
196 | + '60px') | |
197 | + ); | |
198 | + break; | |
199 | + } | |
200 | + if (updateTableColumns) { | |
201 | + this.table.columnsUpdated(true); | |
202 | + } | |
203 | + } | |
204 | + | |
205 | + showContent($event: MouseEvent, content: string, title: string, contentType: MsgDataType = null): void { | |
206 | + if ($event) { | |
207 | + $event.stopPropagation(); | |
208 | + } | |
209 | + // TODO: | |
210 | + this.dialogService.todo(); | |
211 | + } | |
212 | +} | ... | ... |
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2019 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | + | |
19 | +<mat-form-field class="mat-block" style="width: 200px;"> | |
20 | + <mat-label translate>event.event-type</mat-label> | |
21 | + <mat-select matInput [ngModel]="eventTableConfig.eventType" | |
22 | + (ngModelChange)="eventTypeChanged($event)"> | |
23 | + <mat-option *ngFor="let type of eventTableConfig.eventTypes" [value]="type"> | |
24 | + {{ eventTypeTranslationsMap.get(type) | translate }} | |
25 | + </mat-option> | |
26 | + </mat-select> | |
27 | +</mat-form-field> | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2019 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +:host { | |
17 | +/* flex: 1; | |
18 | + display: flex; | |
19 | + justify-content: flex-start; */ | |
20 | + padding-right: 8px; | |
21 | +} | |
22 | + | |
23 | +:host ::ng-deep { | |
24 | + mat-form-field { | |
25 | + font-size: 16px; | |
26 | + | |
27 | + .mat-form-field-wrapper { | |
28 | + padding-bottom: 0; | |
29 | + } | |
30 | + | |
31 | + .mat-form-field-underline { | |
32 | + bottom: 0; | |
33 | + } | |
34 | + } | |
35 | +} | ... | ... |
1 | +/// | |
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { Component } from '@angular/core'; | |
18 | +import { Store } from '@ngrx/store'; | |
19 | +import { AppState } from '@core/core.state'; | |
20 | +import { EntityTableHeaderComponent } from '../../components/entity/entity-table-header.component'; | |
21 | +import { DebugEventType, Event, EventType, eventTypeTranslations } from '@app/shared/models/event.models'; | |
22 | +import { EventTableConfig } from '@home/components/event/event-table-config'; | |
23 | + | |
24 | +@Component({ | |
25 | + selector: 'tb-event-table-header', | |
26 | + templateUrl: './event-table-header.component.html', | |
27 | + styleUrls: ['./event-table-header.component.scss'] | |
28 | +}) | |
29 | +export class EventTableHeaderComponent extends EntityTableHeaderComponent<Event> { | |
30 | + | |
31 | + eventTypeTranslationsMap = eventTypeTranslations; | |
32 | + | |
33 | + get eventTableConfig(): EventTableConfig { | |
34 | + return this.entitiesTableConfig as EventTableConfig; | |
35 | + } | |
36 | + | |
37 | + constructor(protected store: Store<AppState>) { | |
38 | + super(store); | |
39 | + } | |
40 | + | |
41 | + eventTypeChanged(eventType: EventType | DebugEventType) { | |
42 | + this.eventTableConfig.eventType = eventType; | |
43 | + this.eventTableConfig.table.updateData(); | |
44 | + } | |
45 | +} | ... | ... |
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2019 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<tb-entities-table [entitiesTableConfig]="eventTableConfig"></tb-entities-table> | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2019 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +:host ::ng-deep { | |
17 | + tb-entities-table { | |
18 | + .mat-drawer-container { | |
19 | + background-color: white; | |
20 | + } | |
21 | + } | |
22 | +} | ... | ... |
1 | +/// | |
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { Component, Input, OnInit, ViewChild } from '@angular/core'; | |
18 | +import { AuditLogService } from '@core/http/audit-log.service'; | |
19 | +import { TranslateService } from '@ngx-translate/core'; | |
20 | +import { DatePipe } from '@angular/common'; | |
21 | +import { MatDialog } from '@angular/material'; | |
22 | +import { AuditLogMode } from '@shared/models/audit-log.models'; | |
23 | +import { EntityId } from '@shared/models/id/entity-id'; | |
24 | +import { UserId } from '@shared/models/id/user-id'; | |
25 | +import { CustomerId } from '@shared/models/id/customer-id'; | |
26 | +import { AuditLogTableConfig } from '@home/components/audit-log/audit-log-table-config'; | |
27 | +import { EntitiesTableComponent } from '@home/components/entity/entities-table.component'; | |
28 | +import { Store } from '@ngrx/store'; | |
29 | +import { AppState } from '@core/core.state'; | |
30 | +import { Authority } from '@shared/models/authority.enum'; | |
31 | +import { getCurrentAuthUser } from '@core/auth/auth.selectors'; | |
32 | +import { EventTableConfig } from './event-table-config'; | |
33 | +import { EventService } from '@core/http/event.service'; | |
34 | +import { DialogService } from '@core/services/dialog.service'; | |
35 | +import { DebugEventType, EventType } from '@shared/models/event.models'; | |
36 | + | |
37 | +@Component({ | |
38 | + selector: 'tb-event-table', | |
39 | + templateUrl: './event-table.component.html', | |
40 | + styleUrls: ['./event-table.component.scss'] | |
41 | +}) | |
42 | +export class EventTableComponent implements OnInit { | |
43 | + | |
44 | + @Input() | |
45 | + tenantId: string; | |
46 | + | |
47 | + @Input() | |
48 | + defaultEventType: EventType | DebugEventType; | |
49 | + | |
50 | + @Input() | |
51 | + disabledEventTypes: Array<EventType | DebugEventType>; | |
52 | + | |
53 | + @Input() | |
54 | + debugEventTypes: Array<DebugEventType>; | |
55 | + | |
56 | + activeValue = false; | |
57 | + dirtyValue = false; | |
58 | + entityIdValue: EntityId; | |
59 | + | |
60 | + @Input() | |
61 | + set active(active: boolean) { | |
62 | + if (this.activeValue !== active) { | |
63 | + this.activeValue = active; | |
64 | + if (this.activeValue && this.dirtyValue) { | |
65 | + this.dirtyValue = false; | |
66 | + this.entitiesTable.updateData(); | |
67 | + } | |
68 | + } | |
69 | + } | |
70 | + | |
71 | + @Input() | |
72 | + set entityId(entityId: EntityId) { | |
73 | + this.entityIdValue = entityId; | |
74 | + if (this.eventTableConfig && this.eventTableConfig.entityId !== entityId) { | |
75 | + this.eventTableConfig.eventType = this.defaultEventType; | |
76 | + this.eventTableConfig.entityId = entityId; | |
77 | + this.entitiesTable.resetSortAndFilter(this.activeValue); | |
78 | + if (!this.activeValue) { | |
79 | + this.dirtyValue = true; | |
80 | + } | |
81 | + } | |
82 | + } | |
83 | + | |
84 | + @ViewChild(EntitiesTableComponent, {static: true}) entitiesTable: EntitiesTableComponent; | |
85 | + | |
86 | + eventTableConfig: EventTableConfig; | |
87 | + | |
88 | + constructor(private eventService: EventService, | |
89 | + private dialogService: DialogService, | |
90 | + private translate: TranslateService, | |
91 | + private datePipe: DatePipe, | |
92 | + private dialog: MatDialog, | |
93 | + private store: Store<AppState>) { | |
94 | + } | |
95 | + | |
96 | + ngOnInit() { | |
97 | + this.dirtyValue = !this.activeValue; | |
98 | + this.eventTableConfig = new EventTableConfig( | |
99 | + this.eventService, | |
100 | + this.dialogService, | |
101 | + this.translate, | |
102 | + this.datePipe, | |
103 | + this.dialog, | |
104 | + this.entityIdValue, | |
105 | + this.tenantId, | |
106 | + this.defaultEventType, | |
107 | + this.disabledEventTypes, | |
108 | + this.debugEventTypes | |
109 | + ); | |
110 | + } | |
111 | + | |
112 | +} | ... | ... |
... | ... | @@ -24,11 +24,14 @@ import {EntityDetailsPanelComponent} from './entity/entity-details-panel.compone |
24 | 24 | import {ContactComponent} from './contact.component'; |
25 | 25 | import { AuditLogDetailsDialogComponent } from './audit-log/audit-log-details-dialog.component'; |
26 | 26 | import { AuditLogTableComponent } from './audit-log/audit-log-table.component'; |
27 | +import { EventTableHeaderComponent } from '@home/components/event/event-table-header.component'; | |
28 | +import { EventTableComponent } from '@home/components/event/event-table.component'; | |
27 | 29 | |
28 | 30 | @NgModule({ |
29 | 31 | entryComponents: [ |
30 | 32 | AddEntityDialogComponent, |
31 | - AuditLogDetailsDialogComponent | |
33 | + AuditLogDetailsDialogComponent, | |
34 | + EventTableHeaderComponent | |
32 | 35 | ], |
33 | 36 | declarations: |
34 | 37 | [ |
... | ... | @@ -38,7 +41,9 @@ import { AuditLogTableComponent } from './audit-log/audit-log-table.component'; |
38 | 41 | EntityDetailsPanelComponent, |
39 | 42 | ContactComponent, |
40 | 43 | AuditLogTableComponent, |
41 | - AuditLogDetailsDialogComponent | |
44 | + AuditLogDetailsDialogComponent, | |
45 | + EventTableHeaderComponent, | |
46 | + EventTableComponent | |
42 | 47 | ], |
43 | 48 | imports: [ |
44 | 49 | CommonModule, |
... | ... | @@ -50,7 +55,8 @@ import { AuditLogTableComponent } from './audit-log/audit-log-table.component'; |
50 | 55 | DetailsPanelComponent, |
51 | 56 | EntityDetailsPanelComponent, |
52 | 57 | ContactComponent, |
53 | - AuditLogTableComponent | |
58 | + AuditLogTableComponent, | |
59 | + EventTableComponent | |
54 | 60 | ] |
55 | 61 | }) |
56 | 62 | export class HomeComponentsModule { } | ... | ... |
... | ... | @@ -50,6 +50,13 @@ export class EntitiesDataSource<T extends BaseData<HasId>, P extends PageLink = |
50 | 50 | this.pageDataSubject.complete(); |
51 | 51 | } |
52 | 52 | |
53 | + reset() { | |
54 | + const pageData = emptyPageData<T>(); | |
55 | + this.entitiesSubject.next(pageData.data); | |
56 | + this.pageDataSubject.next(pageData); | |
57 | + this.dataLoadedFunction(); | |
58 | + } | |
59 | + | |
53 | 60 | loadEntities(pageLink: P): Observable<PageData<T>> { |
54 | 61 | const result = new ReplaySubject<PageData<T>>(); |
55 | 62 | this.fetchFunction(pageLink).pipe( | ... | ... |
... | ... | @@ -41,6 +41,7 @@ export type EntityActionFunction<T extends BaseData<HasId>> = (action: EntityAct |
41 | 41 | export type CreateEntityOperation<T extends BaseData<HasId>> = () => Observable<T>; |
42 | 42 | |
43 | 43 | export type CellContentFunction<T extends BaseData<HasId>> = (entity: T, key: string) => string; |
44 | +export type HeaderCellStyleFunction<T extends BaseData<HasId>> = (key: string) => object; | |
44 | 45 | export type CellStyleFunction<T extends BaseData<HasId>> = (entity: T, key: string) => object; |
45 | 46 | |
46 | 47 | export interface CellActionDescriptor<T extends BaseData<HasId>> { |
... | ... | @@ -67,13 +68,35 @@ export interface HeaderActionDescriptor { |
67 | 68 | onAction: ($event: MouseEvent) => void; |
68 | 69 | } |
69 | 70 | |
70 | -export class EntityTableColumn<T extends BaseData<HasId>> { | |
71 | +export type EntityTableColumnType = 'content' | 'action'; | |
72 | + | |
73 | +export class BaseEntityTableColumn<T extends BaseData<HasId>> { | |
74 | + constructor(public type: EntityTableColumnType, | |
75 | + public key: string, | |
76 | + public title: string, | |
77 | + public maxWidth: string = '100%', | |
78 | + public sortable: boolean = true) { | |
79 | + } | |
80 | +} | |
81 | + | |
82 | +export class EntityTableColumn<T extends BaseData<HasId>> extends BaseEntityTableColumn<T> { | |
71 | 83 | constructor(public key: string, |
72 | 84 | public title: string, |
73 | 85 | public maxWidth: string = '100%', |
74 | 86 | public cellContentFunction: CellContentFunction<T> = (entity, property) => entity[property], |
75 | 87 | public cellStyleFunction: CellStyleFunction<T> = () => ({}), |
76 | - public sortable: boolean = true) { | |
88 | + public sortable: boolean = true, | |
89 | + public headerCellStyleFunction: HeaderCellStyleFunction<T> = () => ({})) { | |
90 | + super('content', key, title, maxWidth, sortable); | |
91 | + } | |
92 | +} | |
93 | + | |
94 | +export class EntityActionTableColumn<T extends BaseData<HasId>> extends BaseEntityTableColumn<T> { | |
95 | + constructor(public key: string, | |
96 | + public title: string, | |
97 | + public actionDescriptor: CellActionDescriptor<T>, | |
98 | + public maxWidth: string = '100%') { | |
99 | + super('action', key, title, maxWidth, false); | |
77 | 100 | } |
78 | 101 | } |
79 | 102 | |
... | ... | @@ -92,6 +115,8 @@ export class DateEntityTableColumn<T extends BaseData<HasId>> extends EntityTabl |
92 | 115 | } |
93 | 116 | } |
94 | 117 | |
118 | +export type EntityColumn<T extends BaseData<HasId>> = EntityTableColumn<T> | EntityActionTableColumn<T>; | |
119 | + | |
95 | 120 | export class EntityTableConfig<T extends BaseData<HasId>, P extends PageLink = PageLink> { |
96 | 121 | |
97 | 122 | constructor() {} |
... | ... | @@ -116,7 +141,7 @@ export class EntityTableConfig<T extends BaseData<HasId>, P extends PageLink = P |
116 | 141 | entityTabsComponent: Type<EntityTabsComponent<T>>; |
117 | 142 | addDialogStyle = {}; |
118 | 143 | defaultSortOrder: SortOrder = {property: 'createdTime', direction: Direction.ASC}; |
119 | - columns: Array<EntityTableColumn<T>> = []; | |
144 | + columns: Array<EntityColumn<T>> = []; | |
120 | 145 | cellActionDescriptors: Array<CellActionDescriptor<T>> = []; |
121 | 146 | groupActionDescriptors: Array<GroupActionDescriptor<T>> = []; |
122 | 147 | headerActionDescriptors: Array<HeaderActionDescriptor> = []; | ... | ... |
... | ... | @@ -15,6 +15,11 @@ |
15 | 15 | limitations under the License. |
16 | 16 | |
17 | 17 | --> |
18 | +<mat-tab *ngIf="entity" | |
19 | + label="{{ 'asset.events' | translate }}" #eventsTab="matTab"> | |
20 | + <tb-event-table [active]="eventsTab.isActive" [defaultEventType]="eventTypes.ERROR" [tenantId]="entity.tenantId.id" | |
21 | + [entityId]="entity.id"></tb-event-table> | |
22 | +</mat-tab> | |
18 | 23 | <mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" |
19 | 24 | label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> |
20 | 25 | <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table> | ... | ... |
... | ... | @@ -15,6 +15,11 @@ |
15 | 15 | limitations under the License. |
16 | 16 | |
17 | 17 | --> |
18 | +<mat-tab *ngIf="entity" | |
19 | + label="{{ 'customer.events' | translate }}" #eventsTab="matTab"> | |
20 | + <tb-event-table [active]="eventsTab.isActive" [defaultEventType]="eventTypes.ERROR" [tenantId]="entity.tenantId.id" | |
21 | + [entityId]="entity.id"></tb-event-table> | |
22 | +</mat-tab> | |
18 | 23 | <mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" |
19 | 24 | label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> |
20 | 25 | <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.CUSTOMER" [customerId]="entity.id" detailsMode="true"></tb-audit-log-table> | ... | ... |
... | ... | @@ -15,6 +15,11 @@ |
15 | 15 | limitations under the License. |
16 | 16 | |
17 | 17 | --> |
18 | +<mat-tab *ngIf="entity" | |
19 | + label="{{ 'device.events' | translate }}" #eventsTab="matTab"> | |
20 | + <tb-event-table [active]="eventsTab.isActive" [defaultEventType]="eventTypes.ERROR" [tenantId]="entity.tenantId.id" | |
21 | + [entityId]="entity.id"></tb-event-table> | |
22 | +</mat-tab> | |
18 | 23 | <mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" |
19 | 24 | label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> |
20 | 25 | <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table> | ... | ... |
... | ... | @@ -15,6 +15,11 @@ |
15 | 15 | limitations under the License. |
16 | 16 | |
17 | 17 | --> |
18 | +<mat-tab *ngIf="entity" | |
19 | + label="{{ 'entity-view.events' | translate }}" #eventsTab="matTab"> | |
20 | + <tb-event-table [active]="eventsTab.isActive" [defaultEventType]="eventTypes.ERROR" [tenantId]="entity.tenantId.id" | |
21 | + [entityId]="entity.id"></tb-event-table> | |
22 | +</mat-tab> | |
18 | 23 | <mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" |
19 | 24 | label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> |
20 | 25 | <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table> | ... | ... |
... | ... | @@ -15,6 +15,14 @@ |
15 | 15 | limitations under the License. |
16 | 16 | |
17 | 17 | --> |
18 | +<mat-tab *ngIf="entity" | |
19 | + label="{{ 'rulechain.events' | translate }}" #eventsTab="matTab"> | |
20 | + <tb-event-table [active]="eventsTab.isActive" | |
21 | + [debugEventTypes]="[debugEventTypes.DEBUG_RULE_CHAIN]" | |
22 | + [defaultEventType]="debugEventTypes.DEBUG_RULE_CHAIN" | |
23 | + [tenantId]="entity.tenantId.id" | |
24 | + [entityId]="entity.id"></tb-event-table> | |
25 | +</mat-tab> | |
18 | 26 | <mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" |
19 | 27 | label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> |
20 | 28 | <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table> | ... | ... |
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2019 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<mat-tab *ngIf="entity" | |
19 | + label="{{ 'tenant.events' | translate }}" #eventsTab="matTab"> | |
20 | + <tb-event-table [active]="eventsTab.isActive" [defaultEventType]="eventTypes.ERROR" [tenantId]="nullUid" | |
21 | + [entityId]="entity.id"></tb-event-table> | |
22 | +</mat-tab> | ... | ... |
1 | +/// | |
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { Component } from '@angular/core'; | |
18 | +import { Store } from '@ngrx/store'; | |
19 | +import { AppState } from '@core/core.state'; | |
20 | +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component'; | |
21 | +import { Tenant } from '@shared/models/tenant.model'; | |
22 | + | |
23 | +@Component({ | |
24 | + selector: 'tb-tenant-tabs', | |
25 | + templateUrl: './tenant-tabs.component.html', | |
26 | + styleUrls: [] | |
27 | +}) | |
28 | +export class TenantTabsComponent extends EntityTabsComponent<Tenant> { | |
29 | + | |
30 | + constructor(protected store: Store<AppState>) { | |
31 | + super(store); | |
32 | + } | |
33 | + | |
34 | + ngOnInit() { | |
35 | + super.ngOnInit(); | |
36 | + } | |
37 | + | |
38 | +} | ... | ... |
... | ... | @@ -20,13 +20,16 @@ import { SharedModule } from '@shared/shared.module'; |
20 | 20 | import {TenantComponent} from '@modules/home/pages/tenant/tenant.component'; |
21 | 21 | import {TenantRoutingModule} from '@modules/home/pages/tenant/tenant-routing.module'; |
22 | 22 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; |
23 | +import { TenantTabsComponent } from '@home/pages/tenant/tenant-tabs.component'; | |
23 | 24 | |
24 | 25 | @NgModule({ |
25 | 26 | entryComponents: [ |
26 | - TenantComponent | |
27 | + TenantComponent, | |
28 | + TenantTabsComponent | |
27 | 29 | ], |
28 | 30 | declarations: [ |
29 | - TenantComponent | |
31 | + TenantComponent, | |
32 | + TenantTabsComponent | |
30 | 33 | ], |
31 | 34 | imports: [ |
32 | 35 | CommonModule, | ... | ... |
... | ... | @@ -35,6 +35,7 @@ import { |
35 | 35 | import { TenantComponent } from '@modules/home/pages/tenant/tenant.component'; |
36 | 36 | import { EntityAction } from '@home/models/entity/entity-component.models'; |
37 | 37 | import { User } from '@shared/models/user.model'; |
38 | +import { TenantTabsComponent } from '@home/pages/tenant/tenant-tabs.component'; | |
38 | 39 | |
39 | 40 | @Injectable() |
40 | 41 | export class TenantsTableConfigResolver implements Resolve<EntityTableConfig<Tenant>> { |
... | ... | @@ -48,6 +49,7 @@ export class TenantsTableConfigResolver implements Resolve<EntityTableConfig<Ten |
48 | 49 | |
49 | 50 | this.config.entityType = EntityType.TENANT; |
50 | 51 | this.config.entityComponent = TenantComponent; |
52 | + this.config.entityTabsComponent = TenantTabsComponent; | |
51 | 53 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.TENANT); |
52 | 54 | this.config.entityResources = entityTypeResources.get(EntityType.TENANT); |
53 | 55 | ... | ... |
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2019 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" | |
19 | + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> | |
20 | + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.USER" [userId]="entity.id" detailsMode="true"></tb-audit-log-table> | |
21 | +</mat-tab> | ... | ... |
1 | +/// | |
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { Component } from '@angular/core'; | |
18 | +import { Store } from '@ngrx/store'; | |
19 | +import { AppState } from '@core/core.state'; | |
20 | +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component'; | |
21 | +import { User } from '@app/shared/models/user.model'; | |
22 | + | |
23 | +@Component({ | |
24 | + selector: 'tb-user-tabs', | |
25 | + templateUrl: './user-tabs.component.html', | |
26 | + styleUrls: [] | |
27 | +}) | |
28 | +export class UserTabsComponent extends EntityTabsComponent<User> { | |
29 | + | |
30 | + constructor(protected store: Store<AppState>) { | |
31 | + super(store); | |
32 | + } | |
33 | + | |
34 | + ngOnInit() { | |
35 | + super.ngOnInit(); | |
36 | + } | |
37 | + | |
38 | +} | ... | ... |
... | ... | @@ -22,15 +22,18 @@ import { UserRoutingModule } from '@modules/home/pages/user/user-routing.module' |
22 | 22 | import { AddUserDialogComponent } from '@modules/home/pages/user/add-user-dialog.component'; |
23 | 23 | import { ActivationLinkDialogComponent } from '@modules/home/pages/user/activation-link-dialog.component'; |
24 | 24 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; |
25 | +import { UserTabsComponent } from '@home/pages/user/user-tabs.component'; | |
25 | 26 | |
26 | 27 | @NgModule({ |
27 | 28 | entryComponents: [ |
28 | 29 | UserComponent, |
30 | + UserTabsComponent, | |
29 | 31 | AddUserDialogComponent, |
30 | 32 | ActivationLinkDialogComponent |
31 | 33 | ], |
32 | 34 | declarations: [ |
33 | 35 | UserComponent, |
36 | + UserTabsComponent, | |
34 | 37 | AddUserDialogComponent, |
35 | 38 | ActivationLinkDialogComponent |
36 | 39 | ], | ... | ... |
... | ... | @@ -57,6 +57,7 @@ import { NULL_UUID } from '@shared/models/id/has-uuid'; |
57 | 57 | import { Customer } from '@shared/models/customer.model'; |
58 | 58 | import {TenantService} from '@app/core/http/tenant.service'; |
59 | 59 | import {TenantId} from '@app/shared/models/id/tenant-id'; |
60 | +import { UserTabsComponent } from '@home/pages/user/user-tabs.component'; | |
60 | 61 | |
61 | 62 | export interface UsersTableRouteData { |
62 | 63 | authority: Authority; |
... | ... | @@ -83,6 +84,7 @@ export class UsersTableConfigResolver implements Resolve<EntityTableConfig<User> |
83 | 84 | |
84 | 85 | this.config.entityType = EntityType.USER; |
85 | 86 | this.config.entityComponent = UserComponent; |
87 | + this.config.entityTabsComponent = UserTabsComponent; | |
86 | 88 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.USER); |
87 | 89 | this.config.entityResources = entityTypeResources.get(EntityType.USER); |
88 | 90 | ... | ... |
ui-ngx/src/app/shared/models/event.models.ts
0 → 100644
1 | +/// | |
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { ActionStatus, ActionType } from '@shared/models/audit-log.models'; | |
18 | +import { BaseData } from '@shared/models/base-data'; | |
19 | +import { AuditLogId } from '@shared/models/id/audit-log-id'; | |
20 | +import { TenantId } from '@shared/models/id/tenant-id'; | |
21 | +import { CustomerId } from '@shared/models/id/customer-id'; | |
22 | +import { EntityId } from '@shared/models/id/entity-id'; | |
23 | +import { UserId } from '@shared/models/id/user-id'; | |
24 | +import { EventId } from './id/event-id'; | |
25 | +import { MsgDataType } from './rule-node.models'; | |
26 | + | |
27 | +export enum EventType { | |
28 | + ERROR = 'ERROR', | |
29 | + LC_EVENT = 'LC_EVENT', | |
30 | + STATS = 'STATS' | |
31 | +} | |
32 | + | |
33 | +export enum DebugEventType { | |
34 | + DEBUG_RULE_NODE = 'DEBUG_RULE_NODE', | |
35 | + DEBUG_RULE_CHAIN = 'DEBUG_RULE_CHAIN' | |
36 | +} | |
37 | + | |
38 | +export const eventTypeTranslations = new Map<EventType | DebugEventType, string>( | |
39 | + [ | |
40 | + [EventType.ERROR, 'event.type-error'], | |
41 | + [EventType.LC_EVENT, 'event.type-lc-event'], | |
42 | + [EventType.STATS, 'event.type-stats'], | |
43 | + [DebugEventType.DEBUG_RULE_NODE, 'event.type-debug-rule-node'], | |
44 | + [DebugEventType.DEBUG_RULE_CHAIN, 'event.type-debug-rule-chain'], | |
45 | + ] | |
46 | +); | |
47 | + | |
48 | +export interface BaseEventBody { | |
49 | + server: string; | |
50 | +} | |
51 | + | |
52 | +export interface ErrorEventBody extends BaseEventBody { | |
53 | + method: string; | |
54 | + error: string; | |
55 | +} | |
56 | + | |
57 | +export interface LcEventEventBody extends BaseEventBody { | |
58 | + event: string; | |
59 | + success: boolean; | |
60 | + error: string; | |
61 | +} | |
62 | + | |
63 | +export interface StatsEventBody extends BaseEventBody { | |
64 | + messagesProcessed: number; | |
65 | + errorsOccurred: number; | |
66 | +} | |
67 | + | |
68 | +export interface DebugRuleNodeEventBody extends BaseEventBody { | |
69 | + type: string; | |
70 | + entityId: string; | |
71 | + entityName: string; | |
72 | + msgId: string; | |
73 | + msgType: string; | |
74 | + relationType: string; | |
75 | + dataType: MsgDataType; | |
76 | + data: string; | |
77 | + metadata: string; | |
78 | + error: string; | |
79 | +} | |
80 | + | |
81 | +export type EventBody = ErrorEventBody & LcEventEventBody & StatsEventBody & DebugRuleNodeEventBody; | |
82 | + | |
83 | +export interface Event extends BaseData<EventId> { | |
84 | + tenantId: TenantId; | |
85 | + entityId: EntityId; | |
86 | + type: string; | |
87 | + uid: string; | |
88 | + body: EventBody; | |
89 | +} | ... | ... |
ui-ngx/src/app/shared/models/id/event-id.ts
0 → 100644
1 | +/// | |
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { HasUUID } from '@shared/models/id/has-uuid'; | |
18 | + | |
19 | +export class EventId implements HasUUID { | |
20 | + id: string; | |
21 | + constructor(id: string) { | |
22 | + this.id = id; | |
23 | + } | |
24 | +} | ... | ... |
... | ... | @@ -21,6 +21,12 @@ import {CustomerId} from '@shared/models/id/customer-id'; |
21 | 21 | import {RuleChainId} from '@shared/models/id/rule-chain-id'; |
22 | 22 | import {RuleNodeId} from '@shared/models/id/rule-node-id'; |
23 | 23 | |
24 | +export enum MsgDataType { | |
25 | + JSON = 'JSON', | |
26 | + TEXT = 'TEXT', | |
27 | + BINARY = 'BINARY' | |
28 | +} | |
29 | + | |
24 | 30 | export interface RuleNodeConfiguration { |
25 | 31 | todo: Array<any>; |
26 | 32 | // TODO: | ... | ... |