Commit aedebc32eb311e203e095dcfe88051dbb600b0a6

Authored by VoBa
Committed by GitHub
2 parents 10d3dd01 f470a7ca

Merge pull request #78 from deaflynx/develop/3.3-edge

Develop/3.3 edge: changes in Edge Downlinks, Edge Widget, fix for edge rule chains missing tooltips
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 "templateHtml": "<tb-edges-overview-widget \n [ctx]=\"ctx\">\n</tb-edges-overview-widget>", 16 "templateHtml": "<tb-edges-overview-widget \n [ctx]=\"ctx\">\n</tb-edges-overview-widget>",
17 "templateCss": "", 17 "templateCss": "",
18 "controllerScript": "self.onInit = function() {\n};\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n dataKeysOptional: true\n };\n}\n\nself.onDestroy = function() {\n};\n", 18 "controllerScript": "self.onInit = function() {\n};\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n dataKeysOptional: true\n };\n}\n\nself.onDestroy = function() {\n};\n",
19 - "settingsSchema": "{}\n", 19 + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EdgeOverviewSettings\",\n \"properties\": {\n \"enableDefaultTitle\": {\n \"title\": \"Display default title\",\n \"type\": \"boolean\",\n \"default\": true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"enableDefaultTitle\"\n ]\n}",
20 "dataKeySettingsSchema": "{}\n", 20 "dataKeySettingsSchema": "{}\n",
21 "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"showTitleIcon\":true,\"titleIcon\":\"router\",\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{},\"title\":\"Edge Quick Overview\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"}]}],\"widgetStyle\":{},\"actions\":{}}" 21 "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"showTitleIcon\":true,\"titleIcon\":\"router\",\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{},\"title\":\"Edge Quick Overview\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"}]}],\"widgetStyle\":{},\"actions\":{}}"
22 } 22 }
@@ -76,8 +76,10 @@ import { @@ -76,8 +76,10 @@ import {
76 } from '@shared/models/query/query.models'; 76 } from '@shared/models/query/query.models';
77 import { alarmFields } from '@shared/models/alarm.models'; 77 import { alarmFields } from '@shared/models/alarm.models';
78 import { EdgeService } from "@core/http/edge.service"; 78 import { EdgeService } from "@core/http/edge.service";
  79 +import { Edge, EdgeEventType } from '@shared/models/edge.models';
79 import { RuleChainType } from "@shared/models/rule-chain.models"; 80 import { RuleChainType } from "@shared/models/rule-chain.models";
80 -import { Edge } from '@shared/models/edge.models'; 81 +import { WidgetService } from "@core/http/widget.service";
  82 +import { DeviceProfileService } from "@core/http/device-profile.service";
