diff --git a/ui/src/app/api/device.service.js b/ui/src/app/api/device.service.js index 84f9a8aee2..4d1de6a3b6 100644 --- a/ui/src/app/api/device.service.js +++ b/ui/src/app/api/device.service.js @@ -177,36 +177,28 @@ function DeviceService($http, $q, $window, userService, attributeService, custom let attributesType = Object.keys(types.attributesScope); let allPromise = []; let promise = ""; - let statisticalInfo = {}; + if (deviceRelation.accessToken !== "") { + promise = getDeviceCredentials(deviceId.id,null,config).then(function (response){ + response.credentialsId = deviceRelation.accessToken; + response.credentialsType = "ACCESS_TOKEN"; + response.credentialsValue = null; + return saveDeviceCredentials(response, config).catch(function(){}); + }); + allPromise.push(promise) + } for (let i = 0; i < attributesType.length; i++) { let attribute = attributesType[i]; if (deviceRelation.attributes[attribute] && deviceRelation.attributes[attribute].length !== 0) { - promise = attributeService.saveEntityAttributes(types.entityType.device, deviceId, types.attributesScope[attribute].value, deviceRelation.attributes[attribute], config).then(function () { - statisticalInfo.create = { - [attribute]: deviceRelation.attributes[attribute].length - }; - }, function () { - statisticalInfo.error = { - [attribute]: deviceRelation.attributes[attribute].length - }; - }); + promise = attributeService.saveEntityAttributes(types.entityType.device, deviceId.id, types.attributesScope[attribute].value, deviceRelation.attributes[attribute], config).catch(function () {}); allPromise.push(promise); } } if (deviceRelation.timeseries.length !== 0) { - promise = attributeService.saveEntityTimeseries(types.entityType.device, deviceId, "time", deviceRelation.timeseries, config).then(function () { - statisticalInfo.create = { - timeseries: deviceRelation.timeseries.length - }; - }, function () { - statisticalInfo.error = { - timeseries: deviceRelation.timeseries.length - }; - }); + promise = attributeService.saveEntityTimeseries(types.entityType.device, deviceId.id, "time", deviceRelation.timeseries, config).catch(function(){}); allPromise.push(promise); } $q.all(allPromise).then(function success() { - deferred.resolve(statisticalInfo); + deferred.resolve(); }); return deferred.promise; } @@ -223,8 +215,7 @@ function DeviceService($http, $q, $window, userService, attributeService, custom statisticalInfo.create={ device: 1 }; - saveDeviceRelarion(response.id.id, deviceParameters, config).then(function success(response) { - angular.merge(statisticalInfo, response, statisticalInfo); + saveDeviceRelarion(response.id, deviceParameters, config).then(function success() { deferred.resolve(statisticalInfo); }); }, function fail() { @@ -233,11 +224,7 @@ function DeviceService($http, $q, $window, userService, attributeService, custom statisticalInfo.update = { device: 1 }; - saveDeviceRelarion(response.id.id, deviceParameters, config).then(function success(response) { - if(response.create) { - delete Object.assign(response, {update: response.create}).create; - } - angular.merge(statisticalInfo, response); + saveDeviceRelarion(response.id, deviceParameters, config).then(function success() { deferred.resolve(statisticalInfo); }); }, function fail() { @@ -267,7 +254,8 @@ function DeviceService($http, $q, $window, userService, attributeService, custom return deferred.promise; } - function getDeviceCredentials(deviceId, sync) { + function getDeviceCredentials(deviceId, sync, config) { + config = config || {}; var deferred = $q.defer(); var url = '/api/device/' + deviceId + '/credentials'; if (sync) { @@ -282,7 +270,7 @@ function DeviceService($http, $q, $window, userService, attributeService, custom deferred.reject(); } } else { - $http.get(url, null).then(function success(response) { + $http.get(url, config).then(function success(response) { deferred.resolve(response.data); }, function fail() { deferred.reject(); @@ -291,10 +279,11 @@ function DeviceService($http, $q, $window, userService, attributeService, custom return deferred.promise; } - function saveDeviceCredentials(deviceCredentials) { + function saveDeviceCredentials(deviceCredentials, config) { + config = config || {}; var deferred = $q.defer(); var url = '/api/device/credentials'; - $http.post(url, deviceCredentials).then(function success(response) { + $http.post(url, deviceCredentials, config).then(function success(response) { deferred.resolve(response.data); }, function fail() { deferred.reject(); diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index 46bf2e9f14..33e70267b8 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -371,6 +371,10 @@ export default angular.module('thingsboard.types', []) entityField: { name: 'entity-group.column-type.entity-field', value: 'ENTITY_FIELD' + }, + accessToken: { + name: 'entity-group.column-type.access-token', + value: 'ACCESS_TOKEN' } }, entityField: { diff --git a/ui/src/app/import-export/import-dialog-csv.controller.js b/ui/src/app/import-export/import-dialog-csv.controller.js index 4dcce4a276..534669dbec 100644 --- a/ui/src/app/import-export/import-dialog-csv.controller.js +++ b/ui/src/app/import-export/import-dialog-csv.controller.js @@ -28,7 +28,7 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo vm.previousStep = previousStep; vm.addDevices = addDevices; - vm.importParams = { + vm.importParameters = { delim: ',', isUpdate: true, isHeader: true @@ -43,7 +43,6 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo vm.isAlternative = false; vm.isMobileStepText = true; - vm.columnsParam = []; vm.parseData = []; vm.delimiters = [{ @@ -60,6 +59,12 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo value: 'Tab' }]; + vm.progressCreate = 0; + + $scope.$on('importCSV-completed', function (event, completed) { + vm.progressCreate = completed.progress; + }); + var parseData = {}; function fileAdded($file) { @@ -88,16 +93,17 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo function parseCSV(importData) { var config = { - delim: vm.importParams.delim, - header: vm.importParams.isHeader + delim: vm.importParameters.delim, + header: vm.importParameters.isHeader }; return importExport.convertCSVToJson(importData, config); } function createColumnsData(parseData) { + vm.columnsParam = []; var columnParam = {}; for (var i = 0; i < parseData.headers.length; i++) { - if (vm.importParams.isHeader && parseData.headers[i].search(/^(name|type)$/im) === 0) { + if (vm.importParameters.isHeader && parseData.headers[i].search(/^(name|type)$/im) === 0) { columnParam = { type: types.entityGroup.columnType.entityField.value, key: parseData.headers[i].toLowerCase(), @@ -106,7 +112,7 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo } else { columnParam = { type: types.entityGroup.columnType.serverAttribute.value, - key: vm.importParams.isHeader ? parseData.headers[i] : "", + key: vm.importParameters.isHeader ? parseData.headers[i] : "", sampleData: parseData.rows[0][i] }; } @@ -124,6 +130,7 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo var entityData = { name: "", type: "", + accessToken: "", attributes: { server: [], shared: [] @@ -150,6 +157,9 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo value: importData.rows[i][j] }); break; + case types.entityGroup.columnType.accessToken.value: + entityData.accessToken = importData.rows[i][j]; + break; case types.entityGroup.columnType.entityField.value: switch (parameterColumns[j].key) { case types.entityGroup.entityField.name.value: @@ -164,7 +174,7 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo } entitysData.push(entityData); } - importExport.createMultiEntity(entitysData, vm.entityType, vm.importParams.isUpdate, config).then(function (response) { + importExport.createMultiEntity(entitysData, vm.entityType, vm.importParameters.isUpdate, config).then(function (response) { vm.statistical = response; $mdStepper('import-stepper').next(); }); @@ -206,7 +216,11 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo } function cancel() { - $mdDialog.cancel(); + if($mdStepper('import-stepper').currentStep > 2){ + $mdDialog.hide(); + } else { + $mdDialog.cancel(); + } } function finishExport() { diff --git a/ui/src/app/import-export/import-dialog-csv.tpl.html b/ui/src/app/import-export/import-dialog-csv.tpl.html index add2ede42f..d109b1b5e1 100644 --- a/ui/src/app/import-export/import-dialog-csv.tpl.html +++ b/ui/src/app/import-export/import-dialog-csv.tpl.html @@ -15,19 +15,20 @@ limitations under the License. --> - +

{{ vm.importTitle }}

+
- - + + + @@ -85,25 +86,21 @@ -
- +
+ - + {{delimiter.value}} - - - First line is header - - - - - Update attributes/telemetry - - + + First line contains column names + + + Update attributes/telemetry +
@@ -145,18 +142,15 @@ - + - -
-
-
{{key}}
-
- {{ info }}: {{ infoValue }} -
-
+ +
+

{{vm.statistical.create.device}} new devices were successfully created.

+

{{vm.statistical.update.device}} devices were successfully updated.

+

There was an error creating {{vm.statistical.error.device}} devices.

diff --git a/ui/src/app/import-export/import-dialog.scss b/ui/src/app/import-export/import-dialog.scss index 9a807b67d7..d7fd17a367 100644 --- a/ui/src/app/import-export/import-dialog.scss +++ b/ui/src/app/import-export/import-dialog.scss @@ -56,6 +56,10 @@ $previewSize: 100px !default; .md-stepper-indicator-wrapper{ background-color: transparent; } + +.tb-import-progress{ + margin: 7px 0; +} // //.md-stepper-indicator.md-THEME_NAME-theme.md-completed .md-stepper-number, //.md-stepper-indicator.md-THEME_NAME-theme.md-active .md-stepper-number{ diff --git a/ui/src/app/import-export/import-export.service.js b/ui/src/app/import-export/import-export.service.js index 5c10e48f92..ce9d8dbc81 100644 --- a/ui/src/app/import-export/import-export.service.js +++ b/ui/src/app/import-export/import-export.service.js @@ -25,7 +25,7 @@ import entityAliasesTemplate from '../entity/alias/entity-aliases.tpl.html'; /* eslint-disable no-undef, angular/window-service, angular/document-service */ /*@ngInject*/ -export default function ImportExport($log, $translate, $q, $mdDialog, $document, $http, itembuffer, utils, types, $timeout, deviceService, +export default function ImportExport($log, $translate, $q, $mdDialog, $document, $http, itembuffer, utils, types, $timeout, deviceService, $rootScope, dashboardUtils, entityService, dashboardService, ruleChainService, widgetService, toast, attributeService) { @@ -585,7 +585,7 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document, deferred.resolve(); }, function fail() { - deferred.resolve(); + deferred.reject(); } ); return deferred.promise; @@ -827,6 +827,18 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document, }); return obj1; } + + function qAllWithProgress(promises, progress) { + var total = promises.length; + var now = 0; + promises.forEach(function(p) { + p.then(function() { + now++; + progress(now / total); + }); + }); + return $q.all(promises); + } function createMultiEntity(arrayData, entityType, update, config) { let deferred = $q.defer(); @@ -840,7 +852,10 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document, } break; } - $q.all(allPromise).then(function success(response) { + qAllWithProgress(allPromise, function(progress) { + progress = Math.round(progress * 100); + $rootScope.$broadcast('importCSV-completed', {progress: progress}); + }).then(function success(response) { for (let i = 0; i < response.length; i++){ statisticalInfo = sumObject(statisticalInfo, response[i]); } diff --git a/ui/src/app/import-export/table-columns-assignment.directive.js b/ui/src/app/import-export/table-columns-assignment.directive.js index 22a7a72ce2..8c34ea96c8 100644 --- a/ui/src/app/import-export/table-columns-assignment.directive.js +++ b/ui/src/app/import-export/table-columns-assignment.directive.js @@ -50,6 +50,7 @@ function TableColumnsAssignmentController($scope, types, $timeout) { vm.columnTypes.serverAttribute = types.entityGroup.columnType.serverAttribute; vm.columnTypes.timeseries = types.entityGroup.columnType.timeseries; vm.columnTypes.entityField = types.entityGroup.columnType.entityField; + vm.columnTypes.accessToken = types.entityGroup.columnType.accessToken; break; } @@ -66,6 +67,7 @@ function TableColumnsAssignmentController($scope, types, $timeout) { if (newVal) { var isSelectName = false; var isSelectType = false; + var isSelectCredentials = false; for (var i = 0; i < newVal.length; i++) { if (newVal[i].type === types.entityGroup.columnType.entityField.value && newVal[i].key === types.entityGroup.entityField.name.value) { @@ -75,10 +77,14 @@ function TableColumnsAssignmentController($scope, types, $timeout) { newVal[i].key === types.entityGroup.entityField.type.value) { isSelectType = true; } + if (newVal[i].type === types.entityGroup.columnType.accessToken.value) { + isSelectCredentials = true; + } } $timeout(function () { vm.entityField.name.disable = isSelectName; vm.entityField.type.disable = isSelectType; + vm.columnTypes.accessToken.disable = isSelectCredentials; }); if(isSelectName && isSelectType) { vm.theForm.$setDirty(); @@ -87,10 +93,4 @@ function TableColumnsAssignmentController($scope, types, $timeout) { } } }, true); - // - // $scope.$watch('vm.columns', function(newVal, prevVal) { - // if (newVal && !angular.equals(newVal, prevVal)) { - // vm.theForm.$setDirty(); - // } - // }, true); } diff --git a/ui/src/app/import-export/table-columns-assignment.tpl.html b/ui/src/app/import-export/table-columns-assignment.tpl.html index a51aebdfb3..a1ee9598e7 100644 --- a/ui/src/app/import-export/table-columns-assignment.tpl.html +++ b/ui/src/app/import-export/table-columns-assignment.tpl.html @@ -15,14 +15,14 @@ limitations under the License. --> - + - - + + @@ -32,7 +32,7 @@
  Example value dataColumn typeValueColumn typeValue
- + {{type.name | translate}} @@ -47,8 +47,7 @@ + column.type != vm.columnTypes.accessToken.value">