diff --git a/application/src/main/data/json/system/widget_bundles/cards.json b/application/src/main/data/json/system/widget_bundles/cards.json index cc49167184..0d97afd5e7 100644 --- a/application/src/main/data/json/system/widget_bundles/cards.json +++ b/application/src/main/data/json/system/widget_bundles/cards.json @@ -132,22 +132,6 @@ "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {},\n \"required\": []\n },\n \"form\": []\n}", "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"nodeRelationQueryFunction\":\"/**\\n\\n// Function should return relations query object for current node used to fetch entity children.\\n// Function can return 'default' string value. In this case default relations query will be used.\\n\\n// The following example code will construct simple relations query that will fetch relations of type 'Contains'\\n// from the current entity.\\n\\nvar entity = nodeCtx.entity;\\nvar query = {\\n parameters: {\\n rootId: entity.id.id,\\n rootType: entity.id.entityType,\\n direction: \\\"FROM\\\",\\n maxLevel: 1\\n },\\n filters: [{\\n relationType: \\\"Contains\\\",\\n entityTypes: []\\n }]\\n};\\nreturn query;\\n\\n**/\\n\",\"nodeHasChildrenFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node has children (whether it can be expanded).\\n\\n// The following example code will restrict entities hierarchy expansion up to third level.\\n\\nreturn nodeCtx.level <= 2;\\n\\n// The next example code will restrict entities expansion according to the value of example 'nodeHasChildren' attribute.\\n\\nvar data = nodeCtx.data;\\nif (data.hasOwnProperty('nodeHasChildren') && data['nodeHasChildren'] !== null) {\\n return data['nodeHasChildren'] === 'true';\\n} else {\\n return true;\\n}\\n \\n**/\\n \",\"nodeTextFunction\":\"/**\\n\\n// Function should return text (can be HTML code) for the current node.\\n\\n// The following example code will generate node text consisting of entity name and temperature if temperature value is present in entity attributes/timeseries.\\n\\nvar data = nodeCtx.data;\\nvar entity = nodeCtx.entity;\\nvar text = entity.name;\\nif (data.hasOwnProperty('temperature') && data['temperature'] !== null) {\\n text += \\\" \\\"+ data['temperature'] +\\\" °C\\\";\\n}\\nreturn text;\\n\\n**/\",\"nodeIconFunction\":\"/** \\n\\n// Function should return node icon info object.\\n// Resulting object should contain either 'materialIcon' or 'iconUrl' property. \\n// Where:\\n - 'materialIcon' - name of the material icon to be used from the Material Icons Library (https://material.io/tools/icons);\\n - 'iconUrl' - url of the external image to be used as node icon.\\n// Function can return 'default' string value. In this case default icons according to entity type will be used.\\n\\n// The following example code shows how to use external image for devices which name starts with 'Test' and use \\n// default icons for the rest of entities.\\n\\nvar entity = nodeCtx.entity;\\nif (entity.id.entityType === 'DEVICE' && entity.name.startsWith('Test')) {\\n return {iconUrl: 'https://avatars1.githubusercontent.com/u/14793288?v=4&s=117'};\\n} else {\\n return 'default';\\n}\\n \\n**/\",\"nodeDisabledFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node should be disabled (not selectable).\\n\\n// The following example code will disable current node according to the value of example 'nodeDisabled' attribute.\\n\\nvar data = nodeCtx.data;\\nif (data.hasOwnProperty('nodeDisabled') && data['nodeDisabled'] !== null) {\\n return data['nodeDisabled'] === 'true';\\n} else {\\n return false;\\n}\\n \\n**/\\n\",\"nodesSortFunction\":\"/**\\n\\n// This function is used to sort nodes of the same level. Function should compare two nodes and return \\n// integer value: \\n// - less than 0 - sort nodeCtx1 to an index lower than nodeCtx2\\n// - 0 - leave nodeCtx1 and nodeCtx2 unchanged with respect to each other\\n// - greater than 0 - sort nodeCtx2 to an index lower than nodeCtx1\\n\\n// The following example code will sort entities first by entity type in alphabetical order then\\n// by entity name in alphabetical order.\\n\\nvar result = nodeCtx1.entity.id.entityType.localeCompare(nodeCtx2.entity.id.entityType);\\nif (result === 0) {\\n result = nodeCtx1.entity.name.localeCompare(nodeCtx2.entity.name);\\n}\\nreturn result;\\n \\n**/\",\"nodeOpenedFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node should be opened (expanded) when it first loaded.\\n\\n// The following example code will open by default nodes up to third level.\\n\\nreturn nodeCtx.level <= 2;\\n\\n**/\\n \"},\"title\":\"Entities hierarchy\",\"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));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6401141393938932,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"widgetStyle\":{},\"actions\":{}}" } - }, - { - "alias": "edge_instances_overview", - "name": "Edge Instances Overview", - "descriptor": { - "type": "latest", - "sizeX": 7.5, - "sizeY": 3.5, - "resources": [], - "templateHtml": "\n", - "templateCss": "", - "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.edgeInstancesOverviewWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n dataKeysOptional: true\n };\n}\n\nself.actionSources = function() {\n return {\n 'nodeSelected': {\n name: 'widget-action.node-selected',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", - "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EdgeInstancesOverviewSettings\",\n \"properties\": {\n \"nodeRelationQueryFunction\": {\n \"title\": \"Node relations query function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeHasChildrenFunction\": {\n \"title\": \"Node has children function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeOpenedFunction\": {\n \"title\": \"Default node opened function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeDisabledFunction\": {\n \"title\": \"Node disabled function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeIconFunction\": {\n \"title\": \"Node icon function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeTextFunction\": {\n \"title\": \"Node text function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodesSortFunction\": {\n \"title\": \"Nodes sort function: f(nodeCtx1, nodeCtx2)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"nodeRelationQueryFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeHasChildrenFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeOpenedFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeDisabledFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeIconFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeTextFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodesSortFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", - "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {},\n \"required\": []\n },\n \"form\": []\n}", - "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"nodeRelationQueryFunction\":\"/**\\n\\n// Function should return relations query object for current node used to fetch entity children.\\n// Function can return 'default' string value. In this case default relations query will be used.\\n\\n// The following example code will construct simple relations query that will fetch relations of type 'Contains'\\n// from the current entity.\\n\\nvar entity = nodeCtx.entity;\\nvar query = {\\n parameters: {\\n rootId: entity.id.id,\\n rootType: entity.id.entityType,\\n direction: \\\"FROM\\\",\\n maxLevel: 1\\n },\\n filters: [{\\n relationType: \\\"Contains\\\",\\n entityTypes: []\\n }]\\n};\\nreturn query;\\n\\n**/\\n\",\"nodeHasChildrenFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node has children (whether it can be expanded).\\n\\n// The following example code will restrict entities hierarchy expansion up to third level.\\n\\nreturn nodeCtx.level <= 2;\\n\\n// The next example code will restrict entities expansion according to the value of example 'nodeHasChildren' attribute.\\n\\nvar data = nodeCtx.data;\\nif (data.hasOwnProperty('nodeHasChildren') && data['nodeHasChildren'] !== null) {\\n return data['nodeHasChildren'] === 'true';\\n} else {\\n return true;\\n}\\n \\n**/\\n \",\"nodeTextFunction\":\"/**\\n\\n// Function should return text (can be HTML code) for the current node.\\n\\n// The following example code will generate node text consisting of entity name and temperature if temperature value is present in entity attributes/timeseries.\\n\\nvar data = nodeCtx.data;\\nvar entity = nodeCtx.entity;\\nvar text = entity.name;\\nif (data.hasOwnProperty('temperature') && data['temperature'] !== null) {\\n text += \\\" \\\"+ data['temperature'] +\\\" °C\\\";\\n}\\nreturn text;\\n\\n**/\",\"nodeIconFunction\":\"/** \\n\\n// Function should return node icon info object.\\n// Resulting object should contain either 'materialIcon' or 'iconUrl' property. \\n// Where:\\n - 'materialIcon' - name of the material icon to be used from the Material Icons Library (https://material.io/tools/icons);\\n - 'iconUrl' - url of the external image to be used as node icon.\\n// Function can return 'default' string value. In this case default icons according to entity type will be used.\\n\\n// The following example code shows how to use external image for devices which name starts with 'Test' and use \\n// default icons for the rest of entities.\\n\\nvar entity = nodeCtx.entity;\\nif (entity.id.entityType === 'DEVICE' && entity.name.startsWith('Test')) {\\n return {iconUrl: 'https://avatars1.githubusercontent.com/u/14793288?v=4&s=117'};\\n} else {\\n return 'default';\\n}\\n \\n**/\",\"nodeDisabledFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node should be disabled (not selectable).\\n\\n// The following example code will disable current node according to the value of example 'nodeDisabled' attribute.\\n\\nvar data = nodeCtx.data;\\nif (data.hasOwnProperty('nodeDisabled') && data['nodeDisabled'] !== null) {\\n return data['nodeDisabled'] === 'true';\\n} else {\\n return false;\\n}\\n \\n**/\\n\",\"nodesSortFunction\":\"/**\\n\\n// This function is used to sort nodes of the same level. Function should compare two nodes and return \\n// integer value: \\n// - less than 0 - sort nodeCtx1 to an index lower than nodeCtx2\\n// - 0 - leave nodeCtx1 and nodeCtx2 unchanged with respect to each other\\n// - greater than 0 - sort nodeCtx2 to an index lower than nodeCtx1\\n\\n// The following example code will sort entities first by entity type in alphabetical order then\\n// by entity name in alphabetical order.\\n\\nvar result = nodeCtx1.entity.id.entityType.localeCompare(nodeCtx2.entity.id.entityType);\\nif (result === 0) {\\n result = nodeCtx1.entity.name.localeCompare(nodeCtx2.entity.name);\\n}\\nreturn result;\\n \\n**/\",\"nodeOpenedFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node should be opened (expanded) when it first loaded.\\n\\n// The following example code will open by default nodes up to third level.\\n\\nreturn nodeCtx.level <= 2;\\n\\n**/\\n \"},\"title\":\"Edge Instances 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));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6401141393938932,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"widgetStyle\":{},\"actions\":{}}" - } } ] } \ No newline at end of file diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java index fe1b06399c..70acadd3e8 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java @@ -439,6 +439,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { this.deleteSystemWidgetBundle("input_widgets"); this.deleteSystemWidgetBundle("date"); this.deleteSystemWidgetBundle("entity_admin_widgets"); + this.deleteSystemWidgetBundle("edge_widgets"); installScripts.loadSystemWidgets(); } diff --git a/ui-ngx/src/app/core/http/widget.service.ts b/ui-ngx/src/app/core/http/widget.service.ts index 345cc6a7f2..4bf35ca011 100644 --- a/ui-ngx/src/app/core/http/widget.service.ts +++ b/ui-ngx/src/app/core/http/widget.service.ts @@ -126,7 +126,7 @@ export class WidgetService { return this.getBundleWidgetTypes(bundleAlias, isSystem, config).pipe( map((types) => { if (!getCurrentAuthState(this.store).edgesSupportEnabled) { - types = types.filter(type => type.alias !== 'edges_hierarchy') + types = types.filter(type => type.alias !== 'edges_overview') } types = types.sort((a, b) => { let result = widgetType[b.descriptor.type].localeCompare(widgetType[a.descriptor.type]); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.component.html deleted file mode 100644 index 59cabe5b7b..0000000000 --- a/ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.component.html +++ /dev/null @@ -1,51 +0,0 @@ - -
-
- -
- - -   - - - -
-
-
- -
-
-
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.component.ts deleted file mode 100644 index 2214ba301a..0000000000 --- a/ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.component.ts +++ /dev/null @@ -1,554 +0,0 @@ -/// -/// Copyright © 2016-2020 The Thingsboard Authors -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// - -import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild, ViewContainerRef } from '@angular/core'; -import { PageComponent } from '@shared/components/page.component'; -import { Store } from '@ngrx/store'; -import { AppState } from '@core/core.state'; -import { WidgetAction, WidgetContext } from '@home/models/widget-component.models'; -import { DatasourceData, DatasourceType, WidgetConfig, widgetType } from '@shared/models/widget.models'; -import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models'; -import { UtilsService } from '@core/services/utils.service'; -import cssjs from '@core/css/css'; -import { fromEvent } from 'rxjs'; -import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators'; -import { constructTableCssString } from '@home/components/widget/lib/table-widget.models'; -import { Overlay } from '@angular/cdk/overlay'; -import { - LoadNodesCallback, - NavTreeEditCallbacks, NodesCallback, - NodeSearchCallback, - NodeSelectedCallback, - NodesInsertedCallback -} from '@shared/components/nav-tree.component'; -import { EntityType } from '@shared/models/entity-type.models'; -import { deepClone, hashCode } from '@core/utils'; -import { - defaultNodeIconFunction, - defaultNodeOpenedFunction, - defaultNodeRelationQueryFunction, - defaultNodesSortFunction, - EdgeGroupsNodeData, - edgeGroupsNodeText, - edgeGroupsTypes, - EdgeNodeData, - edgeNodeText, - EdgeInstancesOverviewNode, - EdgeInstancesOverviewWidgetSettings, - HierarchyNavTreeNode, - HierarchyNodeContext, - HierarchyNodeDatasource, - iconUrlHtml, - loadNodeCtxFunction, - materialIconHtml, - NodeDisabledFunction, - NodeHasChildrenFunction, - NodeIconFunction, - NodeOpenedFunction, - NodeRelationQueryFunction, - NodesSortFunction, - NodeTextFunction -} from '@home/components/widget/lib/edge-instances-overview-widget.models'; -import { EdgeService } from "@core/http/edge.service"; -import { PageLink } from "@shared/models/page/page-link"; -import { Edge, EdgeInfo } from "@shared/models/edge.models"; -import { TranslateService } from "@ngx-translate/core"; -import { EntityService } from "@core/http/entity.service"; -import { Direction, SortOrder } from "@shared/models/page/sort-order"; -import { EntityRelationsQuery } from "@shared/models/relation.models"; -import { EntityFilter } from "@shared/models/query/query.models"; -import { AliasFilterType, RelationsQueryFilter } from "@shared/models/alias.models"; - -@Component({ - selector: 'tb-edge-instances-overview-widget', - templateUrl: './edge-instances-overview-widget.component.html', - styleUrls: ['./edge-instances-overview-widget.component.scss'] -}) -export class EdgeInstancesOverviewWidgetComponent extends PageComponent implements OnInit, AfterViewInit { - - @Input() - ctx: WidgetContext; - - @ViewChild('searchInput') searchInputField: ElementRef; - - public toastTargetId = 'edge-instances-overview-' + this.utils.guid(); - - public textSearchMode = false; - public textSearch = null; - - public nodeEditCallbacks: NavTreeEditCallbacks = {}; - - private settings: EdgeInstancesOverviewWidgetSettings; - private widgetConfig: WidgetConfig; - private subscription: IWidgetSubscription; - private datasources: Array; - private data: Array>; - - private nodesMap: {[nodeId: string]: HierarchyNavTreeNode} = {}; - private pendingUpdateNodeTasks: {[nodeId: string]: () => void} = {}; - private nodeIdCounter = 0; - - private nodeRelationQueryFunction: NodeRelationQueryFunction; - private nodeIconFunction: NodeIconFunction; - private nodeTextFunction: NodeTextFunction; - private nodeDisabledFunction: NodeDisabledFunction; - private nodeOpenedFunction: NodeOpenedFunction; - private nodeHasChildrenFunction: NodeHasChildrenFunction; - private nodesSortFunction: NodesSortFunction; - - private edgeNodesMap: {[parentNodeId: string]: {[edgeId: string]: string}} = {}; - private edgeGroupsNodesMap: {[edgeNodeId: string]: {[groupType: string]: string}} = {}; - - - private searchAction: WidgetAction = { - name: 'action.search', - show: false, - icon: 'search', - onAction: () => { - this.enterFilterMode(); - } - }; - - constructor(protected store: Store, - private elementRef: ElementRef, - private edgeService: EdgeService, - private entityService: EntityService, - private translateService: TranslateService, - private overlay: Overlay, - private viewContainerRef: ViewContainerRef, - private utils: UtilsService) { - super(store); - } - - ngOnInit(): void { - this.ctx.$scope.edgeInstancesOverviewWidget = this; - this.settings = this.ctx.settings; - this.widgetConfig = this.ctx.widgetConfig; - this.subscription = this.ctx.defaultSubscription; - this.datasources = this.subscription.datasources as Array; - this.data = this.subscription.dataPages[0].data; - this.initializeConfig(); - this.ctx.updateWidgetParams(); - } - - ngAfterViewInit(): void { - fromEvent(this.searchInputField.nativeElement, 'keyup') - .pipe( - debounceTime(150), - distinctUntilChanged(), - tap(() => { - this.updateSearchNodes(); - }) - ) - .subscribe(); - } - - public onDataUpdated() { - this.updateNodeData(this.subscription.data); - } - - private initializeConfig() { - this.ctx.widgetActions = [this.searchAction]; - - const testNodeCtx: HierarchyNodeContext = { - entity: { - id: { - entityType: EntityType.DEVICE, - id: '123' - }, - name: 'TEST DEV1' - }, - data: {}, - level: 2 - }; - const parentNodeCtx = deepClone(testNodeCtx); - parentNodeCtx.level = 1; - testNodeCtx.parentNodeCtx = parentNodeCtx; - - this.nodeRelationQueryFunction = loadNodeCtxFunction(this.settings.nodeRelationQueryFunction, 'nodeCtx', testNodeCtx); - this.nodeIconFunction = loadNodeCtxFunction(this.settings.nodeIconFunction, 'nodeCtx', testNodeCtx); - this.nodeTextFunction = loadNodeCtxFunction(this.settings.nodeTextFunction, 'nodeCtx', testNodeCtx); - this.nodeDisabledFunction = loadNodeCtxFunction(this.settings.nodeDisabledFunction, 'nodeCtx', testNodeCtx); - this.nodeOpenedFunction = loadNodeCtxFunction(this.settings.nodeOpenedFunction, 'nodeCtx', testNodeCtx); - this.nodeHasChildrenFunction = loadNodeCtxFunction(this.settings.nodeHasChildrenFunction, 'nodeCtx', testNodeCtx); - - const testNodeCtx2 = deepClone(testNodeCtx); - testNodeCtx2.entity.name = 'TEST DEV2'; - - this.nodesSortFunction = loadNodeCtxFunction(this.settings.nodesSortFunction, 'nodeCtx1,nodeCtx2', testNodeCtx, testNodeCtx2); - - this.nodeRelationQueryFunction = this.nodeRelationQueryFunction || defaultNodeRelationQueryFunction; - this.nodeIconFunction = this.nodeIconFunction || defaultNodeIconFunction; - this.nodeTextFunction = this.nodeTextFunction || ((nodeCtx) => nodeCtx.entity.name); - this.nodeDisabledFunction = this.nodeDisabledFunction || (() => false); - this.nodeOpenedFunction = this.nodeOpenedFunction || defaultNodeOpenedFunction; - this.nodeHasChildrenFunction = this.nodeHasChildrenFunction || (() => true); - this.nodesSortFunction = this.nodesSortFunction || defaultNodesSortFunction; - - const cssString = constructTableCssString(this.widgetConfig); - const cssParser = new cssjs(); - cssParser.testMode = false; - const namespace = 'edges-instances-overview-' + hashCode(cssString); - cssParser.cssPreviewNamespace = namespace; - cssParser.createStyleElement(namespace, cssString); - $(this.elementRef.nativeElement).addClass(namespace); - } - - private enterFilterMode() { - this.textSearchMode = true; - this.textSearch = ''; - this.ctx.hideTitlePanel = true; - this.ctx.detectChanges(true); - setTimeout(() => { - this.searchInputField.nativeElement.focus(); - this.searchInputField.nativeElement.setSelectionRange(0, 0); - }, 10); - } - - exitFilterMode() { - this.textSearchMode = false; - this.textSearch = null; - this.updateSearchNodes(); - this.ctx.hideTitlePanel = false; - this.ctx.detectChanges(true); - } - - private updateSearchNodes() { - if (this.textSearch != null) { - this.nodeEditCallbacks.search(this.textSearch); - } else { - this.nodeEditCallbacks.clearSearch(); - } - } - - private updateNodeData(subscriptionData: Array) { - const affectedNodes: string[] = []; - if (subscriptionData) { - subscriptionData.forEach((datasourceData) => { - const datasource = datasourceData.datasource as HierarchyNodeDatasource; - if (datasource.nodeId) { - const node = this.nodesMap[datasource.nodeId]; - const key = datasourceData.dataKey.label; - let value; - if (datasourceData.data && datasourceData.data.length) { - value = datasourceData.data[0][1]; - } - if (node.data.nodeCtx.data[key] !== value) { - if (affectedNodes.indexOf(datasource.nodeId) === -1) { - affectedNodes.push(datasource.nodeId); - } - node.data.nodeCtx.data[key] = value; - } - } - }); - } - affectedNodes.forEach((nodeId) => { - const node: HierarchyNavTreeNode = this.nodeEditCallbacks.getNode(nodeId); - if (node) { - this.updateNodeStyle(this.nodesMap[nodeId]); - } else { - this.pendingUpdateNodeTasks[nodeId] = () => { - this.updateNodeStyle(this.nodesMap[nodeId]); - }; - } - }); - } - - public loadNodes: LoadNodesCallback = (node, cb) => { - if (node.id === '#') { - const sortOrder: SortOrder = { property: 'name', direction: Direction.ASC }; - const pageLink = new PageLink(100, 0, null, sortOrder); - this.edgeService.getTenantEdgeInfos(pageLink).subscribe( - (edges) => { - cb(this.edgesToNodes(node.id, edges.data)) - }); - } else if (node.data.type === 'edge') { - const edge = node.data.entity; - cb(this.loadNodesForEdge(node.id, edge)); - } else if (node.data.type === 'edgeGroups') { - const pageLink = new PageLink(100); - this.entityService.getAssignedToEdgeEntitiesByType(node, pageLink).subscribe( - (entities) => { - if (entities.data.length > 0) { - cb(this.edgesToNodes(node.id, entities.data)); - } else { - cb([]); - } - } - ) - } - } - - private loadNodesForEdge(parentNodeId: string, edge: EdgeInfo): EdgeInstancesOverviewNode[] { - const nodes: EdgeInstancesOverviewNode[] = []; - const nodesMap = {}; - this.edgeGroupsNodesMap[parentNodeId] = nodesMap; - edgeGroupsTypes.forEach((entityType) => { - const node: EdgeInstancesOverviewNode = { - id: (++this.nodeIdCounter)+'', - icon: false, - text: edgeGroupsNodeText(this.translateService, entityType), - children: true, - data: { - type: 'edgeGroups', - entityType, - edge, - internalId: edge.id.id + '_' + entityType - } as EdgeGroupsNodeData - }; - nodes.push(node); - nodesMap[entityType] = node.id; - }); - return nodes; - } - - private createEdgeNode(parentNodeId: string, edge: Edge): EdgeInstancesOverviewNode { - let nodesMap = this.edgeNodesMap[parentNodeId]; - if (!nodesMap) { - nodesMap = {}; - this.edgeNodesMap[parentNodeId] = nodesMap; - } - const node: EdgeInstancesOverviewNode = { - id: (++this.nodeIdCounter)+'', - icon: false, - text: edgeNodeText(edge), - children: parentNodeId === '#', - state: { - disabled: false - }, - data: { - type: 'edge', - entity: edge, - internalId: edge.id.id - } as EdgeNodeData - }; - nodesMap[edge.id.id] = node.id; - return node; - } - - private edgesToNodes(parentNodeId: string, edges: Array): EdgeInstancesOverviewNode[] { - const nodes: EdgeInstancesOverviewNode[] = []; - this.edgeNodesMap[parentNodeId] = {}; - if (edges) { - edges.forEach((edge) => { - const node = this.createEdgeNode(parentNodeId, edge); - nodes.push(node); - }); - } - return nodes; - } - - public onNodeSelected: NodeSelectedCallback = (node, event) => { - let nodeId; - if (!node) { - nodeId = -1; - } else { - nodeId = node.id; - } - if (nodeId !== -1) { - const selectedNode = this.nodesMap[nodeId]; - if (selectedNode) { - const descriptors = this.ctx.actionsApi.getActionDescriptors('nodeSelected'); - if (descriptors.length) { - const entity = selectedNode.data.nodeCtx.entity; - this.ctx.actionsApi.handleWidgetAction(event, descriptors[0], entity.id, entity.name, { nodeCtx: selectedNode.data.nodeCtx }); - } - } - } - } - - public onNodesInserted: NodesInsertedCallback = (nodes) => { - if (nodes) { - nodes.forEach((nodeId) => { - const task = this.pendingUpdateNodeTasks[nodeId]; - if (task) { - task(); - delete this.pendingUpdateNodeTasks[nodeId]; - } - }); - } - } - - public searchCallback: NodeSearchCallback = (searchText, node) => { - const theNode = this.nodesMap[node.id]; - if (theNode && theNode.data.searchText) { - return theNode.data.searchText.includes(searchText.toLowerCase()); - } - return false; - } - - private updateNodeStyle(node: HierarchyNavTreeNode) { - const newText = this.prepareNodeText(node); - if (node.text !== newText) { - node.text = newText; - this.nodeEditCallbacks.updateNode(node.id, node.text); - } - const newDisabled = this.nodeDisabledFunction(node.data.nodeCtx); - if (node.state.disabled !== newDisabled) { - node.state.disabled = newDisabled; - if (node.state.disabled) { - this.nodeEditCallbacks.disableNode(node.id); - } else { - this.nodeEditCallbacks.enableNode(node.id); - } - } - const newHasChildren = this.nodeHasChildrenFunction(node.data.nodeCtx); - if (node.children !== newHasChildren) { - node.children = newHasChildren; - this.nodeEditCallbacks.setNodeHasChildren(node.id, node.children); - } - } - - private prepareNodes(nodes: HierarchyNavTreeNode[]): HierarchyNavTreeNode[] { - nodes = nodes.filter((node) => node !== null); - nodes.sort((node1, node2) => this.nodesSortFunction(node1.data.nodeCtx, node2.data.nodeCtx)); - return nodes; - } - - private prepareNodeText(node: HierarchyNavTreeNode): string { - const nodeIcon = this.prepareNodeIcon(node.data.nodeCtx); - const nodeText = this.nodeTextFunction(node.data.nodeCtx); - node.data.searchText = nodeText ? nodeText.replace(/<[^>]+>/g, '').toLowerCase() : ''; - return nodeIcon + nodeText; - } - - private prepareNodeIcon(nodeCtx: HierarchyNodeContext): string { - let iconInfo = this.nodeIconFunction(nodeCtx); - if (iconInfo) { - if (iconInfo === 'default') { - iconInfo = defaultNodeIconFunction(nodeCtx); - } - if (iconInfo && iconInfo !== 'default' && (iconInfo.iconUrl || iconInfo.materialIcon)) { - if (iconInfo.materialIcon) { - return materialIconHtml(iconInfo.materialIcon); - } else { - return iconUrlHtml(iconInfo.iconUrl); - } - } else { - return ''; - } - } else { - return ''; - } - } - - private datasourceToNode(datasource: HierarchyNodeDatasource, - data: DatasourceData[], - parentNodeCtx?: HierarchyNodeContext): HierarchyNavTreeNode { - const node: HierarchyNavTreeNode = { - id: (++this.nodeIdCounter) + '' - }; - this.nodesMap[node.id] = node; - datasource.nodeId = node.id; - node.icon = false; - const nodeCtx: HierarchyNodeContext = { - parentNodeCtx, - entity: { - id: { - id: datasource.entityId, - entityType: datasource.entityType - }, - name: datasource.entityName, - label: datasource.entityLabel ? datasource.entityLabel : datasource.entityName - }, - data: {} - }; - datasource.dataKeys.forEach((dataKey, index) => { - const keyData = data[index].data; - if (keyData && keyData.length && keyData[0].length > 1) { - nodeCtx.data[dataKey.label] = keyData[0][1]; - } else { - nodeCtx.data[dataKey.label] = ''; - } - }); - nodeCtx.level = parentNodeCtx ? parentNodeCtx.level + 1 : 1; - node.data = { - datasource, - nodeCtx - }; - node.state = { - disabled: this.nodeDisabledFunction(node.data.nodeCtx), - opened: this.nodeOpenedFunction(node.data.nodeCtx) - }; - node.text = this.prepareNodeText(node); - node.children = this.nodeHasChildrenFunction(node.data.nodeCtx); - return node; - } - - private loadChildren(parentNode: HierarchyNavTreeNode, datasource: HierarchyNodeDatasource, childrenNodesLoadCb: NodesCallback) { - const nodeCtx = parentNode.data.nodeCtx; - nodeCtx.childrenNodesLoaded = false; - const entityFilter = this.prepareNodeRelationsQueryFilter(nodeCtx); - const childrenDatasource = { - dataKeys: datasource.dataKeys, - type: DatasourceType.entity, - filterId: datasource.filterId, - entityFilter - } as HierarchyNodeDatasource; - const subscriptionOptions: WidgetSubscriptionOptions = { - type: widgetType.latest, - datasources: [childrenDatasource], - callbacks: { - onSubscriptionMessage: (subscription, message) => { - this.ctx.showToast(message.severity, message.message, undefined, - 'bottom', 'left', this.toastTargetId); - }, - onInitialPageDataChanged: (subscription) => { - this.ctx.subscriptionApi.removeSubscription(subscription.id); - this.nodeEditCallbacks.refreshNode(parentNode.id); - }, - onDataUpdated: subscription => { - if (nodeCtx.childrenNodesLoaded) { - this.updateNodeData(subscription.data); - } else { - const datasourcesPageData = subscription.datasourcePages[0]; - const dataPageData = subscription.dataPages[0]; - const childNodes: HierarchyNavTreeNode[] = []; - datasourcesPageData.data.forEach((childDatasource, index) => { - childNodes.push(this.datasourceToNode(childDatasource as HierarchyNodeDatasource, dataPageData.data[index])); - }); - nodeCtx.childrenNodesLoaded = true; - childrenNodesLoadCb(this.prepareNodes(childNodes)); - } - } - } - }; - this.ctx.subscriptionApi.createSubscription(subscriptionOptions, true); - } - - private prepareNodeRelationQuery(nodeCtx: HierarchyNodeContext): EntityRelationsQuery { - let relationQuery = this.nodeRelationQueryFunction(nodeCtx); - if (relationQuery && relationQuery === 'default') { - relationQuery = defaultNodeRelationQueryFunction(nodeCtx); - } - return relationQuery as EntityRelationsQuery; - } - - private prepareNodeRelationsQueryFilter(nodeCtx: HierarchyNodeContext): EntityFilter { - const relationQuery = this.prepareNodeRelationQuery(nodeCtx); - return { - rootEntity: { - id: relationQuery.parameters.rootId, - entityType: relationQuery.parameters.rootType - }, - direction: relationQuery.parameters.direction, - filters: relationQuery.filters, - maxLevel: relationQuery.parameters.maxLevel, - fetchLastLevelOnly: relationQuery.parameters.fetchLastLevelOnly, - type: AliasFilterType.relationsQuery - } as RelationsQueryFilter; - } -} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.models.ts deleted file mode 100644 index aa389c2bea..0000000000 --- a/ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.models.ts +++ /dev/null @@ -1,260 +0,0 @@ -/// -/// Copyright © 2016-2020 The Thingsboard Authors -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// - -import { BaseData } from '@shared/models/base-data'; -import { EntityId } from '@shared/models/id/entity-id'; -import { NavTreeNode } from '@shared/components/nav-tree.component'; -import { Datasource } from '@shared/models/widget.models'; -import { isDefined, isUndefined } from '@core/utils'; -import { EntityRelationsQuery, EntitySearchDirection, RelationTypeGroup } from '@shared/models/relation.models'; -import { EntityType } from '@shared/models/entity-type.models'; -import { Edge } from "@shared/models/edge.models"; -import { TranslateService } from "@ngx-translate/core"; - -export interface EdgeInstancesOverviewWidgetSettings { - nodeRelationQueryFunction: string; - nodeHasChildrenFunction: string; - nodeOpenedFunction: string; - nodeDisabledFunction: string; - nodeIconFunction: string; - nodeTextFunction: string; - nodesSortFunction: string; -} - -export interface HierarchyNodeContext { - parentNodeCtx?: HierarchyNodeContext; - entity: BaseData; - childrenNodesLoaded?: boolean; - level?: number; - data: {[key: string]: any}; -} - -export interface HierarchyNavTreeNode extends NavTreeNode { - data?: { - datasource: HierarchyNodeDatasource; - nodeCtx: HierarchyNodeContext; - searchText?: string; - }; -} - -export interface HierarchyNodeDatasource extends Datasource { - nodeId: string; -} - -export interface HierarchyNodeIconInfo { - iconUrl?: string; - materialIcon?: string; -} - -export type NodeRelationQueryFunction = (nodeCtx: HierarchyNodeContext) => EntityRelationsQuery | 'default'; -export type NodeTextFunction = (nodeCtx: HierarchyNodeContext) => string; -export type NodeDisabledFunction = (nodeCtx: HierarchyNodeContext) => boolean; -export type NodeIconFunction = (nodeCtx: HierarchyNodeContext) => HierarchyNodeIconInfo | 'default'; -export type NodeOpenedFunction = (nodeCtx: HierarchyNodeContext) => boolean; -export type NodeHasChildrenFunction = (nodeCtx: HierarchyNodeContext) => boolean; -export type NodesSortFunction = (nodeCtx1: HierarchyNodeContext, nodeCtx2: HierarchyNodeContext) => number; - -export function loadNodeCtxFunction any>(functionBody: string, argNames: string, ...args: any[]): F { - let nodeCtxFunction: F = null; - if (isDefined(functionBody) && functionBody.length) { - try { - nodeCtxFunction = new Function(argNames, functionBody) as F; - const res = nodeCtxFunction.apply(null, args); - if (isUndefined(res)) { - nodeCtxFunction = null; - } - } catch (e) { - nodeCtxFunction = null; - } - } - return nodeCtxFunction; -} - -export function materialIconHtml(materialIcon: string): string { - return '' + materialIcon + ''; -} - -export function iconUrlHtml(iconUrl: string): string { - return '
 
'; -} - -export function edgeGroupsNodeText(translate: TranslateService, entityType: EntityType): string { - const nodeIcon = materialIconByEntityType(entityType); - const nodeText = textForEdgeGroupsType(translate, entityType); - return nodeIcon + nodeText; -} - -export function edgeNodeText(edge: Edge): string { - const nodeIcon = materialIconByEntityType(edge.id.entityType); - const nodeText = edge.name; - return nodeIcon + nodeText; -} - -export function materialIconByEntityType(entityType: EntityType): string { - let materialIcon = 'insert_drive_file'; - switch (entityType) { - case EntityType.DEVICE: - materialIcon = 'devices_other'; - break; - case EntityType.ASSET: - materialIcon = 'domain'; - break; - case EntityType.CUSTOMER: - materialIcon = 'supervisor_account'; - break; - case EntityType.USER: - materialIcon = 'account_circle'; - break; - case EntityType.DASHBOARD: - materialIcon = 'dashboards'; - break; - case EntityType.ENTITY_VIEW: - materialIcon = 'view_quilt'; - break; - case EntityType.RULE_CHAIN: - materialIcon = 'settings_ethernet'; - break; - case EntityType.EDGE: - materialIcon = 'router'; - break; - } - return '' + materialIcon + ''; -} - -export function textForEdgeGroupsType(translate: TranslateService, entityType: EntityType): string { - let textForEdgeGroupsType: string = ''; - switch (entityType) { - case EntityType.DEVICE: - textForEdgeGroupsType = 'device.devices'; - break; - case EntityType.ASSET: - textForEdgeGroupsType = 'asset.assets'; - break; - case EntityType.DASHBOARD: - textForEdgeGroupsType = 'dashboard.dashboards'; - break; - case EntityType.ENTITY_VIEW: - textForEdgeGroupsType = 'entity-view.entity-views'; - break; - case EntityType.RULE_CHAIN: - textForEdgeGroupsType = 'rulechain.rulechains'; - break; - } - return translate.instant(textForEdgeGroupsType); -} - -export const defaultNodeRelationQueryFunction: NodeRelationQueryFunction = nodeCtx => { - const entity = nodeCtx.entity; - const query: EntityRelationsQuery = { - parameters: { - rootId: entity.id.id, - rootType: entity.id.entityType as EntityType, - direction: EntitySearchDirection.FROM, - relationTypeGroup: RelationTypeGroup.COMMON, - maxLevel: 1 - }, - filters: [ - { - relationType: 'Contains', - entityTypes: [] - } - ] - }; - return query; -}; - -export const edgeGroupsTypes: EntityType[] = [ - EntityType.ASSET, - EntityType.DEVICE, - EntityType.ENTITY_VIEW, - EntityType.DASHBOARD, - EntityType.RULE_CHAIN -] - -export const defaultNodeIconFunction: NodeIconFunction = nodeCtx => { - let materialIcon = 'insert_drive_file'; - const entity = nodeCtx.entity; - if (entity && entity.id && entity.id.entityType) { - switch (entity.id.entityType as EntityType | string) { - case 'function': - materialIcon = 'functions'; - break; - case EntityType.DEVICE: - materialIcon = 'devices_other'; - break; - case EntityType.ASSET: - materialIcon = 'domain'; - break; - case EntityType.TENANT: - materialIcon = 'supervisor_account'; - break; - case EntityType.CUSTOMER: - materialIcon = 'supervisor_account'; - break; - case EntityType.USER: - materialIcon = 'account_circle'; - break; - case EntityType.DASHBOARD: - materialIcon = 'dashboards'; - break; - case EntityType.ALARM: - materialIcon = 'notifications_active'; - break; - case EntityType.ENTITY_VIEW: - materialIcon = 'view_quilt'; - break; - } - } - return { - materialIcon - }; -}; - -export const defaultNodeOpenedFunction: NodeOpenedFunction = nodeCtx => { - return nodeCtx.level <= 4; -}; - -export const defaultNodesSortFunction: NodesSortFunction = (nodeCtx1, nodeCtx2) => { - let result = nodeCtx1.entity.id.entityType.localeCompare(nodeCtx2.entity.id.entityType); - if (result === 0) { - result = nodeCtx1.entity.name.localeCompare(nodeCtx2.entity.name); - } - return result; -}; - -export interface EdgeInstancesOverviewNode extends NavTreeNode { - data?: EdgeInstancesOverviewNodeData; -} - -export type EdgeInstancesOverviewNodeData = EdgeGroupsNodeData | EdgeNodeData; - -export interface EdgeGroupsNodeData extends BaseEdgeInstancesOverviewNodeData { - type: 'edgeGroups'; - entityType: EntityType; - edge: Edge; -} - -export interface EdgeNodeData extends BaseEdgeInstancesOverviewNodeData { - type: 'edge'; - entity: Edge; -} - -export interface BaseEdgeInstancesOverviewNodeData { - type: EdgeInstancesOverviewNodeType; - internalId: string; -} - -export type EdgeInstancesOverviewNodeType = 'edge' | 'edgeGroups'; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/edges-overview-widget.component.scss similarity index 96% rename from ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.component.scss rename to ui-ngx/src/app/modules/home/components/widget/lib/edges-overview-widget.component.scss index 2ca5824dd0..abd1536e98 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/edge-instances-overview-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/edges-overview-widget.component.scss @@ -14,7 +14,7 @@ * limitations under the License. */ :host-context(.tb-has-timewindow) { - .tb-edge-instances-overview { + .tb-edges-overview { mat-toolbar { height: 60px; max-height: 60px; @@ -27,7 +27,7 @@ } :host { - .tb-edge-instances-overview { + .tb-edges-overview { mat-toolbar.mat-table-toolbar:not([color="primary"]) { background: transparent; } @@ -40,7 +40,7 @@ } } - .tb-edges-nav-tree-panel { + .tb-entities-nav-tree-panel { overflow-x: auto; overflow-y: auto; } diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts index 70f6332417..f2390d099a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts @@ -35,7 +35,7 @@ import { TripAnimationComponent } from './trip-animation/trip-animation.componen import { PhotoCameraInputWidgetComponent } from './lib/photo-camera-input.component'; import { GatewayFormComponent } from './lib/gateway/gateway-form.component'; import { ImportExportService } from '@home/components/import-export/import-export.service'; -import { EdgeInstancesOverviewWidgetComponent } from "@home/components/widget/lib/edge-instances-overview-widget.component"; +import { EdgesOverviewWidgetComponent } from "@home/components/widget/lib/edges-overview-widget.component"; @NgModule({ declarations: @@ -46,7 +46,7 @@ import { EdgeInstancesOverviewWidgetComponent } from "@home/components/widget/li AlarmsTableWidgetComponent, TimeseriesTableWidgetComponent, EntitiesHierarchyWidgetComponent, - EdgeInstancesOverviewWidgetComponent, + EdgesOverviewWidgetComponent, DateRangeNavigatorWidgetComponent, DateRangeNavigatorPanelComponent, MultipleInputWidgetComponent, @@ -65,7 +65,7 @@ import { EdgeInstancesOverviewWidgetComponent } from "@home/components/widget/li AlarmsTableWidgetComponent, TimeseriesTableWidgetComponent, EntitiesHierarchyWidgetComponent, - EdgeInstancesOverviewWidgetComponent, + EdgesOverviewWidgetComponent, RpcWidgetsModule, DateRangeNavigatorWidgetComponent, MultipleInputWidgetComponent, diff --git a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-widget-select.component.ts b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-widget-select.component.ts index 982ac584ed..438bd905df 100644 --- a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-widget-select.component.ts +++ b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-widget-select.component.ts @@ -117,7 +117,7 @@ export class DashboardWidgetSelectComponent implements OnInit, OnChanges { break; } if (!getCurrentAuthState(this.store).edgesSupportEnabled) { - this.latestWidgetTypes = this.latestWidgetTypes.filter(type => type.typeAlias !== 'edges_instances_overview') + this.staticWidgetTypes = this.staticWidgetTypes.filter(type => type.typeAlias !== 'edges_instances_overview') } top += widget.sizeY; });