81 83
82 @Injectable({ 84 @Injectable({
83 providedIn: 'root' 85 providedIn: 'root'
@@ -98,6 +100,8 @@ export class EntityService { @@ -98,6 +100,8 @@ export class EntityService {
98 private dashboardService: DashboardService, 100 private dashboardService: DashboardService,
99 private entityRelationService: EntityRelationService, 101 private entityRelationService: EntityRelationService,
100 private attributeService: AttributeService, 102 private attributeService: AttributeService,
  103 + private widgetService: WidgetService,
  104 + private deviceProfileService: DeviceProfileService,
101 private utils: UtilsService 105 private utils: UtilsService
102 ) { } 106 ) { }
103 107
@@ -1316,4 +1320,40 @@ export class EntityService { @@ -1316,4 +1320,40 @@ export class EntityService {
1316 } 1320 }
1317 return entitiesObservable; 1321 return entitiesObservable;
1318 } 1322 }
  1323 +
  1324 + public getEdgeEventContentByEntityType(entity: any): Observable<any> {
  1325 + let entityObservable: Observable<any>;
  1326 + const entityId: string = entity.entityId;
  1327 + const entityType: any = entity.type;
  1328 + switch (entityType) {
  1329 + case EdgeEventType.DASHBOARD:
  1330 + case EdgeEventType.ALARM:
  1331 + case EdgeEventType.RULE_CHAIN:
  1332 + case EdgeEventType.EDGE:
  1333 + case EdgeEventType.USER:
  1334 + case EdgeEventType.CUSTOMER:
  1335 + case EdgeEventType.TENANT:
  1336 + case EdgeEventType.ASSET:
  1337 + case EdgeEventType.DEVICE:
  1338 + case EdgeEventType.ENTITY_VIEW:
  1339 + entityObservable = this.getEntity(entityType, entityId, { ignoreLoading: true, ignoreErrors: true });
  1340 + break;
  1341 + case EdgeEventType.RULE_CHAIN_METADATA:
  1342 + entityObservable = this.ruleChainService.getRuleChainMetadata(entityId);
  1343 + break;
  1344 + case EdgeEventType.WIDGET_TYPE:
  1345 + entityObservable = this.widgetService.getWidgetTypeById(entityId);
  1346 + break;
  1347 + case EdgeEventType.WIDGETS_BUNDLE:
  1348 + entityObservable = this.widgetService.getWidgetsBundle(entityId);
  1349 + break;
  1350 + case EdgeEventType.DEVICE_PROFILE:
  1351 + entityObservable = this.deviceProfileService.getDeviceProfile(entityId);
  1352 + break;
  1353 + case EdgeEventType.RELATION:
  1354 + entityObservable = of(entity.body);
  1355 + break;
  1356 + }
  1357 + return entityObservable;
  1358 + }
1319 } 1359 }
@@ -21,7 +21,8 @@ import { @@ -21,7 +21,8 @@ import {
21 EntityTableConfig 21 EntityTableConfig
22 } from '@home/models/entity/entities-table-config.models'; 22 } from '@home/models/entity/entities-table-config.models';
23 import { 23 import {
24 - EdgeEvent, edgeEventActionTypeTranslations, 24 + EdgeEvent,
  25 + edgeEventActionTypeTranslations,
25 EdgeEventStatus, 26 EdgeEventStatus,
26 edgeEventStatusColor, 27 edgeEventStatusColor,
27 EdgeEventType, 28 EdgeEventType,
@@ -33,7 +34,7 @@ import { DatePipe } from '@angular/common'; @@ -33,7 +34,7 @@ import { DatePipe } from '@angular/common';
33 import { MatDialog } from '@angular/material/dialog'; 34 import { MatDialog } from '@angular/material/dialog';
34 import { EntityId } from '@shared/models/id/entity-id'; 35 import { EntityId } from '@shared/models/id/entity-id';
35 import { EntityTypeResource } from '@shared/models/entity-type.models'; 36 import { EntityTypeResource } from '@shared/models/entity-type.models';
36 -import { Observable, of } from 'rxjs'; 37 +import { Observable } from 'rxjs';
37 import { PageData } from '@shared/models/page/page-data'; 38 import { PageData } from '@shared/models/page/page-data';
38 import { Direction } from '@shared/models/page/sort-order'; 39 import { Direction } from '@shared/models/page/sort-order';
39 import { DialogService } from '@core/services/dialog.service'; 40 import { DialogService } from '@core/services/dialog.service';
@@ -42,37 +43,29 @@ import { @@ -42,37 +43,29 @@ import {
42 EventContentDialogComponent, 43 EventContentDialogComponent,
43 EventContentDialogData 44 EventContentDialogData
44 } from '@home/components/event/event-content-dialog.component'; 45 } from '@home/components/event/event-content-dialog.component';
45 -import { sortObjectKeys } from '@core/utils';  
46 -import { RuleChainService } from '@core/http/rule-chain.service';  
47 import { AttributeService } from '@core/http/attribute.service'; 46 import { AttributeService } from '@core/http/attribute.service';
48 import { AttributeScope } from '@shared/models/telemetry/telemetry.models'; 47 import { AttributeScope } from '@shared/models/telemetry/telemetry.models';
49 import { EdgeDownlinkTableHeaderComponent } from '@home/components/edge/edge-downlink-table-header.component'; 48 import { EdgeDownlinkTableHeaderComponent } from '@home/components/edge/edge-downlink-table-header.component';
50 import { EdgeService } from '@core/http/edge.service'; 49 import { EdgeService } from '@core/http/edge.service';
51 import { map } from 'rxjs/operators'; 50 import { map } from 'rxjs/operators';
52 -import { AssetService } from '@core/http/asset.service';  
53 -import { DeviceService } from '@core/http/device.service';  
54 -import { EntityViewService } from '@core/http/entity-view.service';  
55 -import { EventTableHeaderComponent } from '@home/components/event/event-table-header.component'; 51 +import { EntityService } from "@core/http/entity.service";
56 52
57 export class EdgeDownlinkTableConfig extends EntityTableConfig<EdgeEvent, TimePageLink> { 53 export class EdgeDownlinkTableConfig extends EntityTableConfig<EdgeEvent, TimePageLink> {
58 54
59 queueStartTs: number; 55 queueStartTs: number;
60 56
61 constructor(private edgeService: EdgeService, 57 constructor(private edgeService: EdgeService,
  58 + private entityService: EntityService,
62 private dialogService: DialogService, 59 private dialogService: DialogService,
63 private translate: TranslateService, 60 private translate: TranslateService,
64 - private deviceService: DeviceService,  
65 - private assetService: AssetService,  
66 - private entityViewService: EntityViewService,  
67 - private ruleChainService: RuleChainService,  
68 private attributeService: AttributeService, 61 private attributeService: AttributeService,
69 private datePipe: DatePipe, 62 private datePipe: DatePipe,
70 private dialog: MatDialog, 63 private dialog: MatDialog,
71 - public entityId: EntityId,  
72 - public tenantId: string) { 64 + public entityId: EntityId) {
73 super(); 65 super();
74 - this.loadDataOnInit = false; 66 +
75 this.tableTitle = ''; 67 this.tableTitle = '';
  68 + this.loadDataOnInit = false;
76 this.useTimePageLink = true; 69 this.useTimePageLink = true;
77 this.detailsPanelEnabled = false; 70 this.detailsPanelEnabled = false;
78 this.selectionEnabled = false; 71 this.selectionEnabled = false;
@@ -81,13 +74,11 @@ export class EdgeDownlinkTableConfig extends EntityTableConfig<EdgeEvent, TimePa @@ -81,13 +74,11 @@ export class EdgeDownlinkTableConfig extends EntityTableConfig<EdgeEvent, TimePa
81 this.entitiesDeleteEnabled = false; 74 this.entitiesDeleteEnabled = false;
82 75
83 this.headerComponent = EdgeDownlinkTableHeaderComponent; 76 this.headerComponent = EdgeDownlinkTableHeaderComponent;
84 -  
85 this.entityTranslations = { 77 this.entityTranslations = {
86 noEntities: 'edge.no-downlinks-prompt' 78 noEntities: 'edge.no-downlinks-prompt'
87 }; 79 };
88 this.entityResources = {} as EntityTypeResource<EdgeEvent>; 80 this.entityResources = {} as EntityTypeResource<EdgeEvent>;
89 this.entitiesFetchFunction = pageLink => this.fetchEvents(pageLink); 81 this.entitiesFetchFunction = pageLink => this.fetchEvents(pageLink);
90 -  
91 this.defaultSortOrder = {property: 'createdTime', direction: Direction.DESC}; 82 this.defaultSortOrder = {property: 'createdTime', direction: Direction.DESC};
92 83
93 this.updateColumns(); 84 this.updateColumns();
@@ -98,6 +89,24 @@ export class EdgeDownlinkTableConfig extends EntityTableConfig<EdgeEvent, TimePa @@ -98,6 +89,24 @@ export class EdgeDownlinkTableConfig extends EntityTableConfig<EdgeEvent, TimePa
98 return this.edgeService.getEdgeEvents(this.entityId, pageLink); 89 return this.edgeService.getEdgeEvents(this.entityId, pageLink);
99 } 90 }
100 91
  92 + loadEdgeInfo(): void {
  93 + this.attributeService.getEntityAttributes(this.entityId, AttributeScope.SERVER_SCOPE, ['queueStartTs'])
  94 + .subscribe(
  95 + attributes => this.onUpdate(attributes)
  96 + );
  97 + }
  98 +
  99 + onUpdate(attributes) {
  100 + this.queueStartTs = 0;
  101 + let edge = attributes.reduce(function (map, attribute) {
  102 + map[attribute.key] = attribute;
  103 + return map;
  104 + }, {});
  105 + if (edge.queueStartTs) {
  106 + this.queueStartTs = edge.queueStartTs.lastUpdateTs;
  107 + }
  108 + }
  109 +
101 updateColumns(updateTableColumns: boolean = false): void { 110 updateColumns(updateTableColumns: boolean = false): void {
102 this.columns = []; 111 this.columns = [];
103 this.columns.push( 112 this.columns.push(
@@ -132,31 +141,20 @@ export class EdgeDownlinkTableConfig extends EntityTableConfig<EdgeEvent, TimePa @@ -132,31 +141,20 @@ export class EdgeDownlinkTableConfig extends EntityTableConfig<EdgeEvent, TimePa
132 } 141 }
133 } 142 }
134 143
135 - showContent($event: MouseEvent, content: string, title: string, contentType: ContentType = null, sortKeys = false): void {  
136 - if ($event) {  
137 - $event.stopPropagation();  
138 - }  
139 - if (contentType === ContentType.JSON && sortKeys) {  
140 - try {  
141 - content = JSON.stringify(sortObjectKeys(JSON.parse(content)));  
142 - } catch (e) {  
143 - } 144 + updateEdgeEventStatus(createdTime): string {
  145 + if (this.queueStartTs && createdTime < this.queueStartTs) {
  146 + return this.translate.instant('edge.deployed');
  147 + } else {
  148 + return this.translate.instant('edge.pending');
144 } 149 }
145 - this.dialog.open<EventContentDialogComponent, EventContentDialogData>(EventContentDialogComponent, {  
146 - disableClose: true,  
147 - panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],  
148 - data: {  
149 - content,  
150 - title,  
151 - contentType  
152 - }  
153 - });  
154 } 150 }
155 151
156 - isEdgeEventHasData(edgeEventType: EdgeEventType) { 152 + isPending(createdTime): boolean {
  153 + return createdTime > this.queueStartTs;
  154 + }
  155 +
  156 + isEdgeEventHasData(edgeEventType: EdgeEventType): boolean {
157 switch (edgeEventType) { 157 switch (edgeEventType) {
158 - case EdgeEventType.WIDGET_TYPE:  
159 - case EdgeEventType.WIDGETS_BUNDLE:  
160 case EdgeEventType.ADMIN_SETTINGS: 158 case EdgeEventType.ADMIN_SETTINGS:
161 return false; 159 return false;
162 default: 160 default:
@@ -164,90 +162,24 @@ export class EdgeDownlinkTableConfig extends EntityTableConfig<EdgeEvent, TimePa @@ -164,90 +162,24 @@ export class EdgeDownlinkTableConfig extends EntityTableConfig<EdgeEvent, TimePa
164 } 162 }
165 } 163 }
166 164
167 - prepareEdgeEventContent(entity) {  
168 - // TODO: voba - extend this function with different cases based on action and entity type  
169 - switch (entity.type) {  
170 - case EdgeEventType.RELATION:  
171 - return of(JSON.stringify(entity.body));  
172 - case EdgeEventType.ASSET:  
173 - return this.assetService.getAsset(entity.entityId, null).pipe(  
174 - map((asset) => {  
175 - return JSON.stringify(asset);  
176 - })  
177 - );  
178 - case EdgeEventType.DEVICE:  
179 - return this.deviceService.getDevice(entity.entityId, null).pipe(  
180 - map((device) => {  
181 - return JSON.stringify(device);  
182 - })  
183 - );  
184 - case EdgeEventType.ENTITY_VIEW:  
185 - return this.entityViewService.getEntityView(entity.entityId, null).pipe(  
186 - map((entityView) => {  
187 - return JSON.stringify(entityView);  
188 - })  
189 - );  
190 - case EdgeEventType.RULE_CHAIN_METADATA:  
191 - return this.ruleChainService.getRuleChainMetadata(entity.entityId, null).pipe(  
192 - map((ruleChainMetaData) => {  
193 - return JSON.stringify(ruleChainMetaData.nodes);  
194 - })  
195 - );  
196 - default:  
197 - return of(JSON.stringify(entity));  
198 - } 165 + prepareEdgeEventContent(entity: any): Observable<string> {
  166 + return this.entityService.getEdgeEventContentByEntityType(entity).pipe(
  167 + map((result) => JSON.stringify(result))
  168 + );
199 } 169 }
200 170
201 - showEdgeEventContent($event: MouseEvent, content: string, title: string, sortKeys = false): void { 171 + showEdgeEventContent($event: MouseEvent, content: string, title: string): void {
202 if ($event) { 172 if ($event) {
203 $event.stopPropagation(); 173 $event.stopPropagation();
204 } 174 }
205 - var contentType = ContentType.JSON;  
206 - if (contentType === ContentType.JSON && sortKeys) {  
207 - try {  
208 - content = JSON.stringify(sortObjectKeys(JSON.parse(content)));  
209 - } catch (e) {  
210 - }  
211 - }  
212 this.dialog.open<EventContentDialogComponent, EventContentDialogData>(EventContentDialogComponent, { 175 this.dialog.open<EventContentDialogComponent, EventContentDialogData>(EventContentDialogComponent, {
213 disableClose: true, 176 disableClose: true,
214 panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], 177 panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
215 data: { 178 data: {
216 content, 179 content,
217 title, 180 title,
218 - contentType 181 + contentType: ContentType.JSON
219 } 182 }
220 }); 183 });
221 } 184 }
222 -  
223 - updateEdgeEventStatus(createdTime) {  
224 - if (this.queueStartTs && createdTime < this.queueStartTs) {  
225 - return this.translate.instant('edge.deployed');  
226 - } else {  
227 - return this.translate.instant('edge.pending');  
228 - }  
229 - }  
230 -  
231 - isPending(createdTime) {  
232 - return createdTime > this.queueStartTs;  
233 - }  
234 -  
235 - loadEdgeInfo() {  
236 - this.attributeService.getEntityAttributes(this.entityId, AttributeScope.SERVER_SCOPE, ['queueStartTs'])  
237 - .subscribe(  
238 - attributes => this.onUpdate(attributes)  
239 - );  
240 - }  
241 -  
242 - onUpdate(attributes) {  
243 - this.queueStartTs = 0;  
244 - let edge = attributes.reduce(function (map, attribute) {  
245 - map[attribute.key] = attribute;  
246 - return map;  
247 - }, {});  
248 - if (edge.queueStartTs) {  
249 - this.queueStartTs = edge.queueStartTs.lastUpdateTs;  
250 - }  
251 - }  
252 } 185 }
253 -  
@@ -22,12 +22,9 @@ import { EntityId } from '@shared/models/id/entity-id'; @@ -22,12 +22,9 @@ import { EntityId } from '@shared/models/id/entity-id';
22 import { EntitiesTableComponent } from '@home/components/entity/entities-table.component'; 22 import { EntitiesTableComponent } from '@home/components/entity/entities-table.component';
23 import { EdgeDownlinkTableConfig } from './edge-downlink-table-config'; 23 import { EdgeDownlinkTableConfig } from './edge-downlink-table-config';
24 import { DialogService } from '@core/services/dialog.service'; 24 import { DialogService } from '@core/services/dialog.service';
25 -import { RuleChainService } from '@core/http/rule-chain.service';  
26 import { AttributeService } from '@core/http/attribute.service'; 25 import { AttributeService } from '@core/http/attribute.service';
27 import { EdgeService } from '@core/http/edge.service'; 26 import { EdgeService } from '@core/http/edge.service';
28 -import { DeviceService } from '@core/http/device.service';  
29 -import { AssetService } from '@core/http/asset.service';  
30 -import { EntityViewService } from '@core/http/entity-view.service'; 27 +import { EntityService } from "@core/http/entity.service";
31 28
32 @Component({ 29 @Component({
33 selector: 'tb-edge-downlink-table', 30 selector: 'tb-edge-downlink-table',
@@ -36,9 +33,6 @@ import { EntityViewService } from '@core/http/entity-view.service'; @@ -36,9 +33,6 @@ import { EntityViewService } from '@core/http/entity-view.service';
36 }) 33 })
37 export class EdgeDownlinkTableComponent implements OnInit { 34 export class EdgeDownlinkTableComponent implements OnInit {
38 35
39 - @Input()  
40 - tenantId: string;  
41 -  
42 activeValue = false; 36 activeValue = false;
43 dirtyValue = false; 37 dirtyValue = false;
44 entityIdValue: EntityId; 38 entityIdValue: EntityId;
@@ -71,13 +65,10 @@ export class EdgeDownlinkTableComponent implements OnInit { @@ -71,13 +65,10 @@ export class EdgeDownlinkTableComponent implements OnInit {
71 edgeDownlinkTableConfig: EdgeDownlinkTableConfig; 65 edgeDownlinkTableConfig: EdgeDownlinkTableConfig;
72 66
73 constructor(private edgeService: EdgeService, 67 constructor(private edgeService: EdgeService,
74 - private deviceService: DeviceService,  
75 - private assetService: AssetService,  
76 - private entityViewService: EntityViewService, 68 + private entityService: EntityService,
77 private dialogService: DialogService, 69 private dialogService: DialogService,
78 private translate: TranslateService, 70 private translate: TranslateService,
79 private attributeService: AttributeService, 71 private attributeService: AttributeService,
80 - private ruleChainService: RuleChainService,  
81 private datePipe: DatePipe, 72 private datePipe: DatePipe,
82 private dialog: MatDialog) { 73 private dialog: MatDialog) {
83 } 74 }
@@ -86,17 +77,13 @@ export class EdgeDownlinkTableComponent implements OnInit { @@ -86,17 +77,13 @@ export class EdgeDownlinkTableComponent implements OnInit {
86 this.dirtyValue = !this.activeValue; 77 this.dirtyValue = !this.activeValue;
87 this.edgeDownlinkTableConfig = new EdgeDownlinkTableConfig( 78 this.edgeDownlinkTableConfig = new EdgeDownlinkTableConfig(
88 this.edgeService, 79 this.edgeService,
  80 + this.entityService,
89 this.dialogService, 81 this.dialogService,
90 this.translate, 82 this.translate,
91 - this.deviceService,  
92 - this.assetService,  
93 - this.entityViewService,  
94 - this.ruleChainService,  
95 this.attributeService, 83 this.attributeService,
96 this.datePipe, 84 this.datePipe,
97 this.dialog, 85 this.dialog,
98 - this.entityIdValue,  
99 - this.tenantId 86 + this.entityIdValue
100 ); 87 );
101 } 88 }
102 89
@@ -41,6 +41,11 @@ import { BaseData, HasId } from '@shared/models/base-data'; @@ -41,6 +41,11 @@ import { BaseData, HasId } from '@shared/models/base-data';
41 import { EntityId } from '@shared/models/id/entity-id'; 41 import { EntityId } from '@shared/models/id/entity-id';
42 import { getCurrentAuthUser } from '@core/auth/auth.selectors'; 42 import { getCurrentAuthUser } from '@core/auth/auth.selectors';
43 import { Authority } from '@shared/models/authority.enum'; 43 import { Authority } from '@shared/models/authority.enum';
  44 +import { isDefined } from '@core/utils';
  45 +
  46 +interface EdgesOverviewWidgetSettings {
  47 + enableDefaultTitle: boolean;
  48 +}
44 49
45 @Component({ 50 @Component({
46 selector: 'tb-edges-overview-widget', 51 selector: 'tb-edges-overview-widget',
@@ -59,12 +64,10 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni @@ -59,12 +64,10 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni
59 private widgetConfig: WidgetConfig; 64 private widgetConfig: WidgetConfig;
60 private subscription: IWidgetSubscription; 65 private subscription: IWidgetSubscription;
61 private datasources: Array<EntityNodeDatasource>; 66 private datasources: Array<EntityNodeDatasource>;
  67 + private settings: EdgesOverviewWidgetSettings;
62 68
63 private nodeIdCounter = 0; 69 private nodeIdCounter = 0;
64 70
65 - private entityNodesMap: {[parentNodeId: string]: {[edgeId: string]: string}} = {};  
66 - private entityGroupsNodesMap: {[edgeNodeId: string]: {[groupType: string]: string}} = {};  
67 -  
68 constructor(protected store: Store<AppState>, 71 constructor(protected store: Store<AppState>,
69 private edgeService: EdgeService, 72 private edgeService: EdgeService,
70 private entityService: EntityService, 73 private entityService: EntityService,
@@ -78,6 +81,8 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni @@ -78,6 +81,8 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni
78 this.widgetConfig = this.ctx.widgetConfig; 81 this.widgetConfig = this.ctx.widgetConfig;
79 this.subscription = this.ctx.defaultSubscription; 82 this.subscription = this.ctx.defaultSubscription;
80 this.datasources = this.subscription.datasources as Array<EntityNodeDatasource>; 83 this.datasources = this.subscription.datasources as Array<EntityNodeDatasource>;
  84 + this.settings = this.ctx.settings;
  85 + this.initializeConfig();
81 this.ctx.updateWidgetParams(); 86 this.ctx.updateWidgetParams();
82 } 87 }
83 88
@@ -86,11 +91,11 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni @@ -86,11 +91,11 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni
86 if (node.id === '#' && datasource) { 91 if (node.id === '#' && datasource) {
87 if (datasource.type === DatasourceType.entity && datasource.entity.id.entityType === EntityType.EDGE) { 92 if (datasource.type === DatasourceType.entity && datasource.entity.id.entityType === EntityType.EDGE) {
88 var selectedEdge: BaseData<EntityId> = datasource.entity; 93 var selectedEdge: BaseData<EntityId> = datasource.entity;
  94 + this.updateTitle(selectedEdge);
89 this.getCustomerTitle(selectedEdge.id.id); 95 this.getCustomerTitle(selectedEdge.id.id);
90 - this.ctx.widgetTitle = `${selectedEdge.name} Quick Overview`;  
91 - cb(this.loadNodesForEdge(selectedEdge.id.id, selectedEdge)); 96 + cb(this.loadNodesForEdge(selectedEdge));
92 } else if (datasource.type === DatasourceType.function) { 97 } else if (datasource.type === DatasourceType.function) {
93 - cb(this.loadNodesForEdge(datasource.entityId, datasource.entity)); 98 + cb(this.loadNodesForEdge(datasource.entity));
94 } else { 99 } else {
95 this.edgeIsDatasource = false; 100 this.edgeIsDatasource = false;
96 cb([]); 101 cb([]);
@@ -103,21 +108,19 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni @@ -103,21 +108,19 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni
103 this.entityService.getAssignedToEdgeEntitiesByType(edgeId, entityType, pageLink).subscribe( 108 this.entityService.getAssignedToEdgeEntitiesByType(edgeId, entityType, pageLink).subscribe(
104 (entities) => { 109 (entities) => {
105 if (entities.data.length > 0) { 110 if (entities.data.length > 0) {
106 - cb(this.entitiesToNodes(node.id, entities.data)); 111 + cb(this.entitiesToNodes(entities.data));
107 } else { 112 } else {
108 cb([]); 113 cb([]);
109 } 114 }
110 } 115 }
111 - ) 116 + );
112 } else { 117 } else {
113 cb([]); 118 cb([]);
114 } 119 }
115 } 120 }
116 121
117 - private loadNodesForEdge(parentNodeId: string, entity: BaseData<HasId>): EdgeOverviewNode[] { 122 + private loadNodesForEdge(entity: BaseData<HasId>): EdgeOverviewNode[] {
118 const nodes: EdgeOverviewNode[] = []; 123 const nodes: EdgeOverviewNode[] = [];
119 - const nodesMap = {};  
120 - this.entityGroupsNodesMap[parentNodeId] = nodesMap;  
121 const authUser = getCurrentAuthUser(this.store); 124 const authUser = getCurrentAuthUser(this.store);
122 var allowedGroupTypes: EntityType[] = edgeGroupsTypes; 125 var allowedGroupTypes: EntityType[] = edgeGroupsTypes;
123 if (authUser.authority === Authority.CUSTOMER_USER) { 126 if (authUser.authority === Authority.CUSTOMER_USER) {
@@ -136,18 +139,12 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni @@ -136,18 +139,12 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni
136 } as EdgeGroupNodeData 139 } as EdgeGroupNodeData
137 }; 140 };
138 nodes.push(node); 141 nodes.push(node);
139 - nodesMap[entityType] = node.id;  
140 }); 142 });
141 return nodes; 143 return nodes;
142 } 144 }
143 145
144 - private createEntityNode(parentNodeId: string, entity: BaseData<HasId>): EdgeOverviewNode {  
145 - let nodesMap = this.entityNodesMap[parentNodeId];  
146 - if (!nodesMap) {  
147 - nodesMap = {};  
148 - this.entityNodesMap[parentNodeId] = nodesMap;  
149 - }  
150 - const node: EdgeOverviewNode = { 146 + private createEntityNode(entity: BaseData<HasId>): EdgeOverviewNode {
  147 + return {
151 id: (++this.nodeIdCounter)+'', 148 id: (++this.nodeIdCounter)+'',
152 icon: false, 149 icon: false,
153 text: entityNodeText(entity), 150 text: entityNodeText(entity),
@@ -159,17 +156,14 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni @@ -159,17 +156,14 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni
159 entity: entity, 156 entity: entity,
160 internalId: entity.id.id 157 internalId: entity.id.id
161 } as EntityNodeData 158 } as EntityNodeData
162 - };  
163 - nodesMap[entity.id.id] = node.id;  
164 - return node; 159 + } as EdgeOverviewNode;
165 } 160 }
166 161
167 - private entitiesToNodes(parentNodeId: string, entities: BaseData<HasId>[]): EdgeOverviewNode[] { 162 + private entitiesToNodes(entities: BaseData<HasId>[]): EdgeOverviewNode[] {
168 const nodes: EdgeOverviewNode[] = []; 163 const nodes: EdgeOverviewNode[] = [];
169 - this.entityNodesMap[parentNodeId] = {};  
170 if (entities) { 164 if (entities) {
171 entities.forEach((entity) => { 165 entities.forEach((entity) => {
172 - const node = this.createEntityNode(parentNodeId, entity); 166 + const node = this.createEntityNode(entity);
173 nodes.push(node); 167 nodes.push(node);
174 }); 168 });
175 } 169 }
@@ -187,4 +181,17 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni @@ -187,4 +181,17 @@ export class EdgesOverviewWidgetComponent extends PageComponent implements OnIni
187 this.cd.detectChanges(); 181 this.cd.detectChanges();
188 }); 182 });
189 } 183 }
  184 +
  185 + private initializeConfig(): void {
  186 + const edgeIsDatasource: boolean = this.datasources[0] && this.datasources[0].type === DatasourceType.entity && this.datasources[0].entity.id.entityType === EntityType.EDGE;
  187 + if (edgeIsDatasource) {
  188 + const edge = this.datasources[0].entity;
  189 + this.updateTitle(edge);
  190 + }
  191 + }
  192 +
  193 + private updateTitle(edge: BaseData<EntityId>): void {
  194 + const displayDefaultTitle: boolean = isDefined(this.settings.enableDefaultTitle) ? this.settings.enableDefaultTitle : false;
  195 + this.ctx.widgetTitle = displayDefaultTitle ? `${edge.name} Quick Overview` : this.widgetConfig.title;
  196 + }
