TB-70: Improve dashboards states management.
This commit is contained in:
		
							parent
							
								
									983ba89a04
								
							
						
					
					
						commit
						81ccdf7bfa
					
				@ -26,12 +26,12 @@
 | 
			
		||||
      "name": "Entities table",
 | 
			
		||||
      "descriptor": {
 | 
			
		||||
        "type": "latest",
 | 
			
		||||
        "sizeX": 10.5,
 | 
			
		||||
        "sizeY": 6.5,
 | 
			
		||||
        "sizeX": 7.5,
 | 
			
		||||
        "sizeY": 4.5,
 | 
			
		||||
        "resources": [],
 | 
			
		||||
        "templateHtml": "<tb-entities-table-widget \n    table-id=\"tableId\"\n    ctx=\"ctx\">\n</tb-entities-table-widget>",
 | 
			
		||||
        "templateCss": "",
 | 
			
		||||
        "controllerScript": "self.onInit = function() {\n    var scope = self.ctx.$scope;\n    var id = self.ctx.$scope.$injector.get('utils').guid();\n    scope.tableId = \"table-\"+id;\n    scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n    self.ctx.$scope.$broadcast('entities-table-data-updated', self.ctx.$scope.tableId);\n}\n\nself.typeParameters = function() {\n    return {\n        maxDatasources: 1  \n    };\n}\n\nself.actionSources = function() {\n    return {\n        'actionCellButton': {\n            name: 'widget-action.action-cell-button',\n            multiple: true\n        },\n        'rowClick': {\n            name: 'widget-action.row-click',\n            multiple: false\n        }\n    };\n}\n\nself.onDestroy = function() {\n}\n",
 | 
			
		||||
        "controllerScript": "self.onInit = function() {\n    var scope = self.ctx.$scope;\n    var id = self.ctx.$scope.$injector.get('utils').guid();\n    scope.tableId = \"table-\"+id;\n    scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n    self.ctx.$scope.$broadcast('entities-table-data-updated', self.ctx.$scope.tableId);\n}\n\nself.typeParameters = function() {\n    return {\n        maxDatasources: 1,\n        dataKeysOptional: true\n    };\n}\n\nself.actionSources = function() {\n    return {\n        'actionCellButton': {\n            name: 'widget-action.action-cell-button',\n            multiple: true\n        },\n        'rowClick': {\n            name: 'widget-action.row-click',\n            multiple: false\n        }\n    };\n}\n\nself.onDestroy = function() {\n}\n",
 | 
			
		||||
        "settingsSchema": "{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"EntitiesTableSettings\",\n        \"properties\": {\n            \"entitiesTitle\": {\n                \"title\": \"Entities table title\",\n                \"type\": \"string\",\n                \"default\": \"\"\n            },\n            \"enableSearch\": {\n                \"title\": \"Enable entities search\",\n                \"type\": \"boolean\",\n                \"default\": true\n            },\n            \"displayEntityName\": {\n                \"title\": \"Display entity name column\",\n                \"type\": \"boolean\",\n                \"default\": true\n            },\n            \"entityNameColumnTitle\": {\n                \"title\": \"Entity name column title\",\n                \"type\": \"string\",\n                \"default\": \"\"\n            },\n            \"displayEntityType\": {\n                \"title\": \"Display entity type column\",\n                \"type\": \"boolean\",\n                \"default\": true\n            },\n            \"displayPagination\": {\n                \"title\": \"Display pagination\",\n                \"type\": \"boolean\",\n                \"default\": true\n            },\n            \"defaultPageSize\": {\n                \"title\": \"Default page size\",\n                \"type\": \"number\",\n                \"default\": 10\n            },\n            \"defaultSortOrder\": {\n                \"title\": \"Default sort order\",\n                \"type\": \"string\",\n                \"default\": \"entityName\"\n            }\n        },\n        \"required\": []\n    },\n    \"form\": [\n        \"entitiesTitle\",\n        \"enableSearch\",\n        \"displayEntityName\",\n        \"entityNameColumnTitle\",\n        \"displayEntityType\",\n        \"displayPagination\",\n        \"defaultPageSize\",\n        \"defaultSortOrder\"\n    ]\n}",
 | 
			
		||||
        "dataKeySettingsSchema": "{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"DataKeySettings\",\n        \"properties\": {\n            \"columnWidth\": {\n                \"title\": \"Column width (px or %)\",\n                \"type\": \"string\",\n                \"default\": \"0px\"\n            },\n            \"useCellStyleFunction\": {\n                \"title\": \"Use cell style function\",\n                \"type\": \"boolean\",\n                \"default\": false\n            },\n            \"cellStyleFunction\": {\n                \"title\": \"Cell style function: f(value)\",\n                \"type\": \"string\",\n                \"default\": \"\"\n            },\n            \"useCellContentFunction\": {\n                \"title\": \"Use cell content function\",\n                \"type\": \"boolean\",\n                \"default\": false\n            },\n            \"cellContentFunction\": {\n                \"title\": \"Cell content function: f(value, entity, filter)\",\n                \"type\": \"string\",\n                \"default\": \"\"\n            }\n        },\n        \"required\": []\n    },\n    \"form\": [\n        \"columnWidth\",\n        \"useCellStyleFunction\",\n        {\n            \"key\": \"cellStyleFunction\",\n            \"type\": \"javascript\"\n        },\n        \"useCellContentFunction\",\n        {\n            \"key\": \"cellContentFunction\",\n            \"type\": \"javascript\"\n        }\n    ]\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\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"entityName\",\"displayEntityName\":true,\"displayEntityType\":true},\"title\":\"Entities table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"18px\",\"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;\"}]}]}"
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@
 | 
			
		||||
        "resources": [],
 | 
			
		||||
        "templateHtml": "<div style=\"height: 100%;\" id=\"device-terminal\"></div>",
 | 
			
		||||
        "templateCss": ".cmd .cursor.blink {\n    -webkit-animation-name: terminal-underline;\n       -moz-animation-name: terminal-underline;\n        -ms-animation-name: terminal-underline;\n            animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n    border-bottom-color: #aaa;\n}\n",
 | 
			
		||||
        "controllerScript": "var requestTimeout = 500;\n\nself.onInit = function() {\n    var subscription = self.ctx.defaultSubscription;\n    var rpcEnabled = subscription.rpcEnabled;\n    var deviceName = 'Simulated';\n    var prompt;\n    if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n        deviceName = subscription.targetDeviceName;\n    }\n    if (self.ctx.settings.requestTimeout) {\n        requestTimeout = self.ctx.settings.requestTimeout;\n    }\n    var greetings = 'Welcome to ThingsBoard RPC commands terminal.\\n\\n';\n    if (!rpcEnabled) {\n        greetings += 'Target device is not set!\\n\\n';\n        prompt = '';\n    } else {\n        greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n        greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n        prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n    }\n    \n    var terminal = $('#device-terminal', self.ctx.$container).terminal(\n        function(command) {\n            if (command !== '') {\n                try {\n                    var localCommand = angular.copy(command).trim();\n                    if (localCommand == 'help') {\n                        printUsage(this);\n                    } else {\n                        var cmdObj = $.terminal.parse_command(localCommand);\n                        if (cmdObj.args.length > 1) {\n                            this.error(\"Wrong number of arguments!\");\n                            this.echo(' ');\n                        } else {\n                            var params;\n                            if (cmdObj.args.length && cmdObj.args[0]) {\n                                params = JSON.parse(cmdObj.args[0]);\n                            }\n                            performRpc(this, cmdObj.name, params);\n                        }\n                    }\n                } catch(e) {\n                    this.error(new String(e));\n                }\n            } else {\n               this.echo('');\n            }\n        }, {\n            greetings: greetings,\n            prompt: prompt\n    });\n    \n    if (!rpcEnabled) {\n        terminal.error('No RPC target detected!').pause();\n    }\n}\n\n\nfunction printUsage(terminal) {\n    var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n    commandsListText += '   <method> [params body]\\n\\n';\n    commandsListText += '[[b;#fff;]Example 1:]\\n'; \n    commandsListText += '   myRemoteMethod1 myText\\n\\n'; \n    commandsListText += '[[b;#fff;]Example 2:]\\n'; \n    commandsListText += '   myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n    terminal.echo(new String(commandsListText));\n}\n\nfunction performRpc(terminal, method, params) {\n    terminal.pause();\n    self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout).then(\n        function success(responseBody) {\n            terminal.echo(JSON.stringify(responseBody));\n            terminal.echo(' ');\n            terminal.resume();\n        },\n        function fail() {\n            var errorText = self.ctx.defaultSubscription.rpcErrorText;\n            terminal.error(errorText);\n            terminal.echo(' ');\n            terminal.resume();\n        }\n    );\n}\n\n  \nself.onDestroy = function() {\n}\n",
 | 
			
		||||
        "controllerScript": "var requestTimeout = 500;\n\nself.onInit = function() {\n    var subscription = self.ctx.defaultSubscription;\n    var rpcEnabled = subscription.rpcEnabled;\n    var deviceName = 'Simulated';\n    var prompt;\n    if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n        deviceName = subscription.targetDeviceName;\n    }\n    if (self.ctx.settings.requestTimeout) {\n        requestTimeout = self.ctx.settings.requestTimeout;\n    }\n    var greetings = 'Welcome to ThingsBoard RPC commands terminal.\\n\\n';\n    if (!rpcEnabled) {\n        greetings += 'Target device is not set!\\n\\n';\n        prompt = '';\n    } else {\n        greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n        greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n        prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n    }\n    \n    var terminal = $('#device-terminal', self.ctx.$container).terminal(\n        function(command) {\n            if (command !== '') {\n                try {\n                    var localCommand = angular.copy(command).trim();\n                    if (localCommand == 'help') {\n                        printUsage(this);\n                    } else {\n                        var cmdObj = $.terminal.parse_command(localCommand);\n                        if (cmdObj.args.length > 1) {\n                            this.error(\"Wrong number of arguments!\");\n                            this.echo(' ');\n                        } else {\n                            var params;\n                            if (cmdObj.args.length && cmdObj.args[0]) {\n                                try {\n                                    params = JSON.parse(cmdObj.args[0]);\n                                } catch (e) {\n                                    params = cmdObj.args[0];\n                                }\n                            }\n                            performRpc(this, cmdObj.name, params);\n                        }\n                    }\n                } catch(e) {\n                    this.error(new String(e));\n                }\n            } else {\n               this.echo('');\n            }\n        }, {\n            greetings: greetings,\n            prompt: prompt\n    });\n    \n    if (!rpcEnabled) {\n        terminal.error('No RPC target detected!').pause();\n    }\n}\n\n\nfunction printUsage(terminal) {\n    var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n    commandsListText += '   <method> [params body]\\n\\n';\n    commandsListText += '[[b;#fff;]Example 1:]\\n'; \n    commandsListText += '   myRemoteMethod1 myText\\n\\n'; \n    commandsListText += '[[b;#fff;]Example 2:]\\n'; \n    commandsListText += '   myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n    terminal.echo(new String(commandsListText));\n}\n\nfunction performRpc(terminal, method, params) {\n    terminal.pause();\n    self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout).then(\n        function success(responseBody) {\n            terminal.echo(JSON.stringify(responseBody));\n            terminal.echo(' ');\n            terminal.resume();\n        },\n        function fail() {\n            var errorText = self.ctx.defaultSubscription.rpcErrorText;\n            terminal.error(errorText);\n            terminal.echo(' ');\n            terminal.resume();\n        }\n    );\n}\n\n  \nself.onDestroy = function() {\n}\n",
 | 
			
		||||
        "settingsSchema": "{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"properties\": {\n            \"requestTimeout\": {\n                \"title\": \"RPC request timeout (ms)\",\n                \"type\": \"number\",\n                \"default\": 500\n            }\n        },\n        \"required\": [\"requestTimeout\"]\n    },\n    \"form\": [\n        \"requestTimeout\"\n    ]\n}",
 | 
			
		||||
        "dataKeySettingsSchema": "{}\n",
 | 
			
		||||
        "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n   \\\"pin\\\": \\\"{$pin}\\\",\\n   \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"Device terminal\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
 | 
			
		||||
 | 
			
		||||
@ -53,10 +53,11 @@ export default class AliasController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dashboardStateChanged() {
 | 
			
		||||
        var newEntityId = this.stateController.getStateParams().entityId;
 | 
			
		||||
        var changedAliasIds = [];
 | 
			
		||||
        for (var aliasId in this.resolvedAliasesToStateEntities) {
 | 
			
		||||
            var prevEntityId = this.resolvedAliasesToStateEntities[aliasId];
 | 
			
		||||
            var stateEntityInfo = this.resolvedAliasesToStateEntities[aliasId];
 | 
			
		||||
            var newEntityId = this.stateController.getEntityId(stateEntityInfo.entityParamName);
 | 
			
		||||
            var prevEntityId = stateEntityInfo.entityId;
 | 
			
		||||
            if (!angular.equals(newEntityId, prevEntityId)) {
 | 
			
		||||
                changedAliasIds.push(aliasId);
 | 
			
		||||
                this.setAliasUnresolved(aliasId);
 | 
			
		||||
@ -93,19 +94,26 @@ export default class AliasController {
 | 
			
		||||
                this.entityService.resolveAlias(entityAlias, this.stateController.getStateParams()).then(
 | 
			
		||||
                    function success(aliasInfo) {
 | 
			
		||||
                        aliasCtrl.resolvedAliases[aliasId] = aliasInfo;
 | 
			
		||||
                        delete aliasCtrl.resolvedAliasesPromise[aliasId];
 | 
			
		||||
                        if (aliasInfo.stateEntity) {
 | 
			
		||||
                            var stateEntityInfo = {
 | 
			
		||||
                                entityParamName: aliasInfo.entityParamName,
 | 
			
		||||
                                entityId: aliasCtrl.stateController.getEntityId(aliasInfo.entityParamName)
 | 
			
		||||
                            };
 | 
			
		||||
                            aliasCtrl.resolvedAliasesToStateEntities[aliasId] =
 | 
			
		||||
                                aliasCtrl.stateController.getStateParams().entityId;
 | 
			
		||||
                                stateEntityInfo;
 | 
			
		||||
                        }
 | 
			
		||||
                        aliasCtrl.$scope.$broadcast('entityAliasResolved', aliasId);
 | 
			
		||||
                        deferred.resolve(aliasInfo);
 | 
			
		||||
                    },
 | 
			
		||||
                    function fail() {
 | 
			
		||||
                        deferred.reject();
 | 
			
		||||
                        delete aliasCtrl.resolvedAliasesPromise[aliasId];
 | 
			
		||||
                    }
 | 
			
		||||
                );
 | 
			
		||||
            } else {
 | 
			
		||||
                deferred.reject();
 | 
			
		||||
                delete aliasCtrl.resolvedAliasesPromise[aliasId];
 | 
			
		||||
            }
 | 
			
		||||
            return this.resolvedAliasesPromise[aliasId];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -376,6 +376,7 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
 | 
			
		||||
                var aliasInfo = {
 | 
			
		||||
                    alias: entityAlias.alias,
 | 
			
		||||
                    stateEntity: result.stateEntity,
 | 
			
		||||
                    entityParamName: result.entityParamName,
 | 
			
		||||
                    resolveMultiple: filter.resolveMultiple
 | 
			
		||||
                };
 | 
			
		||||
                aliasInfo.resolvedEntities = result.entities;
 | 
			
		||||
@ -392,12 +393,30 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
 | 
			
		||||
        return deferred.promise;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getStateEntityId(filter, stateParams) {
 | 
			
		||||
        var entityId = null;
 | 
			
		||||
        if (stateParams) {
 | 
			
		||||
            if (filter.stateEntityParamName && filter.stateEntityParamName.length) {
 | 
			
		||||
                if (stateParams[filter.stateEntityParamName]) {
 | 
			
		||||
                    entityId = stateParams[filter.stateEntityParamName].entityId;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                entityId = stateParams.entityId;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return entityId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function resolveAliasFilter(filter, stateParams, maxItems) {
 | 
			
		||||
        var deferred = $q.defer();
 | 
			
		||||
        var result = {
 | 
			
		||||
            entities: [],
 | 
			
		||||
            stateEntity: false
 | 
			
		||||
        };
 | 
			
		||||
        if (filter.stateEntityParamName && filter.stateEntityParamName.length) {
 | 
			
		||||
            result.entityParamName = filter.stateEntityParamName;
 | 
			
		||||
        }
 | 
			
		||||
        var stateEntityId = getStateEntityId(filter, stateParams);
 | 
			
		||||
        switch (filter.type) {
 | 
			
		||||
            case types.aliasFilterType.entityList.value:
 | 
			
		||||
                getEntities(filter.entityType, filter.entityList).then(
 | 
			
		||||
@ -431,8 +450,8 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
 | 
			
		||||
                break;
 | 
			
		||||
            case types.aliasFilterType.stateEntity.value:
 | 
			
		||||
                result.stateEntity = true;
 | 
			
		||||
                if (stateParams && stateParams.entityId) {
 | 
			
		||||
                    getEntity(stateParams.entityId.entityType, stateParams.entityId.id).then(
 | 
			
		||||
                if (stateEntityId) {
 | 
			
		||||
                    getEntity(stateEntityId.entityType, stateEntityId.id).then(
 | 
			
		||||
                        function success(entity) {
 | 
			
		||||
                            result.entities = entitiesToEntitiesInfo([entity]);
 | 
			
		||||
                            deferred.resolve(result);
 | 
			
		||||
@ -479,9 +498,9 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
 | 
			
		||||
                result.stateEntity = filter.rootStateEntity;
 | 
			
		||||
                var rootEntityType;
 | 
			
		||||
                var rootEntityId;
 | 
			
		||||
                if (result.stateEntity && stateParams && stateParams.entityId) {
 | 
			
		||||
                    rootEntityType = stateParams.entityId.entityType;
 | 
			
		||||
                    rootEntityId = stateParams.entityId.id;
 | 
			
		||||
                if (result.stateEntity && stateEntityId) {
 | 
			
		||||
                    rootEntityType = stateEntityId.entityType;
 | 
			
		||||
                    rootEntityId = stateEntityId.id;
 | 
			
		||||
                } else if (!result.stateEntity) {
 | 
			
		||||
                    rootEntityType = filter.rootEntity.entityType;
 | 
			
		||||
                    rootEntityId = filter.rootEntity.id;
 | 
			
		||||
@ -520,9 +539,9 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
 | 
			
		||||
            case types.aliasFilterType.assetSearchQuery.value:
 | 
			
		||||
            case types.aliasFilterType.deviceSearchQuery.value:
 | 
			
		||||
                result.stateEntity = filter.rootStateEntity;
 | 
			
		||||
                if (result.stateEntity && stateParams && stateParams.entityId) {
 | 
			
		||||
                    rootEntityType = stateParams.entityId.entityType;
 | 
			
		||||
                    rootEntityId = stateParams.entityId.id;
 | 
			
		||||
                if (result.stateEntity && stateEntityId) {
 | 
			
		||||
                    rootEntityType = stateEntityId.entityType;
 | 
			
		||||
                    rootEntityId = stateEntityId.id;
 | 
			
		||||
                } else if (!result.stateEntity) {
 | 
			
		||||
                    rootEntityType = filter.rootEntity.entityType;
 | 
			
		||||
                    rootEntityId = filter.rootEntity.id;
 | 
			
		||||
 | 
			
		||||
@ -730,12 +730,15 @@ export default class Subscription {
 | 
			
		||||
                index += datasource.dataKeys.length;
 | 
			
		||||
 | 
			
		||||
                this.datasourceListeners.push(listener);
 | 
			
		||||
                this.ctx.datasourceService.subscribeToDatasource(listener);
 | 
			
		||||
                if (datasource.unresolvedStateEntity) {
 | 
			
		||||
 | 
			
		||||
                if (datasource.dataKeys.length) {
 | 
			
		||||
                    this.ctx.datasourceService.subscribeToDatasource(listener);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (datasource.unresolvedStateEntity || !datasource.dataKeys.length) {
 | 
			
		||||
                    this.notifyDataLoaded();
 | 
			
		||||
                    this.onDataUpdated();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -556,8 +556,9 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, $tr
 | 
			
		||||
         '    self.typeParameters = function() {\n\n' +
 | 
			
		||||
                    return {
 | 
			
		||||
                                useCustomDatasources: false,
 | 
			
		||||
                                maxDatasources: -1 //unlimited
 | 
			
		||||
                                maxDataKeys: -1 //unlimited
 | 
			
		||||
                                maxDatasources: -1, //unlimited
 | 
			
		||||
                                maxDataKeys: -1, //unlimited
 | 
			
		||||
                                dataKeysOptional: false
 | 
			
		||||
                           };
 | 
			
		||||
         '    }\n\n' +
 | 
			
		||||
 | 
			
		||||
@ -625,6 +626,9 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, $tr
 | 
			
		||||
            if (angular.isUndefined(result.typeParameters.maxDataKeys)) {
 | 
			
		||||
                result.typeParameters.maxDataKeys = -1;
 | 
			
		||||
            }
 | 
			
		||||
            if (angular.isUndefined(result.typeParameters.dataKeysOptional)) {
 | 
			
		||||
                result.typeParameters.dataKeysOptional = false;
 | 
			
		||||
            }
 | 
			
		||||
            if (angular.isFunction(widgetTypeInstance.actionSources)) {
 | 
			
		||||
                result.actionSources = widgetTypeInstance.actionSources();
 | 
			
		||||
            } else {
 | 
			
		||||
 | 
			
		||||
@ -68,10 +68,14 @@ function DatasourceEntity($compile, $templateCache, $q, $mdDialog, $window, $doc
 | 
			
		||||
                    ngModelCtrl.$setValidity('entityAlias',
 | 
			
		||||
                        angular.isDefined(value.entityAliasId) &&
 | 
			
		||||
                        value.entityAliasId != null);
 | 
			
		||||
                    ngModelCtrl.$setValidity('entityKeys',
 | 
			
		||||
                        angular.isDefined(value.dataKeys) &&
 | 
			
		||||
                        value.dataKeys != null &&
 | 
			
		||||
                        value.dataKeys.length > 0);
 | 
			
		||||
                    if (scope.optDataKeys) {
 | 
			
		||||
                        ngModelCtrl.$setValidity('entityKeys', true);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        ngModelCtrl.$setValidity('entityKeys',
 | 
			
		||||
                            angular.isDefined(value.dataKeys) &&
 | 
			
		||||
                            value.dataKeys != null &&
 | 
			
		||||
                            value.dataKeys.length > 0);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
@ -281,6 +285,7 @@ function DatasourceEntity($compile, $templateCache, $q, $mdDialog, $window, $doc
 | 
			
		||||
        scope: {
 | 
			
		||||
            widgetType: '=',
 | 
			
		||||
            maxDataKeys: '=',
 | 
			
		||||
            optDataKeys: '=',
 | 
			
		||||
            aliasController: '=',
 | 
			
		||||
            datakeySettingsSchema: '=',
 | 
			
		||||
            generateDataKey: '&',
 | 
			
		||||
 | 
			
		||||
@ -63,10 +63,14 @@ function DatasourceFunc($compile, $templateCache, $mdDialog, $window, $document,
 | 
			
		||||
                var dataValid = angular.isDefined(value) && value != null;
 | 
			
		||||
                ngModelCtrl.$setValidity('deviceData', dataValid);
 | 
			
		||||
                if (dataValid) {
 | 
			
		||||
                    ngModelCtrl.$setValidity('datasourceKeys',
 | 
			
		||||
                        angular.isDefined(value.dataKeys) &&
 | 
			
		||||
                        value.dataKeys != null &&
 | 
			
		||||
                        value.dataKeys.length > 0);
 | 
			
		||||
                    if (scope.optDataKeys) {
 | 
			
		||||
                        ngModelCtrl.$setValidity('datasourceKeys', true);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        ngModelCtrl.$setValidity('datasourceKeys',
 | 
			
		||||
                            angular.isDefined(value.dataKeys) &&
 | 
			
		||||
                            value.dataKeys != null &&
 | 
			
		||||
                            value.dataKeys.length > 0);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
@ -222,6 +226,7 @@ function DatasourceFunc($compile, $templateCache, $mdDialog, $window, $document,
 | 
			
		||||
        scope: {
 | 
			
		||||
            widgetType: '=',
 | 
			
		||||
            maxDataKeys: '=',
 | 
			
		||||
            optDataKeys: '=',
 | 
			
		||||
            generateDataKey: '&',
 | 
			
		||||
            datakeySettingsSchema: '='
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
@ -83,6 +83,7 @@ function Datasource($compile, $templateCache, utils, types) {
 | 
			
		||||
        scope: {
 | 
			
		||||
            aliasController: '=',
 | 
			
		||||
            maxDataKeys: '=',
 | 
			
		||||
            optDataKeys: '=',
 | 
			
		||||
            widgetType: '=',
 | 
			
		||||
            functionsOnly: '=',
 | 
			
		||||
            datakeySettingsSchema: '=',
 | 
			
		||||
 | 
			
		||||
@ -28,6 +28,7 @@
 | 
			
		||||
                            ng-switch-default
 | 
			
		||||
                            ng-model="model"
 | 
			
		||||
                            max-data-keys="maxDataKeys"
 | 
			
		||||
                            opt-data-keys="optDataKeys"
 | 
			
		||||
                            datakey-settings-schema="datakeySettingsSchema"
 | 
			
		||||
                            ng-required="model.type === types.datasourceType.function"
 | 
			
		||||
                            widget-type="widgetType"
 | 
			
		||||
@ -36,6 +37,7 @@
 | 
			
		||||
        <tb-datasource-entity flex
 | 
			
		||||
                              ng-model="model"
 | 
			
		||||
                              max-data-keys="maxDataKeys"
 | 
			
		||||
                              opt-data-keys="optDataKeys"
 | 
			
		||||
                              datakey-settings-schema="datakeySettingsSchema"
 | 
			
		||||
                              ng-switch-when="entity"
 | 
			
		||||
                              ng-required="model.type === types.datasourceType.entity"
 | 
			
		||||
 | 
			
		||||
@ -145,11 +145,13 @@ export default function WidgetActionDialogController($scope, $mdDialog, $filter,
 | 
			
		||||
                result.targetDashboardStateId = action.targetDashboardStateId;
 | 
			
		||||
                result.openRightLayout = action.openRightLayout;
 | 
			
		||||
                result.setEntityId = action.setEntityId;
 | 
			
		||||
                result.stateEntityParamName = action.stateEntityParamName;
 | 
			
		||||
                break;
 | 
			
		||||
            case vm.types.widgetActionTypes.openDashboard.value:
 | 
			
		||||
                result.targetDashboardId = action.targetDashboardId;
 | 
			
		||||
                result.targetDashboardStateId = action.targetDashboardStateId;
 | 
			
		||||
                result.setEntityId = action.setEntityId;
 | 
			
		||||
                result.stateEntityParamName = action.stateEntityParamName;
 | 
			
		||||
                break;
 | 
			
		||||
            case vm.types.widgetActionTypes.custom.value:
 | 
			
		||||
                result.customFunction = action.customFunction;
 | 
			
		||||
 | 
			
		||||
@ -104,12 +104,20 @@
 | 
			
		||||
                                     flex aria-label="{{ 'widget-action.open-right-layout' | translate }}"
 | 
			
		||||
                                     ng-model="vm.action.openRightLayout">{{ 'widget-action.open-right-layout' | translate }}
 | 
			
		||||
                        </md-checkbox>
 | 
			
		||||
                        <md-checkbox ng-if="vm.action.type == vm.types.widgetActionTypes.openDashboardState.value ||
 | 
			
		||||
                                            vm.action.type == vm.types.widgetActionTypes.updateDashboardState.value ||
 | 
			
		||||
                                            vm.action.type == vm.types.widgetActionTypes.openDashboard.value"
 | 
			
		||||
                                     flex aria-label="{{ 'widget-action.set-entity-from-widget' | translate }}"
 | 
			
		||||
                                     ng-model="vm.action.setEntityId">{{ 'widget-action.set-entity-from-widget' | translate }}
 | 
			
		||||
                        </md-checkbox>
 | 
			
		||||
                        <div flex layout="column" ng-if="vm.action.type == vm.types.widgetActionTypes.openDashboardState.value ||
 | 
			
		||||
                                                vm.action.type == vm.types.widgetActionTypes.updateDashboardState.value ||
 | 
			
		||||
                                                vm.action.type == vm.types.widgetActionTypes.openDashboard.value">
 | 
			
		||||
                            <md-checkbox flex aria-label="{{ 'widget-action.set-entity-from-widget' | translate }}"
 | 
			
		||||
                                         ng-model="vm.action.setEntityId">{{ 'widget-action.set-entity-from-widget' | translate }}
 | 
			
		||||
                            </md-checkbox>
 | 
			
		||||
                            <md-input-container ng-if="vm.action.setEntityId" class="md-block">
 | 
			
		||||
                                <label translate>alias.state-entity-parameter-name</label>
 | 
			
		||||
                                <input name="stateEntityParamName"
 | 
			
		||||
                                       placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
 | 
			
		||||
                                       ng-model="vm.action.stateEntityParamName"
 | 
			
		||||
                                       aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
 | 
			
		||||
                            </md-input-container>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <tb-js-func ng-if="vm.action.type == vm.types.widgetActionTypes.custom.value"
 | 
			
		||||
                                    ng-model="vm.action.customFunction"
 | 
			
		||||
                                    function-args="{{ ['$event', 'widgetContext', 'entityId'] }}"
 | 
			
		||||
 | 
			
		||||
@ -96,6 +96,7 @@
 | 
			
		||||
                                        <tb-datasource flex ng-model="datasource.value"
 | 
			
		||||
                                                       widget-type="widgetType"
 | 
			
		||||
                                                       max-data-keys="typeParameters.maxDataKeys"
 | 
			
		||||
                                                       opt-data-keys="typeParameters.dataKeysOptional"
 | 
			
		||||
                                                       alias-controller="aliasController"
 | 
			
		||||
                                                       functions-only="functionsOnly"
 | 
			
		||||
                                                       datakey-settings-schema="datakeySettingsSchema"
 | 
			
		||||
 | 
			
		||||
@ -421,23 +421,41 @@ export default function WidgetController($scope, $state, $timeout, $window, $ele
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function updateEntityParams(params, targetEntityParamName, targetEntityId, entityName) {
 | 
			
		||||
        if (targetEntityId) {
 | 
			
		||||
            var targetEntityParams;
 | 
			
		||||
            if (targetEntityParamName && targetEntityParamName.length) {
 | 
			
		||||
                targetEntityParams = params[targetEntityParamName];
 | 
			
		||||
                if (!targetEntityParams) {
 | 
			
		||||
                    targetEntityParams = {};
 | 
			
		||||
                    params[targetEntityParamName] = targetEntityParams;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                targetEntityParams = params;
 | 
			
		||||
            }
 | 
			
		||||
            targetEntityParams.entityId = targetEntityId;
 | 
			
		||||
            if (entityName) {
 | 
			
		||||
                targetEntityParams.entityName = entityName;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function handleWidgetAction($event, descriptor, entityId, entityName) {
 | 
			
		||||
        var type = descriptor.type;
 | 
			
		||||
        var targetEntityParamName = descriptor.stateEntityParamName;
 | 
			
		||||
        var targetEntityId;
 | 
			
		||||
        if (descriptor.setEntityId) {
 | 
			
		||||
            targetEntityId = entityId;
 | 
			
		||||
        }
 | 
			
		||||
        switch (type) {
 | 
			
		||||
            case types.widgetActionTypes.openDashboardState.value:
 | 
			
		||||
            case types.widgetActionTypes.updateDashboardState.value:
 | 
			
		||||
                var targetDashboardStateId = descriptor.targetDashboardStateId;
 | 
			
		||||
                var targetEntityId;
 | 
			
		||||
                if (descriptor.setEntityId) {
 | 
			
		||||
                    targetEntityId = entityId;
 | 
			
		||||
                }
 | 
			
		||||
                var params = {};
 | 
			
		||||
                if (targetEntityId) {
 | 
			
		||||
                    params.entityId = targetEntityId;
 | 
			
		||||
                    if (entityName) {
 | 
			
		||||
                        params.entityName = entityName;
 | 
			
		||||
                    }
 | 
			
		||||
                var params = angular.copy(widgetContext.stateController.getStateParams());
 | 
			
		||||
                if (!params) {
 | 
			
		||||
                    params = {};
 | 
			
		||||
                }
 | 
			
		||||
                updateEntityParams(params, targetEntityParamName, targetEntityId, entityName);
 | 
			
		||||
                if (type == types.widgetActionTypes.openDashboardState.value) {
 | 
			
		||||
                    widgetContext.stateController.openState(targetDashboardStateId, params, descriptor.openRightLayout);
 | 
			
		||||
                } else {
 | 
			
		||||
@ -447,18 +465,9 @@ export default function WidgetController($scope, $state, $timeout, $window, $ele
 | 
			
		||||
            case types.widgetActionTypes.openDashboard.value:
 | 
			
		||||
                var targetDashboardId = descriptor.targetDashboardId;
 | 
			
		||||
                targetDashboardStateId = descriptor.targetDashboardStateId;
 | 
			
		||||
                targetEntityId;
 | 
			
		||||
                if (descriptor.setEntityId) {
 | 
			
		||||
                    targetEntityId = entityId;
 | 
			
		||||
                }
 | 
			
		||||
                var stateObject = {};
 | 
			
		||||
                stateObject.params = {};
 | 
			
		||||
                if (targetEntityId) {
 | 
			
		||||
                    stateObject.params.entityId = targetEntityId;
 | 
			
		||||
                    if (entityName) {
 | 
			
		||||
                        stateObject.params.entityName = entityName;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                updateEntityParams(stateObject.params, targetEntityParamName, targetEntityId, entityName);
 | 
			
		||||
                if (targetDashboardStateId) {
 | 
			
		||||
                    stateObject.id = targetDashboardStateId;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,8 @@ export default function DashboardSettingsController($scope, $mdDialog, statesCon
 | 
			
		||||
    vm.imageAdded = imageAdded;
 | 
			
		||||
    vm.clearImage = clearImage;
 | 
			
		||||
 | 
			
		||||
    vm.stateControllerIdChanged = stateControllerIdChanged;
 | 
			
		||||
 | 
			
		||||
    vm.settings = settings;
 | 
			
		||||
    vm.gridSettings = gridSettings;
 | 
			
		||||
    vm.stateControllers = statesControllerService.getStateControllers();
 | 
			
		||||
@ -98,6 +100,12 @@ export default function DashboardSettingsController($scope, $mdDialog, statesCon
 | 
			
		||||
        vm.gridSettings.backgroundImageUrl = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function stateControllerIdChanged() {
 | 
			
		||||
        if (vm.settings.stateControllerId != 'default') {
 | 
			
		||||
            vm.settings.toolbarAlwaysOpen = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function save() {
 | 
			
		||||
        $scope.theForm.$setPristine();
 | 
			
		||||
        if (vm.gridSettings) {
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,8 @@
 | 
			
		||||
                    <div ng-show="vm.settings">
 | 
			
		||||
                       <md-input-container class="md-block">
 | 
			
		||||
                            <label translate>dashboard.state-controller</label>
 | 
			
		||||
                            <md-select aria-label="{{ 'dashboard.state-controller' | translate }}" ng-model="vm.settings.stateControllerId">
 | 
			
		||||
                            <md-select aria-label="{{ 'dashboard.state-controller' | translate }}"
 | 
			
		||||
                                       ng-model="vm.settings.stateControllerId" ng-change="vm.stateControllerIdChanged()">
 | 
			
		||||
                                <md-option ng-repeat="(stateControllerId, stateController) in vm.stateControllers" ng-value="stateControllerId">
 | 
			
		||||
                                    {{stateControllerId}}
 | 
			
		||||
                                </md-option>
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@ export default function DefaultStateController($scope, $location, $state, $state
 | 
			
		||||
    vm.getStateId = getStateId;
 | 
			
		||||
    vm.getStateParams = getStateParams;
 | 
			
		||||
    vm.getStateParamsByStateId = getStateParamsByStateId;
 | 
			
		||||
    vm.getEntityId = getEntityId;
 | 
			
		||||
 | 
			
		||||
    vm.getStateName = getStateName;
 | 
			
		||||
 | 
			
		||||
@ -103,6 +104,10 @@ export default function DefaultStateController($scope, $location, $state, $state
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getEntityId() {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getStateObjById(id) {
 | 
			
		||||
        for (var i=0; i < vm.stateObject.length; i++) {
 | 
			
		||||
            if (vm.stateObject[i].id === id) {
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,7 @@ export default function EntityStateController($scope, $location, $state, $stateP
 | 
			
		||||
    vm.getStateId = getStateId;
 | 
			
		||||
    vm.getStateParams = getStateParams;
 | 
			
		||||
    vm.getStateParamsByStateId = getStateParamsByStateId;
 | 
			
		||||
    vm.getEntityId = getEntityId;
 | 
			
		||||
 | 
			
		||||
    vm.getStateName = getStateName;
 | 
			
		||||
 | 
			
		||||
@ -111,6 +112,16 @@ export default function EntityStateController($scope, $location, $state, $stateP
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getEntityId(entityParamName) {
 | 
			
		||||
        var stateParams = getStateParams();
 | 
			
		||||
        if (!entityParamName || !entityParamName.length) {
 | 
			
		||||
            return stateParams.entityId;
 | 
			
		||||
        } else if (stateParams[entityParamName]) {
 | 
			
		||||
            return stateParams[entityParamName].entityId;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getStateObjById(id) {
 | 
			
		||||
        for (var i=0; i < vm.stateObject.length; i++) {
 | 
			
		||||
            if (vm.stateObject[i].id === id) {
 | 
			
		||||
@ -135,15 +146,22 @@ export default function EntityStateController($scope, $location, $state, $stateP
 | 
			
		||||
    function resolveEntity(params) {
 | 
			
		||||
        var deferred = $q.defer();
 | 
			
		||||
        if (params && params.entityId && params.entityId.id && params.entityId.entityType) {
 | 
			
		||||
            entityService.getEntity(params.entityId.entityType, params.entityId.id, {ignoreLoading: true, ignoreErrors: true}).then(
 | 
			
		||||
                function success(entity) {
 | 
			
		||||
                    var entityName = entity.name;
 | 
			
		||||
                    deferred.resolve(entityName);
 | 
			
		||||
                },
 | 
			
		||||
                function fail() {
 | 
			
		||||
                    deferred.reject();
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
            if (params.entityName && params.entityName.length) {
 | 
			
		||||
                deferred.resolve(params.entityName);
 | 
			
		||||
            } else {
 | 
			
		||||
                entityService.getEntity(params.entityId.entityType, params.entityId.id, {
 | 
			
		||||
                    ignoreLoading: true,
 | 
			
		||||
                    ignoreErrors: true
 | 
			
		||||
                }).then(
 | 
			
		||||
                    function success(entity) {
 | 
			
		||||
                        var entityName = entity.name;
 | 
			
		||||
                        deferred.resolve(entityName);
 | 
			
		||||
                    },
 | 
			
		||||
                    function fail() {
 | 
			
		||||
                        deferred.reject();
 | 
			
		||||
                    }
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            deferred.reject();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -70,6 +70,15 @@ export default function StatesComponent($compile, $templateCache, $controller, s
 | 
			
		||||
                    return null;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            stateController.getEntityId = function(entityParamName) {
 | 
			
		||||
                if (scope.statesController) {
 | 
			
		||||
                    return scope.statesController.getEntityId(entityParamName);
 | 
			
		||||
                } else {
 | 
			
		||||
                    return null;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.$on('$destroy', function callOnDestroyHook() {
 | 
			
		||||
 | 
			
		||||
@ -54,6 +54,7 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc
 | 
			
		||||
                    filter.entityNameFilter = '';
 | 
			
		||||
                    break;
 | 
			
		||||
                case types.aliasFilterType.stateEntity.value:
 | 
			
		||||
                    filter.stateEntityParamName = null;
 | 
			
		||||
                    break;
 | 
			
		||||
                case types.aliasFilterType.assetType.value:
 | 
			
		||||
                    filter.assetType = null;
 | 
			
		||||
@ -67,6 +68,7 @@ export default function EntityFilterDirective($compile, $templateCache, $q, $doc
 | 
			
		||||
                case types.aliasFilterType.assetSearchQuery.value:
 | 
			
		||||
                case types.aliasFilterType.deviceSearchQuery.value:
 | 
			
		||||
                    filter.rootStateEntity = false;
 | 
			
		||||
                    filter.stateEntityParamName = null;
 | 
			
		||||
                    filter.rootEntity = null;
 | 
			
		||||
                    filter.direction = types.entitySearchDirection.from;
 | 
			
		||||
                    filter.maxLevel = 1;
 | 
			
		||||
 | 
			
		||||
@ -59,6 +59,13 @@
 | 
			
		||||
        </md-input-container>
 | 
			
		||||
    </section>
 | 
			
		||||
    <section layout="column" ng-if="filter.type == types.aliasFilterType.stateEntity.value" id="stateEntityFilter">
 | 
			
		||||
        <md-input-container class="md-block">
 | 
			
		||||
            <label translate>alias.state-entity-parameter-name</label>
 | 
			
		||||
            <input name="stateEntityParamName"
 | 
			
		||||
                   placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
 | 
			
		||||
                   ng-model="filter.stateEntityParamName"
 | 
			
		||||
                   aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
 | 
			
		||||
        </md-input-container>
 | 
			
		||||
    </section>
 | 
			
		||||
    <section layout="column" ng-if="filter.type == types.aliasFilterType.assetType.value" id="assetTypeFilter">
 | 
			
		||||
        <tb-entity-subtype-autocomplete
 | 
			
		||||
@ -97,12 +104,21 @@
 | 
			
		||||
                              ng-disabled="filter.rootStateEntity"
 | 
			
		||||
                              ng-model="filter.rootEntity">
 | 
			
		||||
            </tb-entity-select>
 | 
			
		||||
            <section class="tb-root-state-entity-switch" layout="column" layout-align="start center">
 | 
			
		||||
                <label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
 | 
			
		||||
                <md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
 | 
			
		||||
                           aria-label="{{ 'alias.root-state-entity' | translate }}">
 | 
			
		||||
                </md-switch>
 | 
			
		||||
            </section>
 | 
			
		||||
            <div layout="column">
 | 
			
		||||
                <section class="tb-root-state-entity-switch" layout="column" layout-align="start center">
 | 
			
		||||
                    <label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
 | 
			
		||||
                    <md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
 | 
			
		||||
                               aria-label="{{ 'alias.root-state-entity' | translate }}">
 | 
			
		||||
                    </md-switch>
 | 
			
		||||
                </section>
 | 
			
		||||
                <md-input-container ng-if="filter.rootStateEntity" class="md-block">
 | 
			
		||||
                    <label translate>alias.state-entity-parameter-name</label>
 | 
			
		||||
                    <input name="stateEntityParamName"
 | 
			
		||||
                           placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
 | 
			
		||||
                           ng-model="filter.stateEntityParamName"
 | 
			
		||||
                           aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
 | 
			
		||||
                </md-input-container>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div flex layout="row">
 | 
			
		||||
            <md-input-container class="md-block" style="min-width: 100px;">
 | 
			
		||||
@ -139,12 +155,21 @@
 | 
			
		||||
                              ng-disabled="filter.rootStateEntity"
 | 
			
		||||
                              ng-model="filter.rootEntity">
 | 
			
		||||
            </tb-entity-select>
 | 
			
		||||
            <section class="tb-root-state-entity-switch" layout="column" layout-align="start center">
 | 
			
		||||
                <label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
 | 
			
		||||
                <md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
 | 
			
		||||
                           aria-label="{{ 'alias.root-state-entity' | translate }}">
 | 
			
		||||
                </md-switch>
 | 
			
		||||
            </section>
 | 
			
		||||
            <div layout="column">
 | 
			
		||||
                <section class="tb-root-state-entity-switch" layout="column" layout-align="start center">
 | 
			
		||||
                    <label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
 | 
			
		||||
                    <md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
 | 
			
		||||
                               aria-label="{{ 'alias.root-state-entity' | translate }}">
 | 
			
		||||
                    </md-switch>
 | 
			
		||||
                </section>
 | 
			
		||||
                <md-input-container ng-if="filter.rootStateEntity" class="md-block">
 | 
			
		||||
                    <label translate>alias.state-entity-parameter-name</label>
 | 
			
		||||
                    <input name="stateEntityParamName"
 | 
			
		||||
                           placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
 | 
			
		||||
                           ng-model="filter.stateEntityParamName"
 | 
			
		||||
                           aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
 | 
			
		||||
                </md-input-container>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div flex layout="row">
 | 
			
		||||
            <md-input-container class="md-block" style="min-width: 100px;">
 | 
			
		||||
@ -189,12 +214,21 @@
 | 
			
		||||
                              ng-disabled="filter.rootStateEntity"
 | 
			
		||||
                              ng-model="filter.rootEntity">
 | 
			
		||||
            </tb-entity-select>
 | 
			
		||||
            <section class="tb-root-state-entity-switch" layout="column" layout-align="start center">
 | 
			
		||||
                <label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
 | 
			
		||||
                <md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
 | 
			
		||||
                           aria-label="{{ 'alias.root-state-entity' | translate }}">
 | 
			
		||||
                </md-switch>
 | 
			
		||||
            </section>
 | 
			
		||||
            <div layout="column">
 | 
			
		||||
                <section class="tb-root-state-entity-switch" layout="column" layout-align="start center">
 | 
			
		||||
                    <label class="tb-small root-state-entity-label" translate>alias.root-state-entity</label>
 | 
			
		||||
                    <md-switch class="root-state-entity-switch" ng-model="filter.rootStateEntity"
 | 
			
		||||
                               aria-label="{{ 'alias.root-state-entity' | translate }}">
 | 
			
		||||
                    </md-switch>
 | 
			
		||||
                </section>
 | 
			
		||||
                <md-input-container ng-if="filter.rootStateEntity" class="md-block">
 | 
			
		||||
                    <label translate>alias.state-entity-parameter-name</label>
 | 
			
		||||
                    <input name="stateEntityParamName"
 | 
			
		||||
                           placeholder="{{ 'alias.default-entity-parameter-name' | translate }}"
 | 
			
		||||
                           ng-model="filter.stateEntityParamName"
 | 
			
		||||
                           aria-label="{{ 'alias.state-entity-parameter-name' | translate }}">
 | 
			
		||||
                </md-input-container>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div flex layout="row">
 | 
			
		||||
            <md-input-container class="md-block" style="min-width: 100px;">
 | 
			
		||||
 | 
			
		||||
@ -187,6 +187,8 @@ export default angular.module('thingsboard.locale', [])
 | 
			
		||||
                    "no-entity-filter-specified": "No entity filter specified",
 | 
			
		||||
                    "root-state-entity": "Use dashboard state entity as root",
 | 
			
		||||
                    "root-entity": "Root entity",
 | 
			
		||||
                    "state-entity-parameter-name": "State entity parameter name",
 | 
			
		||||
                    "default-entity-parameter-name": "By default",
 | 
			
		||||
                    "max-relation-level": "Max relation level",
 | 
			
		||||
                    "unlimited-level": "Unlimited level",
 | 
			
		||||
                    "state-entity": "Dashboard state entity",
 | 
			
		||||
 | 
			
		||||
@ -479,6 +479,9 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra
 | 
			
		||||
 | 
			
		||||
        for (var i=0;i<vm.datasources.length;i++) {
 | 
			
		||||
            datasource = vm.datasources[i];
 | 
			
		||||
            if (datasource.type == types.datasourceType.entity && !datasource.entityId) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            var entity = {
 | 
			
		||||
                id: {}
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user