diff --git a/ui/src/app/api/asset.service.js b/ui/src/app/api/asset.service.js
index f685b1e3f7..2fbb11d253 100644
--- a/ui/src/app/api/asset.service.js
+++ b/ui/src/app/api/asset.service.js
@@ -31,7 +31,8 @@ function AssetService($http, $q, customerService, userService) {
getTenantAssets: getTenantAssets,
getCustomerAssets: getCustomerAssets,
findByQuery: findByQuery,
- fetchAssetsByNameFilter: fetchAssetsByNameFilter
+ fetchAssetsByNameFilter: fetchAssetsByNameFilter,
+ getAssetTypes: getAssetTypes
}
return service;
@@ -152,7 +153,7 @@ function AssetService($http, $q, customerService, userService) {
return deferred.promise;
}
- function getTenantAssets(pageLink, applyCustomersInfo, config) {
+ function getTenantAssets(pageLink, applyCustomersInfo, config, type) {
var deferred = $q.defer();
var url = '/api/tenant/assets?limit=' + pageLink.limit;
if (angular.isDefined(pageLink.textSearch)) {
@@ -164,6 +165,9 @@ function AssetService($http, $q, customerService, userService) {
if (angular.isDefined(pageLink.textOffset)) {
url += '&textOffset=' + pageLink.textOffset;
}
+ if (angular.isDefined(type) && type.length) {
+ url += '&type=' + type;
+ }
$http.get(url, config).then(function success(response) {
if (applyCustomersInfo) {
customerService.applyAssignedCustomersInfo(response.data.data).then(
@@ -184,7 +188,7 @@ function AssetService($http, $q, customerService, userService) {
return deferred.promise;
}
- function getCustomerAssets(customerId, pageLink, applyCustomersInfo, config) {
+ function getCustomerAssets(customerId, pageLink, applyCustomersInfo, config, type) {
var deferred = $q.defer();
var url = '/api/customer/' + customerId + '/assets?limit=' + pageLink.limit;
if (angular.isDefined(pageLink.textSearch)) {
@@ -196,6 +200,9 @@ function AssetService($http, $q, customerService, userService) {
if (angular.isDefined(pageLink.textOffset)) {
url += '&textOffset=' + pageLink.textOffset;
}
+ if (angular.isDefined(type) && type.length) {
+ url += '&type=' + type;
+ }
$http.get(url, config).then(function success(response) {
if (applyCustomersInfo) {
customerService.applyAssignedCustomerInfo(response.data.data, customerId).then(
@@ -258,4 +265,15 @@ function AssetService($http, $q, customerService, userService) {
return deferred.promise;
}
+ function getAssetTypes() {
+ var deferred = $q.defer();
+ var url = '/api/asset/types';
+ $http.get(url).then(function success(response) {
+ deferred.resolve(response.data);
+ }, function fail() {
+ deferred.reject();
+ });
+ return deferred.promise;
+ }
+
}
diff --git a/ui/src/app/api/device.service.js b/ui/src/app/api/device.service.js
index d12d025050..b1d1bb60f8 100644
--- a/ui/src/app/api/device.service.js
+++ b/ui/src/app/api/device.service.js
@@ -41,12 +41,13 @@ function DeviceService($http, $q, attributeService, customerService, types) {
deleteDeviceAttributes: deleteDeviceAttributes,
sendOneWayRpcCommand: sendOneWayRpcCommand,
sendTwoWayRpcCommand: sendTwoWayRpcCommand,
- findByQuery: findByQuery
+ findByQuery: findByQuery,
+ getDeviceTypes: getDeviceTypes
}
return service;
- function getTenantDevices(pageLink, applyCustomersInfo, config) {
+ function getTenantDevices(pageLink, applyCustomersInfo, config, type) {
var deferred = $q.defer();
var url = '/api/tenant/devices?limit=' + pageLink.limit;
if (angular.isDefined(pageLink.textSearch)) {
@@ -58,6 +59,9 @@ function DeviceService($http, $q, attributeService, customerService, types) {
if (angular.isDefined(pageLink.textOffset)) {
url += '&textOffset=' + pageLink.textOffset;
}
+ if (angular.isDefined(type) && type.length) {
+ url += '&type=' + type;
+ }
$http.get(url, config).then(function success(response) {
if (applyCustomersInfo) {
customerService.applyAssignedCustomersInfo(response.data.data).then(
@@ -78,7 +82,7 @@ function DeviceService($http, $q, attributeService, customerService, types) {
return deferred.promise;
}
- function getCustomerDevices(customerId, pageLink, applyCustomersInfo, config) {
+ function getCustomerDevices(customerId, pageLink, applyCustomersInfo, config, type) {
var deferred = $q.defer();
var url = '/api/customer/' + customerId + '/devices?limit=' + pageLink.limit;
if (angular.isDefined(pageLink.textSearch)) {
@@ -90,6 +94,9 @@ function DeviceService($http, $q, attributeService, customerService, types) {
if (angular.isDefined(pageLink.textOffset)) {
url += '&textOffset=' + pageLink.textOffset;
}
+ if (angular.isDefined(type) && type.length) {
+ url += '&type=' + type;
+ }
$http.get(url, config).then(function success(response) {
if (applyCustomersInfo) {
customerService.applyAssignedCustomerInfo(response.data.data, customerId).then(
@@ -286,4 +293,15 @@ function DeviceService($http, $q, attributeService, customerService, types) {
return deferred.promise;
}
+ function getDeviceTypes() {
+ var deferred = $q.defer();
+ var url = '/api/device/types';
+ $http.get(url).then(function success(response) {
+ deferred.resolve(response.data);
+ }, function fail() {
+ deferred.reject();
+ });
+ return deferred.promise;
+ }
+
}
diff --git a/ui/src/app/app.config.js b/ui/src/app/app.config.js
index fef3273368..074437df2a 100644
--- a/ui/src/app/app.config.js
+++ b/ui/src/app/app.config.js
@@ -160,10 +160,6 @@ export default function AppConfig($provide,
indigoTheme();
}
- $mdThemingProvider.theme('tb-search-input', 'default')
- .primaryPalette('tb-primary')
- .backgroundPalette('tb-primary');
-
$mdThemingProvider.setDefaultTheme('default');
//$mdThemingProvider.alwaysWatchTheme(true);
}
diff --git a/ui/src/app/asset/asset-card.tpl.html b/ui/src/app/asset/asset-card.tpl.html
index 3c06558a82..30d0483934 100644
--- a/ui/src/app/asset/asset-card.tpl.html
+++ b/ui/src/app/asset/asset-card.tpl.html
@@ -15,5 +15,8 @@
limitations under the License.
-->
-
{{'asset.assignedToCustomer' | translate}} '{{vm.item.assignedCustomer.title}}'
-{{'asset.public' | translate}}
+
+
{{vm.item.type}}
+
{{'asset.assignedToCustomer' | translate}} '{{vm.item.assignedCustomer.title}}'
+
{{'asset.public' | translate}}
+
diff --git a/ui/src/app/asset/asset-fieldset.tpl.html b/ui/src/app/asset/asset-fieldset.tpl.html
index 8cf0c961b6..d921b2e6c4 100644
--- a/ui/src/app/asset/asset-fieldset.tpl.html
+++ b/ui/src/app/asset/asset-fieldset.tpl.html
@@ -56,13 +56,13 @@
asset.name-required
-
-
-
-
-
+
+
diff --git a/ui/src/app/asset/asset.controller.js b/ui/src/app/asset/asset.controller.js
index d0944ae143..1253891cf4 100644
--- a/ui/src/app/asset/asset.controller.js
+++ b/ui/src/app/asset/asset.controller.js
@@ -47,7 +47,8 @@ export function AssetCardController(types) {
/*@ngInject*/
-export function AssetController(userService, assetService, customerService, $state, $stateParams, $document, $mdDialog, $q, $translate, types) {
+export function AssetController($rootScope, userService, assetService, customerService, $state, $stateParams,
+ $document, $mdDialog, $q, $translate, types) {
var customerId = $stateParams.customerId;
@@ -129,8 +130,8 @@ export function AssetController(userService, assetService, customerService, $sta
}
if (vm.assetsScope === 'tenant') {
- fetchAssetsFunction = function (pageLink) {
- return assetService.getTenantAssets(pageLink, true);
+ fetchAssetsFunction = function (pageLink, assetType) {
+ return assetService.getTenantAssets(pageLink, true, null, assetType);
};
deleteAssetFunction = function (assetId) {
return assetService.deleteAsset(assetId);
@@ -229,8 +230,8 @@ export function AssetController(userService, assetService, customerService, $sta
} else if (vm.assetsScope === 'customer' || vm.assetsScope === 'customer_user') {
- fetchAssetsFunction = function (pageLink) {
- return assetService.getCustomerAssets(customerId, pageLink, true);
+ fetchAssetsFunction = function (pageLink, assetType) {
+ return assetService.getCustomerAssets(customerId, pageLink, true, null, assetType);
};
deleteAssetFunction = function (assetId) {
return assetService.unassignAssetFromCustomer(assetId);
@@ -333,6 +334,7 @@ export function AssetController(userService, assetService, customerService, $sta
var deferred = $q.defer();
assetService.saveAsset(asset).then(
function success(savedAsset) {
+ $rootScope.$broadcast('assetSaved');
var assets = [ savedAsset ];
customerService.applyAssignedCustomersInfo(assets).then(
function success(items) {
diff --git a/ui/src/app/asset/asset.directive.js b/ui/src/app/asset/asset.directive.js
index 8c13082735..7110e6ad63 100644
--- a/ui/src/app/asset/asset.directive.js
+++ b/ui/src/app/asset/asset.directive.js
@@ -25,6 +25,7 @@ export default function AssetDirective($compile, $templateCache, toast, $transla
var template = $templateCache.get(assetFieldsetTemplate);
element.html(template);
+ scope.types = types;
scope.isAssignedToCustomer = false;
scope.isPublic = false;
scope.assignedCustomer = null;
diff --git a/ui/src/app/asset/asset.routes.js b/ui/src/app/asset/asset.routes.js
index c9a312df40..732f74cf7b 100644
--- a/ui/src/app/asset/asset.routes.js
+++ b/ui/src/app/asset/asset.routes.js
@@ -20,7 +20,7 @@ import assetsTemplate from './assets.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
-export default function AssetRoutes($stateProvider) {
+export default function AssetRoutes($stateProvider, types) {
$stateProvider
.state('home.assets', {
url: '/assets',
@@ -37,6 +37,8 @@ export default function AssetRoutes($stateProvider) {
data: {
assetsType: 'tenant',
searchEnabled: true,
+ searchByEntitySubtype: true,
+ searchEntityType: types.entityType.asset,
pageTitle: 'asset.assets'
},
ncyBreadcrumb: {
@@ -58,6 +60,8 @@ export default function AssetRoutes($stateProvider) {
data: {
assetsType: 'customer',
searchEnabled: true,
+ searchByEntitySubtype: true,
+ searchEntityType: types.entityType.asset,
pageTitle: 'customer.assets'
},
ncyBreadcrumb: {
diff --git a/ui/src/app/components/datasource-device.directive.js b/ui/src/app/components/datasource-device.directive.js
deleted file mode 100644
index 02f3442cce..0000000000
--- a/ui/src/app/components/datasource-device.directive.js
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright © 2016-2017 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 './datasource-device.scss';
-
-import 'md-color-picker';
-import tinycolor from 'tinycolor2';
-import $ from 'jquery';
-import thingsboardTypes from '../common/types.constant';
-import thingsboardDatakeyConfigDialog from './datakey-config-dialog.controller';
-import thingsboardTruncate from './truncate.filter';
-
-/* eslint-disable import/no-unresolved, import/default */
-
-import datasourceDeviceTemplate from './datasource-device.tpl.html';
-import datakeyConfigDialogTemplate from './datakey-config-dialog.tpl.html';
-
-/* eslint-enable import/no-unresolved, import/default */
-
-/* eslint-disable angular/angularelement */
-
-export default angular.module('thingsboard.directives.datasourceDevice', [thingsboardTruncate, thingsboardTypes, thingsboardDatakeyConfigDialog])
- .directive('tbDatasourceDevice', DatasourceDevice)
- .name;
-
-/*@ngInject*/
-function DatasourceDevice($compile, $templateCache, $q, $mdDialog, $window, $document, $mdColorPicker, $mdConstant, types) {
-
- var linker = function (scope, element, attrs, ngModelCtrl) {
- var template = $templateCache.get(datasourceDeviceTemplate);
- element.html(template);
-
- scope.ngModelCtrl = ngModelCtrl;
- scope.types = types;
-
- scope.selectedTimeseriesDataKey = null;
- scope.timeseriesDataKeySearchText = null;
-
- scope.selectedAttributeDataKey = null;
- scope.attributeDataKeySearchText = null;
-
- scope.updateValidity = function () {
- if (ngModelCtrl.$viewValue) {
- var value = ngModelCtrl.$viewValue;
- var dataValid = angular.isDefined(value) && value != null;
- ngModelCtrl.$setValidity('deviceData', dataValid);
- if (dataValid) {
- ngModelCtrl.$setValidity('deviceAlias',
- angular.isDefined(value.deviceAliasId) &&
- value.deviceAliasId != null);
- ngModelCtrl.$setValidity('deviceKeys',
- angular.isDefined(value.dataKeys) &&
- value.dataKeys != null &&
- value.dataKeys.length > 0);
- }
- }
- };
-
- scope.$watch('deviceAlias', function () {
- if (ngModelCtrl.$viewValue) {
- if (scope.deviceAlias) {
- ngModelCtrl.$viewValue.deviceAliasId = scope.deviceAlias.id;
- } else {
- ngModelCtrl.$viewValue.deviceAliasId = null;
- }
- scope.updateValidity();
- scope.selectedDeviceAliasChange();
- }
- });
-
- scope.$watch('timeseriesDataKeys', function () {
- if (ngModelCtrl.$viewValue) {
- var dataKeys = [];
- dataKeys = dataKeys.concat(scope.timeseriesDataKeys);
- dataKeys = dataKeys.concat(scope.attributeDataKeys);
- ngModelCtrl.$viewValue.dataKeys = dataKeys;
- scope.updateValidity();
- }
- }, true);
-
- scope.$watch('attributeDataKeys', function () {
- if (ngModelCtrl.$viewValue) {
- var dataKeys = [];
- dataKeys = dataKeys.concat(scope.timeseriesDataKeys);
- dataKeys = dataKeys.concat(scope.attributeDataKeys);
- ngModelCtrl.$viewValue.dataKeys = dataKeys;
- scope.updateValidity();
- }
- }, true);
-
- ngModelCtrl.$render = function () {
- if (ngModelCtrl.$viewValue) {
- var deviceAliasId = ngModelCtrl.$viewValue.deviceAliasId;
- if (scope.deviceAliases[deviceAliasId]) {
- scope.deviceAlias = {id: deviceAliasId, alias: scope.deviceAliases[deviceAliasId].alias,
- deviceId: scope.deviceAliases[deviceAliasId].deviceId};
- } else {
- scope.deviceAlias = null;
- }
- var timeseriesDataKeys = [];
- var attributeDataKeys = [];
- for (var d in ngModelCtrl.$viewValue.dataKeys) {
- var dataKey = ngModelCtrl.$viewValue.dataKeys[d];
- if (dataKey.type === types.dataKeyType.timeseries) {
- timeseriesDataKeys.push(dataKey);
- } else if (dataKey.type === types.dataKeyType.attribute) {
- attributeDataKeys.push(dataKey);
- }
- }
- scope.timeseriesDataKeys = timeseriesDataKeys;
- scope.attributeDataKeys = attributeDataKeys;
- }
- };
-
- scope.textIsNotEmpty = function(text) {
- return (text && text != null && text.length > 0) ? true : false;
- }
-
- scope.selectedDeviceAliasChange = function () {
- if (!scope.timeseriesDataKeySearchText || scope.timeseriesDataKeySearchText === '') {
- scope.timeseriesDataKeySearchText = scope.timeseriesDataKeySearchText === '' ? null : '';
- }
- if (!scope.attributeDataKeySearchText || scope.attributeDataKeySearchText === '') {
- scope.attributeDataKeySearchText = scope.attributeDataKeySearchText === '' ? null : '';
- }
- };
-
- scope.transformTimeseriesDataKeyChip = function (chip) {
- return scope.generateDataKey({chip: chip, type: types.dataKeyType.timeseries});
- };
-
- scope.transformAttributeDataKeyChip = function (chip) {
- return scope.generateDataKey({chip: chip, type: types.dataKeyType.attribute});
- };
-
- scope.showColorPicker = function (event, dataKey) {
- $mdColorPicker.show({
- value: dataKey.color,
- defaultValue: '#fff',
- random: tinycolor.random(),
- clickOutsideToClose: false,
- hasBackdrop: false,
- skipHide: true,
- preserveScope: false,
-
- mdColorAlphaChannel: true,
- mdColorSpectrum: true,
- mdColorSliders: true,
- mdColorGenericPalette: false,
- mdColorMaterialPalette: true,
- mdColorHistory: false,
- mdColorDefaultTab: 2,
-
- $event: event
-
- }).then(function (color) {
- dataKey.color = color;
- ngModelCtrl.$setDirty();
- });
- }
-
- scope.editDataKey = function (event, dataKey, index) {
-
- $mdDialog.show({
- controller: 'DatakeyConfigDialogController',
- controllerAs: 'vm',
- templateUrl: datakeyConfigDialogTemplate,
- locals: {
- dataKey: angular.copy(dataKey),
- dataKeySettingsSchema: scope.datakeySettingsSchema,
- deviceAlias: scope.deviceAlias,
- deviceAliases: scope.deviceAliases
- },
- parent: angular.element($document[0].body),
- fullscreen: true,
- targetEvent: event,
- skipHide: true,
- onComplete: function () {
- var w = angular.element($window);
- w.triggerHandler('resize');
- }
- }).then(function (dataKey) {
- if (dataKey.type === types.dataKeyType.timeseries) {
- scope.timeseriesDataKeys[index] = dataKey;
- } else if (dataKey.type === types.dataKeyType.attribute) {
- scope.attributeDataKeys[index] = dataKey;
- }
- ngModelCtrl.$setDirty();
- }, function () {
- });
- };
-
- scope.dataKeysSearch = function (searchText, type) {
- if (scope.deviceAlias) {
- var deferred = $q.defer();
- scope.fetchDeviceKeys({deviceAliasId: scope.deviceAlias.id, query: searchText, type: type})
- .then(function (dataKeys) {
- deferred.resolve(dataKeys);
- }, function (e) {
- deferred.reject(e);
- });
- return deferred.promise;
- } else {
- return $q.when([]);
- }
- };
-
- scope.createKey = function (event, chipsId) {
- var chipsChild = $(chipsId, element)[0].firstElementChild;
- var el = angular.element(chipsChild);
- var chipBuffer = el.scope().$mdChipsCtrl.getChipBuffer();
- event.preventDefault();
- event.stopPropagation();
- el.scope().$mdChipsCtrl.appendChip(chipBuffer.trim());
- el.scope().$mdChipsCtrl.resetChipBuffer();
- }
-
- $compile(element.contents())(scope);
- }
-
- return {
- restrict: "E",
- require: "^ngModel",
- scope: {
- widgetType: '=',
- deviceAliases: '=',
- datakeySettingsSchema: '=',
- generateDataKey: '&',
- fetchDeviceKeys: '&',
- onCreateDeviceAlias: '&'
- },
- link: linker
- };
-}
-
-/* eslint-enable angular/angularelement */
diff --git a/ui/src/app/components/datasource-device.scss b/ui/src/app/components/datasource-device.scss
deleted file mode 100644
index a86118e722..0000000000
--- a/ui/src/app/components/datasource-device.scss
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright © 2016-2017 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 '../../scss/constants';
-
-.tb-device-alias-autocomplete, .tb-timeseries-datakey-autocomplete, .tb-attribute-datakey-autocomplete {
- .tb-not-found {
- display: block;
- line-height: 1.5;
- height: 48px;
- .tb-no-entries {
- line-height: 48px;
- }
- }
- li {
- height: auto !important;
- white-space: normal !important;
- }
-}
-
-tb-datasource-device {
- @media (min-width: $layout-breakpoint-gt-sm) {
- padding-left: 4px;
- padding-right: 4px;
- }
- tb-device-alias-select {
- @media (min-width: $layout-breakpoint-gt-sm) {
- width: 200px;
- max-width: 200px;
- }
- }
-}
\ No newline at end of file
diff --git a/ui/src/app/components/datasource-device.tpl.html b/ui/src/app/components/datasource-device.tpl.html
deleted file mode 100644
index 652e9a0963..0000000000
--- a/ui/src/app/components/datasource-device.tpl.html
+++ /dev/null
@@ -1,137 +0,0 @@
-
-
-
-
-
-
-
-
- {{item}}
-
-
-
- device.no-keys-found
-
-
-
-
-
-
-
-
-
-
- {{$chip.label}}
-
-
:
-
- {{$chip.name}}
- f({{$chip.name}})
-
-
-
- edit
-
-
-
-
-
-
- {{item}}
-
-
-
- device.no-keys-found
-
-
-
-
-
-
-
-
-
-
- {{$chip.label}}
-
-
:
-
- {{$chip.name}}
- f({{$chip.name}})
-
-
-
- edit
-
-
-
-
-
-
-
datakey.timeseries-required
-
datakey.timeseries-or-attributes-required
-
-
-
diff --git a/ui/src/app/components/device-alias-select.directive.js b/ui/src/app/components/device-alias-select.directive.js
deleted file mode 100644
index 01d05984b3..0000000000
--- a/ui/src/app/components/device-alias-select.directive.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright © 2016-2017 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 $ from 'jquery';
-
-import './device-alias-select.scss';
-
-/* eslint-disable import/no-unresolved, import/default */
-
-import deviceAliasSelectTemplate from './device-alias-select.tpl.html';
-
-/* eslint-enable import/no-unresolved, import/default */
-
-
-/* eslint-disable angular/angularelement */
-
-export default angular.module('thingsboard.directives.deviceAliasSelect', [])
- .directive('tbDeviceAliasSelect', DeviceAliasSelect)
- .name;
-
-/*@ngInject*/
-function DeviceAliasSelect($compile, $templateCache, $mdConstant) {
-
- var linker = function (scope, element, attrs, ngModelCtrl) {
- var template = $templateCache.get(deviceAliasSelectTemplate);
- element.html(template);
-
- scope.tbRequired = angular.isDefined(scope.tbRequired) ? scope.tbRequired : false;
-
- scope.ngModelCtrl = ngModelCtrl;
- scope.deviceAliasList = [];
- scope.deviceAlias = null;
-
- scope.updateValidity = function () {
- var value = ngModelCtrl.$viewValue;
- var valid = angular.isDefined(value) && value != null || !scope.tbRequired;
- ngModelCtrl.$setValidity('deviceAlias', valid);
- };
-
- scope.$watch('deviceAliases', function () {
- scope.deviceAliasList = [];
- for (var aliasId in scope.deviceAliases) {
- var deviceAlias = {id: aliasId, alias: scope.deviceAliases[aliasId].alias, deviceId: scope.deviceAliases[aliasId].deviceId};
- scope.deviceAliasList.push(deviceAlias);
- }
- }, true);
-
- scope.$watch('deviceAlias', function () {
- scope.updateView();
- });
-
- scope.deviceAliasSearch = function (deviceAliasSearchText) {
- return deviceAliasSearchText ? scope.deviceAliasList.filter(
- scope.createFilterForDeviceAlias(deviceAliasSearchText)) : scope.deviceAliasList;
- };
-
- scope.createFilterForDeviceAlias = function (query) {
- var lowercaseQuery = angular.lowercase(query);
- return function filterFn(deviceAlias) {
- return (angular.lowercase(deviceAlias.alias).indexOf(lowercaseQuery) === 0);
- };
- };
-
- scope.updateView = function () {
- ngModelCtrl.$setViewValue(scope.deviceAlias);
- scope.updateValidity();
- }
-
- ngModelCtrl.$render = function () {
- if (ngModelCtrl.$viewValue) {
- scope.deviceAlias = ngModelCtrl.$viewValue;
- }
- }
-
- scope.textIsNotEmpty = function(text) {
- return (text && text != null && text.length > 0) ? true : false;
- }
-
- scope.deviceAliasEnter = function($event) {
- if ($event.keyCode === $mdConstant.KEY_CODE.ENTER) {
- $event.preventDefault();
- if (!scope.deviceAlias) {
- var found = scope.deviceAliasSearch(scope.deviceAliasSearchText);
- found = found.length > 0;
- if (!found) {
- scope.createDeviceAlias($event, scope.deviceAliasSearchText);
- }
- }
- }
- }
-
- scope.createDeviceAlias = function (event, alias) {
- var autoChild = $('#device-autocomplete', element)[0].firstElementChild;
- var el = angular.element(autoChild);
- el.scope().$mdAutocompleteCtrl.hidden = true;
- el.scope().$mdAutocompleteCtrl.hasNotFound = false;
- event.preventDefault();
- var promise = scope.onCreateDeviceAlias({event: event, alias: alias});
- if (promise) {
- promise.then(
- function success(newAlias) {
- el.scope().$mdAutocompleteCtrl.hasNotFound = true;
- if (newAlias) {
- scope.deviceAliasList.push(newAlias);
- scope.deviceAlias = newAlias;
- }
- },
- function fail() {
- el.scope().$mdAutocompleteCtrl.hasNotFound = true;
- }
- );
- } else {
- el.scope().$mdAutocompleteCtrl.hasNotFound = true;
- }
- };
-
- $compile(element.contents())(scope);
- }
-
- return {
- restrict: "E",
- require: "^ngModel",
- link: linker,
- scope: {
- tbRequired: '=?',
- deviceAliases: '=',
- onCreateDeviceAlias: '&'
- }
- };
-}
-
-/* eslint-enable angular/angularelement */
diff --git a/ui/src/app/components/device-alias-select.tpl.html b/ui/src/app/components/device-alias-select.tpl.html
deleted file mode 100644
index 1eca13eef2..0000000000
--- a/ui/src/app/components/device-alias-select.tpl.html
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
- {{item.alias}}
-
-
-
-
- device.no-aliases-found
-
-
-
-
-
-
-
device.alias-required
-
-
diff --git a/ui/src/app/components/device-filter.directive.js b/ui/src/app/components/device-filter.directive.js
deleted file mode 100644
index 0233c95b02..0000000000
--- a/ui/src/app/components/device-filter.directive.js
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright © 2016-2017 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.
- */
-
-/* eslint-disable import/no-unresolved, import/default */
-
-import deviceFilterTemplate from './device-filter.tpl.html';
-
-/* eslint-enable import/no-unresolved, import/default */
-
-import './device-filter.scss';
-
-export default angular.module('thingsboard.directives.deviceFilter', [])
- .directive('tbDeviceFilter', DeviceFilter)
- .name;
-
-/*@ngInject*/
-function DeviceFilter($compile, $templateCache, $q, deviceService) {
-
- var linker = function (scope, element, attrs, ngModelCtrl) {
-
- var template = $templateCache.get(deviceFilterTemplate);
- element.html(template);
-
- scope.ngModelCtrl = ngModelCtrl;
-
- scope.fetchDevices = function(searchText, limit) {
- var pageLink = {limit: limit, textSearch: searchText};
-
- var deferred = $q.defer();
-
- deviceService.getTenantDevices(pageLink, false).then(function success(result) {
- deferred.resolve(result.data);
- }, function fail() {
- deferred.reject();
- });
-
- return deferred.promise;
- }
-
- scope.updateValidity = function() {
- if (ngModelCtrl.$viewValue) {
- var value = ngModelCtrl.$viewValue;
- var valid;
- if (value.useFilter) {
- ngModelCtrl.$setValidity('deviceList', true);
- if (angular.isDefined(value.deviceNameFilter) && value.deviceNameFilter.length > 0) {
- ngModelCtrl.$setValidity('deviceNameFilter', true);
- valid = angular.isDefined(scope.model.matchingFilterDevice) && scope.model.matchingFilterDevice != null;
- ngModelCtrl.$setValidity('deviceNameFilterDeviceMatch', valid);
- } else {
- ngModelCtrl.$setValidity('deviceNameFilter', false);
- }
- } else {
- ngModelCtrl.$setValidity('deviceNameFilter', true);
- ngModelCtrl.$setValidity('deviceNameFilterDeviceMatch', true);
- valid = angular.isDefined(value.deviceList) && value.deviceList.length > 0;
- ngModelCtrl.$setValidity('deviceList', valid);
- }
- }
- }
-
- ngModelCtrl.$render = function () {
- destroyWatchers();
- scope.model = {
- useFilter: false,
- deviceList: [],
- deviceNameFilter: ''
- }
- if (ngModelCtrl.$viewValue) {
- var value = ngModelCtrl.$viewValue;
- var model = scope.model;
- model.useFilter = value.useFilter === true ? true: false;
- model.deviceList = [];
- model.deviceNameFilter = value.deviceNameFilter || '';
- processDeviceNameFilter(model.deviceNameFilter).then(
- function(device) {
- scope.model.matchingFilterDevice = device;
- if (value.deviceList && value.deviceList.length > 0) {
- deviceService.getDevices(value.deviceList).then(function (devices) {
- model.deviceList = devices;
- updateMatchingDevice();
- initWatchers();
- });
- } else {
- updateMatchingDevice();
- initWatchers();
- }
- }
- )
- }
- }
-
- function updateMatchingDevice() {
- if (scope.model.useFilter) {
- scope.model.matchingDevice = scope.model.matchingFilterDevice;
- } else {
- if (scope.model.deviceList && scope.model.deviceList.length > 0) {
- scope.model.matchingDevice = scope.model.deviceList[0];
- } else {
- scope.model.matchingDevice = null;
- }
- }
- }
-
- function processDeviceNameFilter(deviceNameFilter) {
- var deferred = $q.defer();
- if (angular.isDefined(deviceNameFilter) && deviceNameFilter.length > 0) {
- scope.fetchDevices(deviceNameFilter, 1).then(function (devices) {
- if (devices && devices.length > 0) {
- deferred.resolve(devices[0]);
- } else {
- deferred.resolve(null);
- }
- });
- } else {
- deferred.resolve(null);
- }
- return deferred.promise;
- }
-
- function destroyWatchers() {
- if (scope.deviceListDeregistration) {
- scope.deviceListDeregistration();
- scope.deviceListDeregistration = null;
- }
- if (scope.useFilterDeregistration) {
- scope.useFilterDeregistration();
- scope.useFilterDeregistration = null;
- }
- if (scope.deviceNameFilterDeregistration) {
- scope.deviceNameFilterDeregistration();
- scope.deviceNameFilterDeregistration = null;
- }
- if (scope.matchingDeviceDeregistration) {
- scope.matchingDeviceDeregistration();
- scope.matchingDeviceDeregistration = null;
- }
- }
-
- function initWatchers() {
- scope.deviceListDeregistration = scope.$watch('model.deviceList', function () {
- if (ngModelCtrl.$viewValue) {
- var value = ngModelCtrl.$viewValue;
- value.deviceList = [];
- if (scope.model.deviceList && scope.model.deviceList.length > 0) {
- for (var i in scope.model.deviceList) {
- value.deviceList.push(scope.model.deviceList[i].id.id);
- }
- }
- updateMatchingDevice();
- ngModelCtrl.$setViewValue(value);
- scope.updateValidity();
- }
- }, true);
- scope.useFilterDeregistration = scope.$watch('model.useFilter', function () {
- if (ngModelCtrl.$viewValue) {
- var value = ngModelCtrl.$viewValue;
- value.useFilter = scope.model.useFilter;
- updateMatchingDevice();
- ngModelCtrl.$setViewValue(value);
- scope.updateValidity();
- }
- });
- scope.deviceNameFilterDeregistration = scope.$watch('model.deviceNameFilter', function (newNameFilter, prevNameFilter) {
- if (ngModelCtrl.$viewValue) {
- if (!angular.equals(newNameFilter, prevNameFilter)) {
- var value = ngModelCtrl.$viewValue;
- value.deviceNameFilter = scope.model.deviceNameFilter;
- processDeviceNameFilter(value.deviceNameFilter).then(
- function(device) {
- scope.model.matchingFilterDevice = device;
- updateMatchingDevice();
- ngModelCtrl.$setViewValue(value);
- scope.updateValidity();
- }
- );
- }
- }
- });
-
- scope.matchingDeviceDeregistration = scope.$watch('model.matchingDevice', function (newMatchingDevice, prevMatchingDevice) {
- if (!angular.equals(newMatchingDevice, prevMatchingDevice)) {
- if (scope.onMatchingDeviceChange) {
- scope.onMatchingDeviceChange({device: newMatchingDevice});
- }
- }
- });
- }
-
- $compile(element.contents())(scope);
-
- }
-
- return {
- restrict: "E",
- require: "^ngModel",
- link: linker,
- scope: {
- isEdit: '=',
- onMatchingDeviceChange: '&'
- }
- };
-
-}
diff --git a/ui/src/app/components/device-filter.scss b/ui/src/app/components/device-filter.scss
deleted file mode 100644
index ce7517fe95..0000000000
--- a/ui/src/app/components/device-filter.scss
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Copyright © 2016-2017 The Thingsboard Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-.tb-device-filter {
- #device_list_chips {
- .md-chips {
- padding-bottom: 1px;
- }
- }
- .device-name-filter-input {
- margin-top: 10px;
- margin-bottom: 0px;
- .md-errors-spacer {
- min-height: 0px;
- }
- }
- .tb-filter-switch {
- padding-left: 10px;
- .filter-switch {
- margin: 0;
- }
- .filter-label {
- margin: 5px 0;
- }
- }
- .tb-error-messages {
- margin-top: -11px;
- height: 35px;
- .tb-error-message {
- padding-left: 1px;
- }
- }
-}
\ No newline at end of file
diff --git a/ui/src/app/components/device-filter.tpl.html b/ui/src/app/components/device-filter.tpl.html
deleted file mode 100644
index c96066cf83..0000000000
--- a/ui/src/app/components/device-filter.tpl.html
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
-
-
- {{item.name}}
-
-
- device.no-devices-matching
-
-
-
-
- {{$chip.name}}
-
-
-
-
-
-
-
-
-
-
-
-
-
device.device-list-empty
-
device.device-name-filter-required
-
device.device-name-filter-no-device-matched
-
-
\ No newline at end of file
diff --git a/ui/src/app/components/grid.directive.js b/ui/src/app/components/grid.directive.js
index 56644009c8..296456a9c5 100644
--- a/ui/src/app/components/grid.directive.js
+++ b/ui/src/app/components/grid.directive.js
@@ -197,7 +197,7 @@ function GridController($scope, $state, $mdDialog, $document, $q, $timeout, $tra
},
getLength: function () {
- if (vm.items.hasNext) {
+ if (vm.items.hasNext && !vm.items.pending) {
return vm.items.rowData.length + pageSize;
} else {
return vm.items.rowData.length;
@@ -206,7 +206,7 @@ function GridController($scope, $state, $mdDialog, $document, $q, $timeout, $tra
fetchMoreItems_: function () {
if (vm.items.hasNext && !vm.items.pending) {
- var promise = vm.fetchItemsFunc(vm.items.nextPageLink);
+ var promise = vm.fetchItemsFunc(vm.items.nextPageLink, $scope.searchConfig.searchEntitySubtype);
if (promise) {
vm.items.pending = true;
promise.then(
@@ -433,6 +433,10 @@ function GridController($scope, $state, $mdDialog, $document, $q, $timeout, $tra
reload();
});
+ $scope.$on('searchEntitySubtypeUpdated', function () {
+ reload();
+ });
+
vm.onGridInited(vm);
vm.itemRows.getItemAtIndex(pageSize);
@@ -441,18 +445,16 @@ function GridController($scope, $state, $mdDialog, $document, $q, $timeout, $tra
if (vm.items && vm.items.pending) {
vm.items.reloadPending = true;
} else {
- vm.items = {
- data: [],
- rowData: [],
- nextPageLink: {
- limit: pageSize,
- textSearch: $scope.searchConfig.searchText
- },
- selections: {},
- selectedCount: 0,
- hasNext: true,
- pending: false
+ vm.items.data.length = 0;
+ vm.items.rowData.length = 0;
+ vm.items.nextPageLink = {
+ limit: pageSize,
+ textSearch: $scope.searchConfig.searchText
};
+ vm.items.selections = {};
+ vm.items.selectedCount = 0;
+ vm.items.hasNext = true;
+ vm.items.pending = false;
vm.detailsConfig.isDetailsOpen = false;
vm.items.reloadPending = false;
vm.itemRows.getItemAtIndex(pageSize);
diff --git a/ui/src/app/components/grid.tpl.html b/ui/src/app/components/grid.tpl.html
index c29c2e5b1a..24285d898a 100644
--- a/ui/src/app/components/grid.tpl.html
+++ b/ui/src/app/components/grid.tpl.html
@@ -24,9 +24,8 @@
diff --git a/ui/src/app/dashboard/aliases-device-select-button.tpl.html b/ui/src/app/dashboard/aliases-device-select-button.tpl.html
deleted file mode 100644
index 4b3c86a801..0000000000
--- a/ui/src/app/dashboard/aliases-device-select-button.tpl.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
- {{ 'dashboard.select-devices' | translate }}
-
- devices_other
-
-
-
- {{ 'dashboard.select-devices' | translate }}
-
- {{displayValue}}
-
-
diff --git a/ui/src/app/dashboard/aliases-device-select-panel.controller.js b/ui/src/app/dashboard/aliases-device-select-panel.controller.js
deleted file mode 100644
index fec6e1a000..0000000000
--- a/ui/src/app/dashboard/aliases-device-select-panel.controller.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright © 2016-2017 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.
- */
-
-/*@ngInject*/
-export default function AliasesDeviceSelectPanelController(mdPanelRef, $scope, types, deviceAliases, deviceAliasesInfo, onDeviceAliasesUpdate) {
-
- var vm = this;
- vm._mdPanelRef = mdPanelRef;
- vm.deviceAliases = deviceAliases;
- vm.deviceAliasesInfo = deviceAliasesInfo;
- vm.onDeviceAliasesUpdate = onDeviceAliasesUpdate;
-
- $scope.$watch('vm.deviceAliases', function () {
- if (onDeviceAliasesUpdate) {
- onDeviceAliasesUpdate(vm.deviceAliases);
- }
- }, true);
-}
diff --git a/ui/src/app/dashboard/aliases-device-select-panel.tpl.html b/ui/src/app/dashboard/aliases-device-select-panel.tpl.html
deleted file mode 100644
index e15159531c..0000000000
--- a/ui/src/app/dashboard/aliases-device-select-panel.tpl.html
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
- {{deviceInfo.name}}
-
-
-
-
-
-
-
diff --git a/ui/src/app/dashboard/aliases-device-select.directive.js b/ui/src/app/dashboard/aliases-device-select.directive.js
deleted file mode 100644
index 767b34cf01..0000000000
--- a/ui/src/app/dashboard/aliases-device-select.directive.js
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright © 2016-2017 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 './aliases-device-select.scss';
-
-import $ from 'jquery';
-
-/* eslint-disable import/no-unresolved, import/default */
-
-import aliasesDeviceSelectButtonTemplate from './aliases-device-select-button.tpl.html';
-import aliasesDeviceSelectPanelTemplate from './aliases-device-select-panel.tpl.html';
-
-/* eslint-enable import/no-unresolved, import/default */
-
-/* eslint-disable angular/angularelement */
-/*@ngInject*/
-export default function AliasesDeviceSelectDirective($compile, $templateCache, $mdMedia, types, $mdPanel, $document, $translate) {
-
- var linker = function (scope, element, attrs, ngModelCtrl) {
-
- /* tbAliasesDeviceSelect (ng-model)
- * {
- * "aliasId": {
- * alias: alias,
- * deviceId: deviceId
- * }
- * }
- */
-
- var template = $templateCache.get(aliasesDeviceSelectButtonTemplate);
-
- scope.tooltipDirection = angular.isDefined(attrs.tooltipDirection) ? attrs.tooltipDirection : 'top';
-
- element.html(template);
-
- scope.openEditMode = function (event) {
- if (scope.disabled) {
- return;
- }
- var position;
- var panelHeight = $mdMedia('min-height: 350px') ? 250 : 150;
- var panelWidth = 300;
- var offset = element[0].getBoundingClientRect();
- var bottomY = offset.bottom - $(window).scrollTop(); //eslint-disable-line
- var leftX = offset.left - $(window).scrollLeft(); //eslint-disable-line
- var yPosition;
- var xPosition;
- if (bottomY + panelHeight > $( window ).height()) { //eslint-disable-line
- yPosition = $mdPanel.yPosition.ABOVE;
- } else {
- yPosition = $mdPanel.yPosition.BELOW;
- }
- if (leftX + panelWidth > $( window ).width()) { //eslint-disable-line
- xPosition = $mdPanel.xPosition.CENTER;
- } else {
- xPosition = $mdPanel.xPosition.ALIGN_START;
- }
- position = $mdPanel.newPanelPosition()
- .relativeTo(element)
- .addPanelPosition(xPosition, yPosition);
- var config = {
- attachTo: angular.element($document[0].body),
- controller: 'AliasesDeviceSelectPanelController',
- controllerAs: 'vm',
- templateUrl: aliasesDeviceSelectPanelTemplate,
- panelClass: 'tb-aliases-device-select-panel',
- position: position,
- fullscreen: false,
- locals: {
- 'deviceAliases': angular.copy(scope.model),
- 'deviceAliasesInfo': scope.deviceAliasesInfo,
- 'onDeviceAliasesUpdate': function (deviceAliases) {
- scope.model = deviceAliases;
- scope.updateView();
- }
- },
- openFrom: event,
- clickOutsideToClose: true,
- escapeToClose: true,
- focusOnOpen: false
- };
- $mdPanel.open(config);
- }
-
- scope.updateView = function () {
- var value = angular.copy(scope.model);
- ngModelCtrl.$setViewValue(value);
- updateDisplayValue();
- }
-
- ngModelCtrl.$render = function () {
- if (ngModelCtrl.$viewValue) {
- var value = ngModelCtrl.$viewValue;
- scope.model = angular.copy(value);
- updateDisplayValue();
- }
- }
-
- function updateDisplayValue() {
- var displayValue;
- var singleValue = true;
- var currentAliasId;
- for (var aliasId in scope.model) {
- if (!currentAliasId) {
- currentAliasId = aliasId;
- } else {
- singleValue = false;
- break;
- }
- }
- if (singleValue && currentAliasId) {
- var deviceId = scope.model[currentAliasId].deviceId;
- var devicesInfo = scope.deviceAliasesInfo[currentAliasId];
- for (var i=0;i 0) {
- var targetDeviceAliasId = widget.config.targetDeviceAliasIds[0];
- widgetsTitleList = vm.aliasToWidgetsMap[targetDeviceAliasId];
- if (!widgetsTitleList) {
- widgetsTitleList = [];
- vm.aliasToWidgetsMap[targetDeviceAliasId] = widgetsTitleList;
- }
- widgetsTitleList.push(widget.config.title);
- }
- } else {
- for (var i in widget.config.datasources) {
- var datasource = widget.config.datasources[i];
- if (datasource.type === types.datasourceType.device && datasource.deviceAliasId) {
- widgetsTitleList = vm.aliasToWidgetsMap[datasource.deviceAliasId];
- if (!widgetsTitleList) {
- widgetsTitleList = [];
- vm.aliasToWidgetsMap[datasource.deviceAliasId] = widgetsTitleList;
- }
- widgetsTitleList.push(widget.config.title);
- }
- }
- }
- }
- }
- }
-
- if (vm.isSingleDeviceAlias) {
- if (!vm.singleDeviceAlias.deviceFilter || vm.singleDeviceAlias.deviceFilter == null) {
- vm.singleDeviceAlias.deviceFilter = {
- useFilter: false,
- deviceNameFilter: '',
- deviceList: [],
- };
- }
- }
-
- for (aliasId in config.deviceAliases) {
- var deviceAlias = config.deviceAliases[aliasId];
- var alias = deviceAlias.alias;
- var deviceFilter;
- if (!deviceAlias.deviceFilter) {
- deviceFilter = {
- useFilter: false,
- deviceNameFilter: '',
- deviceList: [],
- };
- if (deviceAlias.deviceId) {
- deviceFilter.deviceList = [deviceAlias.deviceId];
- } else {
- deviceFilter.deviceList = [];
- }
- } else {
- deviceFilter = deviceAlias.deviceFilter;
- }
- var result = {id: aliasId, alias: alias, deviceFilter: deviceFilter, changed: true};
- vm.deviceAliases.push(result);
- }
- }
-
- function onFilterDeviceChanged(device, deviceAlias) {
- if (deviceAlias) {
- if (!deviceAlias.alias || deviceAlias.alias.length == 0) {
- deviceAlias.changed = false;
- }
- if (!deviceAlias.changed && device) {
- deviceAlias.alias = device.name;
- }
- }
- }
-
- function addAlias() {
- var aliasId = 0;
- for (var a in vm.deviceAliases) {
- aliasId = Math.max(vm.deviceAliases[a].id, aliasId);
- }
- aliasId++;
- var deviceAlias = {id: aliasId, alias: '', deviceFilter: {useFilter: false, deviceNameFilter: '', deviceList: []}, changed: false};
- vm.deviceAliases.push(deviceAlias);
- }
-
- function removeAlias($event, deviceAlias) {
- var index = vm.deviceAliases.indexOf(deviceAlias);
- if (index > -1) {
- var widgetsTitleList = vm.aliasToWidgetsMap[deviceAlias.id];
- if (widgetsTitleList) {
- var widgetsListHtml = '';
- for (var t in widgetsTitleList) {
- widgetsListHtml += '
\'' + widgetsTitleList[t] + '\'';
- }
- var alert = $mdDialog.alert()
- .parent(angular.element($document[0].body))
- .clickOutsideToClose(true)
- .title($translate.instant('device.unable-delete-device-alias-title'))
- .htmlContent($translate.instant('device.unable-delete-device-alias-text', {deviceAlias: deviceAlias.alias, widgetsList: widgetsListHtml}))
- .ariaLabel($translate.instant('device.unable-delete-device-alias-title'))
- .ok($translate.instant('action.close'))
- .targetEvent($event);
- alert._options.skipHide = true;
- alert._options.fullscreen = true;
-
- $mdDialog.show(alert);
- } else {
- vm.deviceAliases.splice(index, 1);
- if ($scope.theForm) {
- $scope.theForm.$setDirty();
- }
- }
- }
- }
-
- function cancel() {
- $mdDialog.cancel();
- }
-
- function cleanupDeviceFilter(deviceFilter) {
- if (deviceFilter.useFilter) {
- deviceFilter.deviceList = [];
- } else {
- deviceFilter.deviceNameFilter = '';
- }
- return deviceFilter;
- }
-
- function save() {
-
- var deviceAliases = {};
- var uniqueAliasList = {};
-
- var valid = true;
- var aliasId, maxAliasId;
- var alias;
- var i;
-
- if (vm.isSingleDeviceAlias) {
- maxAliasId = 0;
- vm.singleDeviceAlias.deviceFilter = cleanupDeviceFilter(vm.singleDeviceAlias.deviceFilter);
- for (i in vm.deviceAliases) {
- aliasId = vm.deviceAliases[i].id;
- alias = vm.deviceAliases[i].alias;
- if (alias === vm.singleDeviceAlias.alias) {
- valid = false;
- break;
- }
- maxAliasId = Math.max(aliasId, maxAliasId);
- }
- maxAliasId++;
- vm.singleDeviceAlias.id = maxAliasId;
- } else {
- for (i in vm.deviceAliases) {
- aliasId = vm.deviceAliases[i].id;
- alias = vm.deviceAliases[i].alias;
- if (!uniqueAliasList[alias]) {
- uniqueAliasList[alias] = alias;
- deviceAliases[aliasId] = {alias: alias, deviceFilter: cleanupDeviceFilter(vm.deviceAliases[i].deviceFilter)};
- } else {
- valid = false;
- break;
- }
- }
- }
- if (valid) {
- $scope.theForm.$setPristine();
- if (vm.isSingleDeviceAlias) {
- $mdDialog.hide(vm.singleDeviceAlias);
- } else {
- $mdDialog.hide(deviceAliases);
- }
- } else {
- toast.showError($translate.instant('device.duplicate-alias-error', {alias: alias}));
- }
- }
-
-}
diff --git a/ui/src/app/dashboard/device-aliases.tpl.html b/ui/src/app/dashboard/device-aliases.tpl.html
deleted file mode 100644
index 4b362ced20..0000000000
--- a/ui/src/app/dashboard/device-aliases.tpl.html
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/ui/src/app/dashboard/states/manage-dashboard-states.tpl.html b/ui/src/app/dashboard/states/manage-dashboard-states.tpl.html
index 151c05ac7b..9f86b9b1de 100644
--- a/ui/src/app/dashboard/states/manage-dashboard-states.tpl.html
+++ b/ui/src/app/dashboard/states/manage-dashboard-states.tpl.html
@@ -58,7 +58,7 @@
{{ 'dashboard.search-states' | translate }}
-
+
diff --git a/ui/src/app/device/attribute/add-attribute-dialog.controller.js b/ui/src/app/device/attribute/add-attribute-dialog.controller.js
deleted file mode 100644
index 7f90d6da30..0000000000
--- a/ui/src/app/device/attribute/add-attribute-dialog.controller.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright © 2016-2017 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.
- */
-/*@ngInject*/
-export default function AddAttributeDialogController($scope, $mdDialog, types, deviceService, deviceId, attributeScope) {
-
- var vm = this;
-
- vm.attribute = {};
-
- vm.valueTypes = types.valueType;
-
- vm.valueType = types.valueType.string;
-
- vm.add = add;
- vm.cancel = cancel;
-
- function cancel() {
- $mdDialog.cancel();
- }
-
- function add() {
- $scope.theForm.$setPristine();
- deviceService.saveDeviceAttributes(deviceId, attributeScope, [vm.attribute]).then(
- function success() {
- $mdDialog.hide();
- }
- );
- }
-
- $scope.$watch('vm.valueType', function() {
- if (vm.valueType === types.valueType.boolean) {
- vm.attribute.value = false;
- } else {
- vm.attribute.value = null;
- }
- });
-}
diff --git a/ui/src/app/device/attribute/add-attribute-dialog.tpl.html b/ui/src/app/device/attribute/add-attribute-dialog.tpl.html
deleted file mode 100644
index 18f99fcd89..0000000000
--- a/ui/src/app/device/attribute/add-attribute-dialog.tpl.html
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-
-
diff --git a/ui/src/app/device/attribute/add-widget-to-dashboard-dialog.controller.js b/ui/src/app/device/attribute/add-widget-to-dashboard-dialog.controller.js
deleted file mode 100644
index 974b4a99c1..0000000000
--- a/ui/src/app/device/attribute/add-widget-to-dashboard-dialog.controller.js
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright © 2016-2017 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.
- */
-/*@ngInject*/
-export default function AddWidgetToDashboardDialogController($scope, $mdDialog, $state, itembuffer, dashboardService, deviceId, deviceName, widget) {
-
- var vm = this;
-
- vm.widget = widget;
- vm.dashboardId = null;
- vm.addToDashboardType = 0;
- vm.newDashboard = {};
- vm.openDashboard = false;
-
- vm.add = add;
- vm.cancel = cancel;
-
- function cancel() {
- $mdDialog.cancel();
- }
-
- function add() {
- $scope.theForm.$setPristine();
- if (vm.addToDashboardType === 0) {
- dashboardService.getDashboard(vm.dashboardId).then(
- function success(dashboard) {
- addWidgetToDashboard(dashboard);
- },
- function fail() {}
- );
- } else {
- addWidgetToDashboard(vm.newDashboard);
- }
-
- }
-
- function addWidgetToDashboard(theDashboard) {
- var aliasesInfo = {
- datasourceAliases: {},
- targetDeviceAliases: {}
- };
- aliasesInfo.datasourceAliases[0] = {
- aliasName: deviceName,
- deviceFilter: {
- useFilter: false,
- deviceNameFilter: '',
- deviceList: [deviceId]
- }
- };
- theDashboard = itembuffer.addWidgetToDashboard(theDashboard, vm.widget, aliasesInfo, null, 48, -1, -1);
- dashboardService.saveDashboard(theDashboard).then(
- function success(dashboard) {
- $mdDialog.hide();
- if (vm.openDashboard) {
- $state.go('home.dashboards.dashboard', {dashboardId: dashboard.id.id});
- }
- }
- );
- }
-
-}
diff --git a/ui/src/app/device/attribute/add-widget-to-dashboard-dialog.tpl.html b/ui/src/app/device/attribute/add-widget-to-dashboard-dialog.tpl.html
deleted file mode 100644
index eb16077422..0000000000
--- a/ui/src/app/device/attribute/add-widget-to-dashboard-dialog.tpl.html
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
diff --git a/ui/src/app/device/attribute/attribute-table.directive.js b/ui/src/app/device/attribute/attribute-table.directive.js
deleted file mode 100644
index 701fd37754..0000000000
--- a/ui/src/app/device/attribute/attribute-table.directive.js
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright © 2016-2017 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 'angular-material-data-table/dist/md-data-table.min.css';
-import './attribute-table.scss';
-
-/* eslint-disable import/no-unresolved, import/default */
-
-import attributeTableTemplate from './attribute-table.tpl.html';
-import addAttributeDialogTemplate from './add-attribute-dialog.tpl.html';
-import addWidgetToDashboardDialogTemplate from './add-widget-to-dashboard-dialog.tpl.html';
-import editAttributeValueTemplate from './edit-attribute-value.tpl.html';
-
-/* eslint-enable import/no-unresolved, import/default */
-
-import EditAttributeValueController from './edit-attribute-value.controller';
-
-/*@ngInject*/
-export default function AttributeTableDirective($compile, $templateCache, $rootScope, $q, $mdEditDialog, $mdDialog,
- $document, $translate, $filter, utils, types, dashboardService, deviceService, widgetService) {
-
- var linker = function (scope, element, attrs) {
-
- var template = $templateCache.get(attributeTableTemplate);
-
- element.html(template);
-
- scope.types = types;
- scope.attributeScopes = types.deviceAttributesScope;
-
- var getAttributeScopeByValue = function(attributeScopeValue) {
- if (scope.types.latestTelemetry.value === attributeScopeValue) {
- return scope.types.latestTelemetry;
- }
- for (var attrScope in scope.attributeScopes) {
- if (scope.attributeScopes[attrScope].value === attributeScopeValue) {
- return scope.attributeScopes[attrScope];
- }
- }
- }
-
- scope.attributeScope = getAttributeScopeByValue(attrs.defaultAttributeScope);
-
- scope.attributes = {
- count: 0,
- data: []
- };
-
- scope.selectedAttributes = [];
- scope.mode = 'default'; // 'widget'
- scope.subscriptionId = null;
-
- scope.query = {
- order: 'key',
- limit: 5,
- page: 1,
- search: null
- };
-
- scope.$watch("deviceId", function(newVal, prevVal) {
- if (newVal && !angular.equals(newVal, prevVal)) {
- scope.resetFilter();
- scope.getDeviceAttributes(false, true);
- }
- });
-
- scope.$watch("attributeScope", function(newVal, prevVal) {
- if (newVal && !angular.equals(newVal, prevVal)) {
- scope.mode = 'default';
- scope.query.search = null;
- scope.selectedAttributes = [];
- scope.getDeviceAttributes(false, true);
- }
- });
-
- scope.resetFilter = function() {
- scope.mode = 'default';
- scope.query.search = null;
- scope.selectedAttributes = [];
- scope.attributeScope = getAttributeScopeByValue(attrs.defaultAttributeScope);
- }
-
- scope.enterFilterMode = function() {
- scope.query.search = '';
- }
-
- scope.exitFilterMode = function() {
- scope.query.search = null;
- scope.getDeviceAttributes();
- }
-
- scope.$watch("query.search", function(newVal, prevVal) {
- if (!angular.equals(newVal, prevVal) && scope.query.search != null) {
- scope.getDeviceAttributes();
- }
- });
-
- function success(attributes, update, apply) {
- scope.attributes = attributes;
- if (!update) {
- scope.selectedAttributes = [];
- }
- if (apply) {
- scope.$digest();
- }
- }
-
- scope.onReorder = function() {
- scope.getDeviceAttributes(false, false);
- }
-
- scope.onPaginate = function() {
- scope.getDeviceAttributes(false, false);
- }
-
- scope.getDeviceAttributes = function(forceUpdate, reset) {
- if (scope.attributesDeferred) {
- scope.attributesDeferred.resolve();
- }
- if (scope.deviceId && scope.attributeScope) {
- if (reset) {
- scope.attributes = {
- count: 0,
- data: []
- };
- }
- scope.checkSubscription();
- scope.attributesDeferred = deviceService.getDeviceAttributes(scope.deviceId, scope.attributeScope.value,
- scope.query, function(attributes, update, apply) {
- success(attributes, update || forceUpdate, apply);
- }
- );
- } else {
- var deferred = $q.defer();
- scope.attributesDeferred = deferred;
- success({
- count: 0,
- data: []
- });
- deferred.resolve();
- }
- }
-
- scope.checkSubscription = function() {
- var newSubscriptionId = null;
- if (scope.deviceId && scope.attributeScope.clientSide && scope.mode != 'widget') {
- newSubscriptionId = deviceService.subscribeForDeviceAttributes(scope.deviceId, scope.attributeScope.value);
- }
- if (scope.subscriptionId && scope.subscriptionId != newSubscriptionId) {
- deviceService.unsubscribeForDeviceAttributes(scope.subscriptionId);
- }
- scope.subscriptionId = newSubscriptionId;
- }
-
- scope.$on('$destroy', function() {
- if (scope.subscriptionId) {
- deviceService.unsubscribeForDeviceAttributes(scope.subscriptionId);
- }
- });
-
- scope.editAttribute = function($event, attribute) {
- if (!scope.attributeScope.clientSide) {
- $event.stopPropagation();
- $mdEditDialog.show({
- controller: EditAttributeValueController,
- templateUrl: editAttributeValueTemplate,
- locals: {attributeValue: attribute.value,
- save: function (model) {
- var updatedAttribute = angular.copy(attribute);
- updatedAttribute.value = model.value;
- deviceService.saveDeviceAttributes(scope.deviceId, scope.attributeScope.value, [updatedAttribute]).then(
- function success() {
- scope.getDeviceAttributes();
- }
- );
- }},
- targetEvent: $event
- });
- }
- }
-
- scope.addAttribute = function($event) {
- if (!scope.attributeScope.clientSide) {
- $event.stopPropagation();
- $mdDialog.show({
- controller: 'AddAttributeDialogController',
- controllerAs: 'vm',
- templateUrl: addAttributeDialogTemplate,
- parent: angular.element($document[0].body),
- locals: {deviceId: scope.deviceId, attributeScope: scope.attributeScope.value},
- fullscreen: true,
- targetEvent: $event
- }).then(function () {
- scope.getDeviceAttributes();
- });
- }
- }
-
- scope.deleteAttributes = function($event) {
- if (!scope.attributeScope.clientSide) {
- $event.stopPropagation();
- var confirm = $mdDialog.confirm()
- .targetEvent($event)
- .title($translate.instant('attribute.delete-attributes-title', {count: scope.selectedAttributes.length}, 'messageformat'))
- .htmlContent($translate.instant('attribute.delete-attributes-text'))
- .ariaLabel($translate.instant('attribute.delete-attributes'))
- .cancel($translate.instant('action.no'))
- .ok($translate.instant('action.yes'));
- $mdDialog.show(confirm).then(function () {
- deviceService.deleteDeviceAttributes(scope.deviceId, scope.attributeScope.value, scope.selectedAttributes).then(
- function success() {
- scope.selectedAttributes = [];
- scope.getDeviceAttributes();
- }
- )
- });
- }
- }
-
- scope.nextWidget = function() {
- if (scope.widgetsCarousel.index < scope.widgetsList.length-1) {
- scope.widgetsCarousel.index++;
- }
- }
-
- scope.prevWidget = function() {
- if (scope.widgetsCarousel.index > 0) {
- scope.widgetsCarousel.index--;
- }
- }
-
- scope.enterWidgetMode = function() {
-
- if (scope.widgetsIndexWatch) {
- scope.widgetsIndexWatch();
- scope.widgetsIndexWatch = null;
- }
-
- if (scope.widgetsBundleWatch) {
- scope.widgetsBundleWatch();
- scope.widgetsBundleWatch = null;
- }
-
- scope.mode = 'widget';
- scope.checkSubscription();
- scope.widgetsList = [];
- scope.widgetsListCache = [];
- scope.widgetsLoaded = false;
- scope.widgetsCarousel = {
- index: 0
- }
- scope.widgetsBundle = null;
- scope.firstBundle = true;
- scope.selectedWidgetsBundleAlias = types.systemBundleAlias.cards;
-
- scope.aliasesInfo = {
- deviceAliases: {
- '1': {alias: scope.deviceName, deviceId: scope.deviceId}
- },
- deviceAliasesInfo: {
- '1': [
- {name: scope.deviceName, id: scope.deviceId}
- ]
- }
- };
-
- var dataKeyType = scope.attributeScope === types.latestTelemetry ?
- types.dataKeyType.timeseries : types.dataKeyType.attribute;
-
- var datasource = {
- type: types.datasourceType.device,
- deviceAliasId: '1',
- dataKeys: []
- }
- var i = 0;
- for (var attr =0; attr < scope.selectedAttributes.length;attr++) {
- var attribute = scope.selectedAttributes[attr];
- var dataKey = {
- name: attribute.key,
- label: attribute.key,
- type: dataKeyType,
- color: utils.getMaterialColor(i),
- settings: {},
- _hash: Math.random()
- }
- datasource.dataKeys.push(dataKey);
- i++;
- }
-
- scope.widgetsIndexWatch = scope.$watch('widgetsCarousel.index', function(newVal, prevVal) {
- if (scope.mode === 'widget' && (newVal != prevVal)) {
- var index = scope.widgetsCarousel.index;
- for (var i = 0; i < scope.widgetsList.length; i++) {
- scope.widgetsList[i].splice(0, scope.widgetsList[i].length);
- if (i === index) {
- scope.widgetsList[i].push(scope.widgetsListCache[i][0]);
- }
- }
- }
- });
-
- scope.widgetsBundleWatch = scope.$watch('widgetsBundle', function(newVal, prevVal) {
- if (scope.mode === 'widget' && (scope.firstBundle === true || newVal != prevVal)) {
- scope.widgetsList = [];
- scope.widgetsListCache = [];
- scope.widgetsCarousel.index = 0;
- scope.firstBundle = false;
- if (scope.widgetsBundle) {
- scope.widgetsLoaded = false;
- var bundleAlias = scope.widgetsBundle.alias;
- var isSystem = scope.widgetsBundle.tenantId.id === types.id.nullUid;
- widgetService.getBundleWidgetTypes(scope.widgetsBundle.alias, isSystem).then(
- function success(widgetTypes) {
-
- widgetTypes = $filter('orderBy')(widgetTypes, ['-descriptor.type','-createdTime']);
-
- for (var i = 0; i < widgetTypes.length; i++) {
- var widgetType = widgetTypes[i];
- var widgetInfo = widgetService.toWidgetInfo(widgetType);
- if (widgetInfo.type !== types.widgetType.static.value) {
- var sizeX = widgetInfo.sizeX * 2;
- var sizeY = widgetInfo.sizeY * 2;
- var col = Math.floor(Math.max(0, (20 - sizeX) / 2));
- var widget = {
- isSystemType: isSystem,
- bundleAlias: bundleAlias,
- typeAlias: widgetInfo.alias,
- type: widgetInfo.type,
- title: widgetInfo.widgetName,
- sizeX: sizeX,
- sizeY: sizeY,
- row: 0,
- col: col,
- config: angular.fromJson(widgetInfo.defaultConfig)
- };
-
- widget.config.title = widgetInfo.widgetName;
- widget.config.datasources = [datasource];
- var length;
- if (scope.attributeScope === types.latestTelemetry && widgetInfo.type !== types.widgetType.rpc.value) {
- length = scope.widgetsListCache.push([widget]);
- scope.widgetsList.push(length === 1 ? [widget] : []);
- } else if (widgetInfo.type === types.widgetType.latest.value) {
- length = scope.widgetsListCache.push([widget]);
- scope.widgetsList.push(length === 1 ? [widget] : []);
- }
- }
- }
- scope.widgetsLoaded = true;
- }
- );
- }
- }
- });
- }
-
- scope.exitWidgetMode = function() {
- if (scope.widgetsBundleWatch) {
- scope.widgetsBundleWatch();
- scope.widgetsBundleWatch = null;
- }
- if (scope.widgetsIndexWatch) {
- scope.widgetsIndexWatch();
- scope.widgetsIndexWatch = null;
- }
- scope.selectedWidgetsBundleAlias = null;
- scope.mode = 'default';
- scope.getDeviceAttributes(true);
- }
-
- scope.getServerTimeDiff = function() {
- return dashboardService.getServerTimeDiff();
- }
-
- scope.addWidgetToDashboard = function($event) {
- if (scope.mode === 'widget' && scope.widgetsListCache.length > 0) {
- var widget = scope.widgetsListCache[scope.widgetsCarousel.index][0];
- $event.stopPropagation();
- $mdDialog.show({
- controller: 'AddWidgetToDashboardDialogController',
- controllerAs: 'vm',
- templateUrl: addWidgetToDashboardDialogTemplate,
- parent: angular.element($document[0].body),
- locals: {deviceId: scope.deviceId, deviceName: scope.deviceName, widget: angular.copy(widget)},
- fullscreen: true,
- targetEvent: $event
- }).then(function () {
-
- });
- }
- }
-
- scope.loading = function() {
- return $rootScope.loading;
- }
-
- $compile(element.contents())(scope);
- }
-
- return {
- restrict: "E",
- link: linker,
- scope: {
- deviceId: '=',
- deviceName: '=',
- disableAttributeScopeSelection: '@?'
- }
- };
-}
diff --git a/ui/src/app/device/attribute/attribute-table.scss b/ui/src/app/device/attribute/attribute-table.scss
deleted file mode 100644
index 3358230654..0000000000
--- a/ui/src/app/device/attribute/attribute-table.scss
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright © 2016-2017 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 '../../../scss/constants';
-
-$md-light: rgba(255, 255, 255, 100%);
-$md-edit-icon-fill: #757575;
-
-md-toolbar.md-table-toolbar.alternate {
- .md-toolbar-tools {
- md-icon {
- color: $md-light;
- }
- }
-}
-
-.md-table {
- .md-cell {
- ng-md-icon {
- fill: $md-edit-icon-fill;
- float: right;
- height: 16px;
- }
- }
-}
-
-.widgets-carousel {
- position: relative;
- margin: 0px;
-
- min-height: 150px !important;
-
- tb-dashboard {
- #gridster-parent {
- padding: 0 7px;
- }
- }
-}
\ No newline at end of file
diff --git a/ui/src/app/device/attribute/attribute-table.tpl.html b/ui/src/app/device/attribute/attribute-table.tpl.html
deleted file mode 100644
index b6099c4ffa..0000000000
--- a/ui/src/app/device/attribute/attribute-table.tpl.html
+++ /dev/null
@@ -1,210 +0,0 @@
-
-
-
-
-
-
-
- {{scope.name | translate}}
-
-
-
-
-
-
-
- {{ attributeScope.name }}
-
-
- add
-
- {{ 'action.add' | translate }}
-
-
-
- search
-
- {{ 'action.search' | translate }}
-
-
-
- refresh
-
- {{ 'action.refresh' | translate }}
-
-
-
-
-
-
-
- search
-
- {{ 'action.search' | translate }}
-
-
-
-
-
-
-
- close
-
- {{ 'action.close' | translate }}
-
-
-
-
-
-
-
-
-
- delete
-
- {{ 'action.delete' | translate }}
-
-
-
-
- {{ 'attribute.show-on-widget' | translate }}
-
- now_widgets
- attribute.show-on-widget
-
-
-
-
-
-
-
-
-
-
- | Last update time |
- Key |
- Value |
-
-
-
-
- | {{attribute.lastUpdateTs | date : 'yyyy-MM-dd HH:mm:ss'}} |
- {{attribute.key}} |
-
- {{attribute.value}}
-
- |
-
-
-
-
-
-
-
-
-
diff --git a/ui/src/app/device/attribute/edit-attribute-value.controller.js b/ui/src/app/device/attribute/edit-attribute-value.controller.js
deleted file mode 100644
index fba5b4d0b9..0000000000
--- a/ui/src/app/device/attribute/edit-attribute-value.controller.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright © 2016-2017 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.
- */
-/*@ngInject*/
-export default function EditAttributeValueController($scope, $q, $element, types, attributeValue, save) {
-
- $scope.valueTypes = types.valueType;
-
- $scope.model = {};
-
- $scope.model.value = attributeValue;
-
- if ($scope.model.value === true || $scope.model.value === false) {
- $scope.valueType = types.valueType.boolean;
- } else if (angular.isNumber($scope.model.value)) {
- if ($scope.model.value.toString().indexOf('.') == -1) {
- $scope.valueType = types.valueType.integer;
- } else {
- $scope.valueType = types.valueType.double;
- }
- } else {
- $scope.valueType = types.valueType.string;
- }
-
- $scope.submit = submit;
- $scope.dismiss = dismiss;
-
- function dismiss() {
- $element.remove();
- }
-
- function update() {
- if($scope.editDialog.$invalid) {
- return $q.reject();
- }
-
- if(angular.isFunction(save)) {
- return $q.when(save($scope.model));
- }
-
- return $q.resolve();
- }
-
- function submit() {
- update().then(function () {
- $scope.dismiss();
- });
- }
-
- $scope.$watch('valueType', function(newVal, prevVal) {
- if (newVal != prevVal) {
- if ($scope.valueType === types.valueType.boolean) {
- $scope.model.value = false;
- } else {
- $scope.model.value = null;
- }
- }
- });
-}
diff --git a/ui/src/app/device/attribute/edit-attribute-value.tpl.html b/ui/src/app/device/attribute/edit-attribute-value.tpl.html
deleted file mode 100644
index 8ce8d81f73..0000000000
--- a/ui/src/app/device/attribute/edit-attribute-value.tpl.html
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/ui/src/app/device/device-card.tpl.html b/ui/src/app/device/device-card.tpl.html
index bb84af7182..58f4c85d96 100644
--- a/ui/src/app/device/device-card.tpl.html
+++ b/ui/src/app/device/device-card.tpl.html
@@ -15,5 +15,8 @@
limitations under the License.
-->
-{{'device.assignedToCustomer' | translate}} '{{vm.item.assignedCustomer.title}}'
-{{'device.public' | translate}}
+
+
{{vm.item.type}}
+
{{'device.assignedToCustomer' | translate}} '{{vm.item.assignedCustomer.title}}'
+
{{'device.public' | translate}}
+
diff --git a/ui/src/app/device/device-fieldset.tpl.html b/ui/src/app/device/device-fieldset.tpl.html
index fd6c9d1f72..767e47aad4 100644
--- a/ui/src/app/device/device-fieldset.tpl.html
+++ b/ui/src/app/device/device-fieldset.tpl.html
@@ -66,6 +66,13 @@
device.name-required
+
+
{{ 'device.is-gateway' | translate }}
diff --git a/ui/src/app/device/device.controller.js b/ui/src/app/device/device.controller.js
index 55b70832e2..3e8c9ac723 100644
--- a/ui/src/app/device/device.controller.js
+++ b/ui/src/app/device/device.controller.js
@@ -48,7 +48,8 @@ export function DeviceCardController(types) {
/*@ngInject*/
-export function DeviceController(userService, deviceService, customerService, $state, $stateParams, $document, $mdDialog, $q, $translate, types) {
+export function DeviceController($rootScope, userService, deviceService, customerService, $state, $stateParams,
+ $document, $mdDialog, $q, $translate, types) {
var customerId = $stateParams.customerId;
@@ -131,8 +132,8 @@ export function DeviceController(userService, deviceService, customerService, $s
}
if (vm.devicesScope === 'tenant') {
- fetchDevicesFunction = function (pageLink) {
- return deviceService.getTenantDevices(pageLink, true);
+ fetchDevicesFunction = function (pageLink, deviceType) {
+ return deviceService.getTenantDevices(pageLink, true, null, deviceType);
};
deleteDeviceFunction = function (deviceId) {
return deviceService.deleteDevice(deviceId);
@@ -242,8 +243,8 @@ export function DeviceController(userService, deviceService, customerService, $s
} else if (vm.devicesScope === 'customer' || vm.devicesScope === 'customer_user') {
- fetchDevicesFunction = function (pageLink) {
- return deviceService.getCustomerDevices(customerId, pageLink, true);
+ fetchDevicesFunction = function (pageLink, deviceType) {
+ return deviceService.getCustomerDevices(customerId, pageLink, true, null, deviceType);
};
deleteDeviceFunction = function (deviceId) {
return deviceService.unassignDeviceFromCustomer(deviceId);
@@ -368,6 +369,7 @@ export function DeviceController(userService, deviceService, customerService, $s
var deferred = $q.defer();
deviceService.saveDevice(device).then(
function success(savedDevice) {
+ $rootScope.$broadcast('deviceSaved');
var devices = [ savedDevice ];
customerService.applyAssignedCustomersInfo(devices).then(
function success(items) {
diff --git a/ui/src/app/device/device.directive.js b/ui/src/app/device/device.directive.js
index eb50a155c6..eda4fb2ce9 100644
--- a/ui/src/app/device/device.directive.js
+++ b/ui/src/app/device/device.directive.js
@@ -25,6 +25,7 @@ export default function DeviceDirective($compile, $templateCache, toast, $transl
var template = $templateCache.get(deviceFieldsetTemplate);
element.html(template);
+ scope.types = types;
scope.isAssignedToCustomer = false;
scope.isPublic = false;
scope.assignedCustomer = null;
diff --git a/ui/src/app/device/device.routes.js b/ui/src/app/device/device.routes.js
index c1f5b278dc..b1ca7ed74b 100644
--- a/ui/src/app/device/device.routes.js
+++ b/ui/src/app/device/device.routes.js
@@ -20,7 +20,7 @@ import devicesTemplate from './devices.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
-export default function DeviceRoutes($stateProvider) {
+export default function DeviceRoutes($stateProvider, types) {
$stateProvider
.state('home.devices', {
url: '/devices',
@@ -37,6 +37,8 @@ export default function DeviceRoutes($stateProvider) {
data: {
devicesType: 'tenant',
searchEnabled: true,
+ searchByEntitySubtype: true,
+ searchEntityType: types.entityType.device,
pageTitle: 'device.devices'
},
ncyBreadcrumb: {
@@ -58,6 +60,8 @@ export default function DeviceRoutes($stateProvider) {
data: {
devicesType: 'customer',
searchEnabled: true,
+ searchByEntitySubtype: true,
+ searchEntityType: types.entityType.device,
pageTitle: 'customer.devices'
},
ncyBreadcrumb: {
diff --git a/ui/src/app/entity/attribute/attribute-table.tpl.html b/ui/src/app/entity/attribute/attribute-table.tpl.html
index bf3b8cd22c..3b10902242 100644
--- a/ui/src/app/entity/attribute/attribute-table.tpl.html
+++ b/ui/src/app/entity/attribute/attribute-table.tpl.html
@@ -63,7 +63,7 @@
{{ 'action.search' | translate }}
-
+
diff --git a/ui/src/app/entity/entity-subtype-autocomplete.directive.js b/ui/src/app/entity/entity-subtype-autocomplete.directive.js
new file mode 100644
index 0000000000..98110b05a5
--- /dev/null
+++ b/ui/src/app/entity/entity-subtype-autocomplete.directive.js
@@ -0,0 +1,141 @@
+/*
+ * Copyright © 2016-2017 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 './entity-subtype-autocomplete.scss';
+
+/* eslint-disable import/no-unresolved, import/default */
+
+import entitySubtypeAutocompleteTemplate from './entity-subtype-autocomplete.tpl.html';
+
+/* eslint-enable import/no-unresolved, import/default */
+
+/*@ngInject*/
+export default function EntitySubtypeAutocomplete($compile, $templateCache, $q, $filter, assetService, deviceService, types) {
+
+ var linker = function (scope, element, attrs, ngModelCtrl) {
+ var template = $templateCache.get(entitySubtypeAutocompleteTemplate);
+ element.html(template);
+
+ scope.tbRequired = angular.isDefined(scope.tbRequired) ? scope.tbRequired : false;
+ scope.subType = null;
+ scope.subTypeSearchText = '';
+ scope.entitySubtypes = null;
+
+ scope.fetchSubTypes = function(searchText) {
+ var deferred = $q.defer();
+ loadSubTypes().then(
+ function success(subTypes) {
+ var result = $filter('filter')(subTypes, {'$': searchText});
+ if (result && result.length) {
+ deferred.resolve(result);
+ } else {
+ deferred.resolve([searchText]);
+ }
+ },
+ function fail() {
+ deferred.reject();
+ }
+ );
+ return deferred.promise;
+ }
+
+ scope.subTypeSearchTextChanged = function() {
+ }
+
+ scope.updateView = function () {
+ if (!scope.disabled) {
+ ngModelCtrl.$setViewValue(scope.subType);
+ }
+ }
+
+ ngModelCtrl.$render = function () {
+ scope.subType = ngModelCtrl.$viewValue;
+ }
+
+ scope.$watch('entityType', function () {
+ load();
+ });
+
+ scope.$watch('subType', function (newValue, prevValue) {
+ if (!angular.equals(newValue, prevValue)) {
+ scope.updateView();
+ }
+ });
+
+ scope.$watch('disabled', function () {
+ scope.updateView();
+ });
+
+ function loadSubTypes() {
+ var deferred = $q.defer();
+ if (!scope.entitySubtypes) {
+ var entitySubtypesPromise;
+ if (scope.entityType == types.entityType.asset) {
+ entitySubtypesPromise = assetService.getAssetTypes();
+ } else if (scope.entityType == types.entityType.device) {
+ entitySubtypesPromise = deviceService.getDeviceTypes();
+ }
+ if (entitySubtypesPromise) {
+ entitySubtypesPromise.then(
+ function success(types) {
+ scope.entitySubtypes = [];
+ types.forEach(function (type) {
+ scope.entitySubtypes.push(type.type);
+ });
+ deferred.resolve(scope.entitySubtypes);
+ },
+ function fail() {
+ deferred.reject();
+ }
+ );
+ } else {
+ deferred.reject();
+ }
+ } else {
+ deferred.resolve(scope.entitySubtypes);
+ }
+ return deferred.promise;
+ }
+
+ function load() {
+ if (scope.entityType == types.entityType.asset) {
+ scope.selectEntitySubtypeText = 'asset.select-asset-type';
+ scope.entitySubtypeText = 'asset.asset-type';
+ scope.entitySubtypeRequiredText = 'asset.asset-type-required';
+ } else if (scope.entityType == types.entityType.device) {
+ scope.selectEntitySubtypeText = 'device.select-device-type';
+ scope.entitySubtypeText = 'device.device-type';
+ scope.entitySubtypeRequiredText = 'device.device-type-required';
+ scope.$on('deviceSaved', function() {
+ scope.entitySubtypes = null;
+ });
+ }
+ }
+
+ $compile(element.contents())(scope);
+ }
+
+ return {
+ restrict: "E",
+ require: "^ngModel",
+ link: linker,
+ scope: {
+ theForm: '=?',
+ tbRequired: '=?',
+ disabled:'=ngDisabled',
+ entityType: "="
+ }
+ };
+}
diff --git a/ui/src/app/components/device-alias-select.scss b/ui/src/app/entity/entity-subtype-autocomplete.scss
similarity index 85%
rename from ui/src/app/components/device-alias-select.scss
rename to ui/src/app/entity/entity-subtype-autocomplete.scss
index aff0e671bf..a50aee5ae2 100644
--- a/ui/src/app/components/device-alias-select.scss
+++ b/ui/src/app/entity/entity-subtype-autocomplete.scss
@@ -13,14 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-.tb-device-alias-autocomplete {
- .tb-not-found {
+.tb-entity-subtype-autocomplete {
+ .tb-entity-subtype-item {
display: block;
- line-height: 1.5;
height: 48px;
- .tb-no-entries {
- line-height: 48px;
- }
}
li {
height: auto !important;
diff --git a/ui/src/app/entity/entity-subtype-autocomplete.tpl.html b/ui/src/app/entity/entity-subtype-autocomplete.tpl.html
new file mode 100644
index 0000000000..ce220eeaeb
--- /dev/null
+++ b/ui/src/app/entity/entity-subtype-autocomplete.tpl.html
@@ -0,0 +1,41 @@
+
+
+
+
+ {{item}}
+
+
+
+
{{ entitySubtypeRequiredText }}
+
+
diff --git a/ui/src/app/entity/entity-subtype-select.directive.js b/ui/src/app/entity/entity-subtype-select.directive.js
new file mode 100644
index 0000000000..4a2d33eea1
--- /dev/null
+++ b/ui/src/app/entity/entity-subtype-select.directive.js
@@ -0,0 +1,138 @@
+/*
+ * Copyright © 2016-2017 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 './entity-subtype-select.scss';
+
+/* eslint-disable import/no-unresolved, import/default */
+
+import entitySubtypeSelectTemplate from './entity-subtype-select.tpl.html';
+
+/* eslint-enable import/no-unresolved, import/default */
+
+/*@ngInject*/
+export default function EntitySubtypeSelect($compile, $templateCache, $translate, assetService, deviceService, types) {
+
+ var linker = function (scope, element, attrs, ngModelCtrl) {
+ var template = $templateCache.get(entitySubtypeSelectTemplate);
+ element.html(template);
+
+ if (angular.isDefined(attrs.hideLabel)) {
+ scope.showLabel = false;
+ } else {
+ scope.showLabel = true;
+ }
+
+ scope.ngModelCtrl = ngModelCtrl;
+
+ scope.entitySubtypes = [];
+
+ scope.subTypeName = function(subType) {
+ if (subType && subType.length) {
+ if (scope.typeTranslatePrefix) {
+ return $translate.instant(scope.typeTranslatePrefix + '.' + subType);
+ } else {
+ return subType;
+ }
+ } else {
+ return $translate.instant('entity.all-subtypes');
+ }
+ }
+
+ scope.$watch('entityType', function () {
+ load();
+ });
+
+ scope.$watch('entitySubtype', function (newValue, prevValue) {
+ if (!angular.equals(newValue, prevValue)) {
+ scope.updateView();
+ }
+ });
+
+ scope.updateView = function () {
+ ngModelCtrl.$setViewValue(scope.entitySubtype);
+ };
+
+ ngModelCtrl.$render = function () {
+ scope.entitySubtype = ngModelCtrl.$viewValue;
+ };
+
+ function loadSubTypes() {
+ scope.entitySubtypes.length = 0;
+ var entitySubtypesPromise;
+ if (scope.entityType == types.entityType.asset) {
+ entitySubtypesPromise = assetService.getAssetTypes();
+ } else if (scope.entityType == types.entityType.device) {
+ entitySubtypesPromise = deviceService.getDeviceTypes();
+ }
+ if (entitySubtypesPromise) {
+ entitySubtypesPromise.then(
+ function success(types) {
+ scope.entitySubtypes.push('');
+ types.forEach(function(type) {
+ scope.entitySubtypes.push(type.type);
+ });
+ if (scope.entitySubtypes.indexOf(scope.entitySubtype) == -1) {
+ scope.entitySubtype = '';
+ }
+ },
+ function fail() {}
+ );
+ }
+
+ }
+
+ function load() {
+ if (scope.entityType == types.entityType.asset) {
+ scope.entitySubtypeTitle = 'asset.asset-type';
+ scope.entitySubtypeRequiredText = 'asset.asset-type-required';
+ } else if (scope.entityType == types.entityType.device) {
+ scope.entitySubtypeTitle = 'device.device-type';
+ scope.entitySubtypeRequiredText = 'device.device-type-required';
+ }
+ scope.entitySubtypes.length = 0;
+ if (scope.entitySubtypesList && scope.entitySubtypesList.length) {
+ scope.entitySubtypesList.forEach(function(subType) {
+ scope.entitySubtypes.push(subType);
+ });
+ } else {
+ loadSubTypes();
+ if (scope.entityType == types.entityType.asset) {
+ scope.$on('assetSaved', function() {
+ loadSubTypes();
+ });
+ } else if (scope.entityType == types.entityType.device) {
+ scope.$on('deviceSaved', function() {
+ loadSubTypes();
+ });
+ }
+ }
+ }
+
+ $compile(element.contents())(scope);
+ }
+
+ return {
+ restrict: "E",
+ require: "^ngModel",
+ link: linker,
+ scope: {
+ theForm: '=?',
+ entityType: "=",
+ entitySubtypesList: "=?",
+ typeTranslatePrefix: "@?"
+ }
+ };
+}
diff --git a/ui/src/app/dashboard/device-aliases.scss b/ui/src/app/entity/entity-subtype-select.scss
similarity index 81%
rename from ui/src/app/dashboard/device-aliases.scss
rename to ui/src/app/entity/entity-subtype-select.scss
index 9b1c489287..a6b2fe108e 100644
--- a/ui/src/app/dashboard/device-aliases.scss
+++ b/ui/src/app/entity/entity-subtype-select.scss
@@ -14,12 +14,6 @@
* limitations under the License.
*/
-.tb-aliases-dialog {
- .md-dialog-content {
- padding-bottom: 0px;
- }
- .tb-alias {
- padding: 10px 0 0 10px;
- margin: 5px;
- }
+md-select.tb-entity-subtype-select {
+ min-width: 200px;
}
diff --git a/ui/src/app/entity/entity-subtype-select.tpl.html b/ui/src/app/entity/entity-subtype-select.tpl.html
new file mode 100644
index 0000000000..323f07f31f
--- /dev/null
+++ b/ui/src/app/entity/entity-subtype-select.tpl.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+ {{ subTypeName(subType) }}
+
+
+
+
{{ entitySubtypeRequiredText }}
+
+
diff --git a/ui/src/app/entity/index.js b/ui/src/app/entity/index.js
index 07c0862242..8423f11c3c 100644
--- a/ui/src/app/entity/index.js
+++ b/ui/src/app/entity/index.js
@@ -16,6 +16,8 @@
import EntityAliasesController from './entity-aliases.controller';
import EntityTypeSelectDirective from './entity-type-select.directive';
+import EntitySubtypeSelectDirective from './entity-subtype-select.directive';
+import EntitySubtypeAutocompleteDirective from './entity-subtype-autocomplete.directive';
import EntityFilterDirective from './entity-filter.directive';
import AliasesEntitySelectPanelController from './aliases-entity-select-panel.controller';
import AliasesEntitySelectDirective from './aliases-entity-select.directive';
@@ -29,6 +31,8 @@ export default angular.module('thingsboard.entity', [])
.controller('AddAttributeDialogController', AddAttributeDialogController)
.controller('AddWidgetToDashboardDialogController', AddWidgetToDashboardDialogController)
.directive('tbEntityTypeSelect', EntityTypeSelectDirective)
+ .directive('tbEntitySubtypeSelect', EntitySubtypeSelectDirective)
+ .directive('tbEntitySubtypeAutocomplete', EntitySubtypeAutocompleteDirective)
.directive('tbEntityFilter', EntityFilterDirective)
.directive('tbAliasesEntitySelect', AliasesEntitySelectDirective)
.directive('tbAttributeTable', AttributeTableDirective)
diff --git a/ui/src/app/layout/home.controller.js b/ui/src/app/layout/home.controller.js
index 4979501085..5091da8415 100644
--- a/ui/src/app/layout/home.controller.js
+++ b/ui/src/app/layout/home.controller.js
@@ -25,7 +25,7 @@ import logoSvg from '../../svg/logo_title_white.svg';
/* eslint-disable angular/angularelement */
/*@ngInject*/
-export default function HomeController(loginService, userService, deviceService, Fullscreen, $scope, $element, $rootScope, $document, $state,
+export default function HomeController(types, loginService, userService, deviceService, Fullscreen, $scope, $element, $rootScope, $document, $state,
$window, $log, $mdMedia, $animate, $timeout) {
var siteSideNav = $('.tb-site-sidenav', $element);
@@ -38,8 +38,11 @@ export default function HomeController(loginService, userService, deviceService,
if (angular.isUndefined($rootScope.searchConfig)) {
$rootScope.searchConfig = {
searchEnabled: false,
+ searchByEntitySubtype: false,
+ searchEntityType: null,
showSearch: false,
- searchText: ""
+ searchText: "",
+ searchEntitySubtype: ""
};
}
@@ -47,6 +50,7 @@ export default function HomeController(loginService, userService, deviceService,
vm.isLockSidenav = false;
vm.displaySearchMode = displaySearchMode;
+ vm.displayEntitySubtypeSearch = displayEntitySubtypeSearch;
vm.openSidenav = openSidenav;
vm.goBack = goBack;
vm.searchTextUpdated = searchTextUpdated;
@@ -54,25 +58,35 @@ export default function HomeController(loginService, userService, deviceService,
vm.toggleFullscreen = toggleFullscreen;
$scope.$on('$stateChangeSuccess', function (evt, to, toParams, from) {
+ watchEntitySubtype(false);
if (angular.isDefined(to.data.searchEnabled)) {
$scope.searchConfig.searchEnabled = to.data.searchEnabled;
+ $scope.searchConfig.searchByEntitySubtype = to.data.searchByEntitySubtype;
+ $scope.searchConfig.searchEntityType = to.data.searchEntityType;
if ($scope.searchConfig.searchEnabled === false || to.name !== from.name) {
$scope.searchConfig.showSearch = false;
$scope.searchConfig.searchText = "";
+ $scope.searchConfig.searchEntitySubtype = "";
}
} else {
$scope.searchConfig.searchEnabled = false;
+ $scope.searchConfig.searchByEntitySubtype = false;
+ $scope.searchConfig.searchEntityType = null;
$scope.searchConfig.showSearch = false;
$scope.searchConfig.searchText = "";
+ $scope.searchConfig.searchEntitySubtype = "";
}
+ watchEntitySubtype($scope.searchConfig.searchByEntitySubtype);
});
- if ($mdMedia('gt-sm')) {
+ vm.isGtSm = $mdMedia('gt-sm');
+ if (vm.isGtSm) {
vm.isLockSidenav = true;
$animate.enabled(siteSideNav, false);
}
$scope.$watch(function() { return $mdMedia('gt-sm'); }, function(isGtSm) {
+ vm.isGtSm = isGtSm;
vm.isLockSidenav = isGtSm;
vm.isShowSidenav = isGtSm;
if (!isGtSm) {
@@ -84,11 +98,28 @@ export default function HomeController(loginService, userService, deviceService,
}
});
+ function watchEntitySubtype(enableWatch) {
+ if ($scope.entitySubtypeWatch) {
+ $scope.entitySubtypeWatch();
+ }
+ if (enableWatch) {
+ $scope.entitySubtypeWatch = $scope.$watch('searchConfig.searchEntitySubtype', function (newVal, prevVal) {
+ if (!angular.equals(newVal, prevVal)) {
+ $scope.$broadcast('searchEntitySubtypeUpdated');
+ }
+ });
+ }
+ }
+
function displaySearchMode() {
return $scope.searchConfig.searchEnabled &&
$scope.searchConfig.showSearch;
}
+ function displayEntitySubtypeSearch() {
+ return $scope.searchConfig.searchByEntitySubtype && vm.isGtSm;
+ }
+
function toggleFullscreen() {
if (Fullscreen.isEnabled()) {
Fullscreen.cancel();
diff --git a/ui/src/app/layout/home.scss b/ui/src/app/layout/home.scss
index edcdbc81bb..a809cf69f0 100644
--- a/ui/src/app/layout/home.scss
+++ b/ui/src/app/layout/home.scss
@@ -70,3 +70,11 @@ md-icon.tb-logo-title {
z-index: 2;
white-space: nowrap;
}
+
+.tb-entity-subtype-search {
+ margin-top: 15px;
+}
+
+.tb-entity-search {
+ margin-top: 34px;
+}
diff --git a/ui/src/app/layout/home.tpl.html b/ui/src/app/layout/home.tpl.html
index bfb37eb3cd..8e642eb7b0 100644
--- a/ui/src/app/layout/home.tpl.html
+++ b/ui/src/app/layout/home.tpl.html
@@ -39,7 +39,7 @@