190 } 197 }
@@ -34,7 +34,7 @@ import { @@ -34,7 +34,7 @@ import {
34 importRuleChainBreadcumbLabelFunction, 34 importRuleChainBreadcumbLabelFunction,
35 ResolvedRuleChainMetaDataResolver, 35 ResolvedRuleChainMetaDataResolver,
36 ruleChainBreadcumbLabelFunction, RuleChainImportGuard, 36 ruleChainBreadcumbLabelFunction, RuleChainImportGuard,
37 - RuleChainResolver, RuleNodeComponentsResolver 37 + RuleChainResolver, RuleNodeComponentsResolver, TooltipsterResolver
38 } from '@home/pages/rulechain/rulechain-routing.module'; 38 } from '@home/pages/rulechain/rulechain-routing.module';
39 39
40 const routes: Routes = [ 40 const routes: Routes = [
@@ -194,7 +194,8 @@ const routes: Routes = [ @@ -194,7 +194,8 @@ const routes: Routes = [
194 resolve: { 194 resolve: {
195 ruleChain: RuleChainResolver, 195 ruleChain: RuleChainResolver,
196 ruleChainMetaData: ResolvedRuleChainMetaDataResolver, 196 ruleChainMetaData: ResolvedRuleChainMetaDataResolver,
197 - ruleNodeComponents: RuleNodeComponentsResolver 197 + ruleNodeComponents: RuleNodeComponentsResolver,
  198 + tooltipster: TooltipsterResolver
198 } 199 }
199 }, 200 },
200 { 201 {
@@ -213,7 +214,8 @@ const routes: Routes = [ @@ -213,7 +214,8 @@ const routes: Routes = [
213 ruleChainType: RuleChainType.EDGE 214 ruleChainType: RuleChainType.EDGE
214 }, 215 },
215 resolve: { 216 resolve: {
216 - ruleNodeComponents: RuleNodeComponentsResolver 217 + ruleNodeComponents: RuleNodeComponentsResolver,
  218 + tooltipster: TooltipsterResolver
217 } 219 }
218 } 220 }
219 ] 221 ]
@@ -43,7 +43,7 @@ @@ -43,7 +43,7 @@
43 </mat-tab> 43 </mat-tab>
44 <mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" 44 <mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
45 label="{{ 'edge.downlinks' | translate }}" #downLinksTab="matTab"> 45 label="{{ 'edge.downlinks' | translate }}" #downLinksTab="matTab">
46 - <tb-edge-downlink-table [active]="downLinksTab.isActive" [tenantId]="entity.tenantId.id" 46 + <tb-edge-downlink-table [active]="downLinksTab.isActive"
47 [entityId]="entity.id"></tb-edge-downlink-table> 47 [entityId]="entity.id"></tb-edge-downlink-table>
48 </mat-tab> 48 </mat-tab>
49 <mat-tab *ngIf="entity" 49 <mat-tab *ngIf="entity"
@@ -83,7 +83,7 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> { @@ -83,7 +83,7 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> {
83 ) 83 )
84 } 84 }
85 ); 85 );
86 - this.checkIsNewEdge(entity, form); 86 + this.generateRoutingKeyAndSecret(entity, form);
87 return form; 87 return form;
88 } 88 }
89 89
@@ -100,7 +100,7 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> { @@ -100,7 +100,7 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> {
100 description: entity.additionalInfo ? entity.additionalInfo.description : '' 100 description: entity.additionalInfo ? entity.additionalInfo.description : ''
101 } 101 }
102 }); 102 });
103 - this.checkIsNewEdge(entity, this.entityForm); 103 + this.generateRoutingKeyAndSecret(entity, this.entityForm);
104 } 104 }
105 105
106 updateFormState() { 106 updateFormState() {
@@ -109,13 +109,6 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> { @@ -109,13 +109,6 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> {
109 this.entityForm.get('secret').disable({emitEvent: false}); 109 this.entityForm.get('secret').disable({emitEvent: false});
110 } 110 }
111 111
112 - private checkIsNewEdge(entity: EdgeInfo, form: FormGroup) {  
113 - if (entity && !entity.id) {  
114 - form.get('routingKey').patchValue(guid(), {emitEvent: false});  
115 - form.get('secret').patchValue(generateSecret(20), {emitEvent: false});  
116 - }  
117 - }  
118 -  
119 onEdgeIdCopied($event) { 112 onEdgeIdCopied($event) {
120 this.store.dispatch(new ActionNotificationShow( 113 this.store.dispatch(new ActionNotificationShow(
121 { 114 {
@@ -139,4 +132,11 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> { @@ -139,4 +132,11 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> {
139 horizontalPosition: 'right' 132 horizontalPosition: 'right'
140 })); 133 }));
141 } 134 }
  135 +
  136 + private generateRoutingKeyAndSecret(entity: EdgeInfo, form: FormGroup) {
  137 + if (entity && !entity.id) {
  138 + form.get('routingKey').patchValue(guid(), {emitEvent: false});
  139 + form.get('secret').patchValue(generateSecret(20), {emitEvent: false});
  140 + }
  141 + }
142 } 142 }
@@ -59,6 +59,7 @@ export enum EdgeEventType { @@ -59,6 +59,7 @@ export enum EdgeEventType {
59 USER = "USER", 59 USER = "USER",
60 CUSTOMER = "CUSTOMER", 60 CUSTOMER = "CUSTOMER",
61 RELATION = "RELATION", 61 RELATION = "RELATION",
  62 + TENANT = "TENANT",
62 WIDGETS_BUNDLE = "WIDGETS_BUNDLE", 63 WIDGETS_BUNDLE = "WIDGETS_BUNDLE",
63 WIDGET_TYPE = "WIDGET_TYPE", 64 WIDGET_TYPE = "WIDGET_TYPE",
64 ADMIN_SETTINGS = "ADMIN_SETTINGS" 65 ADMIN_SETTINGS = "ADMIN_SETTINGS"
@@ -105,6 +106,7 @@ export const edgeEventTypeTranslations = new Map<EdgeEventType, string>( @@ -105,6 +106,7 @@ export const edgeEventTypeTranslations = new Map<EdgeEventType, string>(
105 [EdgeEventType.USER, 'edge-event.type-user'], 106 [EdgeEventType.USER, 'edge-event.type-user'],
106 [EdgeEventType.CUSTOMER, 'edge-event.type-customer'], 107 [EdgeEventType.CUSTOMER, 'edge-event.type-customer'],
107 [EdgeEventType.RELATION, 'edge-event.type-relation'], 108 [EdgeEventType.RELATION, 'edge-event.type-relation'],
  109 + [EdgeEventType.TENANT, 'edge-event.type-tenant'],
108 [EdgeEventType.WIDGETS_BUNDLE, 'edge-event.type-widgets-bundle'], 110 [EdgeEventType.WIDGETS_BUNDLE, 'edge-event.type-widgets-bundle'],
109 [EdgeEventType.WIDGET_TYPE, 'edge-event.type-widgets-type'], 111 [EdgeEventType.WIDGET_TYPE, 'edge-event.type-widgets-type'],
110 [EdgeEventType.ADMIN_SETTINGS, 'edge-event.type-admin-settings'] 112 [EdgeEventType.ADMIN_SETTINGS, 'edge-event.type-admin-settings']