diff --git a/ui/src/app/api/attribute.service.js b/ui/src/app/api/attribute.service.js index df34674f48..7f235c9d89 100644 --- a/ui/src/app/api/attribute.service.js +++ b/ui/src/app/api/attribute.service.js @@ -238,23 +238,23 @@ function AttributeService($http, $q, $filter, types, telemetryWebsocketService) function success() { deferred.resolve(response.data); }, - function fail() { - deferred.reject(); + function fail(response) { + deferred.reject(response); } ) } else { deferred.resolve(response.data); } - }, function fail() { - deferred.reject(); + }, function fail(response) { + deferred.reject(response); }); } else if (deleteEntityAttributesPromise) { deleteEntityAttributesPromise.then( function success() { deferred.resolve(); }, - function fail() { - deferred.reject(); + function fail(response) { + deferred.reject(response); } ) } else { @@ -277,7 +277,7 @@ function AttributeService($http, $q, $filter, types, telemetryWebsocketService) } var deleteEntityTimeseriesPromise; if (deleteTimeseries.length) { - deleteEntityTimeseriesPromise = deleteEntityTimeseries(entityType, entityId, deleteTimeseries); + deleteEntityTimeseriesPromise = deleteEntityTimeseries(entityType, entityId, deleteTimeseries, config); } if (Object.keys(timeseriesData).length) { var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/timeseries/' + timeseriesScope; @@ -287,23 +287,23 @@ function AttributeService($http, $q, $filter, types, telemetryWebsocketService) function success() { deferred.resolve(response.data); }, - function fail() { - deferred.reject(); + function fail(response) { + deferred.reject(response); } ) } else { deferred.resolve(response.data); } - }, function fail() { - deferred.reject(); + }, function fail(response) { + deferred.reject(response); }); } else if (deleteEntityTimeseriesPromise) { deleteEntityTimeseriesPromise.then( function success() { deferred.resolve(); }, - function fail() { - deferred.reject(); + function fail(response) { + deferred.reject(response); } ) } else { @@ -312,7 +312,8 @@ function AttributeService($http, $q, $filter, types, telemetryWebsocketService) return deferred.promise; } - function deleteEntityAttributes(entityType, entityId, attributeScope, attributes) { + function deleteEntityAttributes(entityType, entityId, attributeScope, attributes, config) { + config = config || {}; var deferred = $q.defer(); var keys = ''; for (var i = 0; i < attributes.length; i++) { @@ -322,15 +323,16 @@ function AttributeService($http, $q, $filter, types, telemetryWebsocketService) keys += attributes[i].key; } var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/' + attributeScope + '?keys=' + keys; - $http.delete(url).then(function success() { + $http.delete(url, config).then(function success() { deferred.resolve(); - }, function fail() { - deferred.reject(); + }, function fail(response) { + deferred.reject(response); }); return deferred.promise; } - function deleteEntityTimeseries(entityType, entityId, timeseries) { + function deleteEntityTimeseries(entityType, entityId, timeseries, config) { + config = config || {}; var deferred = $q.defer(); var keys = ''; for (var i = 0; i < timeseries.length; i++) { @@ -340,10 +342,10 @@ function AttributeService($http, $q, $filter, types, telemetryWebsocketService) keys += timeseries[i].key; } var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/timeseries/delete' + '?keys=' + keys; - $http.delete(url).then(function success() { + $http.delete(url, config).then(function success() { deferred.resolve(); - }, function fail() { - deferred.reject(); + }, function fail(response) { + deferred.reject(response); }); return deferred.promise; } diff --git a/ui/src/app/api/device.service.js b/ui/src/app/api/device.service.js index 3df99cb7cd..c0db363869 100644 --- a/ui/src/app/api/device.service.js +++ b/ui/src/app/api/device.service.js @@ -20,7 +20,7 @@ export default angular.module('thingsboard.api.device', [thingsboardTypes]) .name; /*@ngInject*/ -function DeviceService($http, $q, $window, userService, attributeService, customerService, types) { +function DeviceService($http, $q, $window, userService, attributeService, customerService, types, $timeout) { var service = { assignDeviceToCustomer: assignDeviceToCustomer, @@ -167,25 +167,45 @@ function DeviceService($http, $q, $window, userService, attributeService, custom var url = '/api/device'; $http.post(url, device, config).then(function success(response) { deferred.resolve(response.data); - }, function fail() { - deferred.reject(); + }, function fail(response) { + deferred.reject(response); + }); + return deferred.promise; + } + + function resendRequest(callback){ + const deferred = $q.defer(); + let request = callback(); + request.then(function success(response) { + deferred.resolve(response); + }, function fail(response) { + if (response.status === 429) { + $timeout(function () { + request = callback(); + }, 1000 + Math.random() * 10000); + } else { + deferred.reject(response); + } }); return deferred.promise; } function saveDeviceRelarion(deviceId, deviceRelation, config) { - var deferred = $q.defer(); - var attributesType = Object.keys(types.attributesScope); - var allPromise = []; - var promise = ""; - for (var i = 0; i < attributesType.length; i++) { + const deferred = $q.defer(); + let attributesType = Object.keys(types.attributesScope); + let allPromise = []; + let promise = ""; + for (let i = 0; i < attributesType.length; i++) { if (deviceRelation.attributes[attributesType[i]] && deviceRelation.attributes[attributesType[i]].length !== 0) { - promise = attributeService.saveEntityAttributes(types.entityType.device, deviceId, types.attributesScope[attributesType[i]].value, deviceRelation.attributes[attributesType[i]], config).then(function success() {}); + promise = resendRequest(function () { + return attributeService.saveEntityAttributes(types.entityType.device, deviceId, types.attributesScope[attributesType[i]].value, deviceRelation.attributes[attributesType[i]], config); + }); allPromise.push(promise); } } if (deviceRelation.timeseries.length !== 0) { - promise = attributeService.saveEntityTimeseries(types.entityType.device, deviceId, "time", deviceRelation.timeseries, config).then(function success() { + promise = resendRequest(function () { + return attributeService.saveEntityTimeseries(types.entityType.device, deviceId, "time", deviceRelation.timeseries, config); }); allPromise.push(promise); } @@ -197,26 +217,41 @@ function DeviceService($http, $q, $window, userService, attributeService, custom function saveDeviceParameters(deviceParameters, update, config) { config = config || {}; - var deferred = $q.defer(); - var newDevice = { + const deferred = $q.defer(); + let statisticalInfo = { + create: {}, + update: {}, + error: {} + }; + let newDevice = { name: deviceParameters.name, type: deviceParameters.type }; - saveDevice(newDevice, config).then(function success(response) { + resendRequest(function () { + return saveDevice(newDevice, config); + }).then(function success(response) { + statisticalInfo.create.device = 1; saveDeviceRelarion(response.id.id, deviceParameters, config).then(function success() { - deferred.resolve(); + deferred.resolve(statisticalInfo); }); - }, function fail() { + }, function fail(response) { + console.log(response); // eslint-disable-line if (update) { - findByName(deviceParameters.name, config).then(function success(response) { + resendRequest(function () { + return findByName(deviceParameters.name, config); + }).then(function success(response) { + statisticalInfo.update.device = 1; saveDeviceRelarion(response.id.id, deviceParameters, config).then(function success() { - deferred.resolve(); + deferred.resolve(statisticalInfo); }); + }, function fail() { + statisticalInfo.error.device = newDevice; + deferred.resolve(statisticalInfo); }); } else { - deferred.resolve(); + statisticalInfo.error.device = newDevice; + deferred.resolve(statisticalInfo); } - console.log("error"); // eslint-disable-line }); return deferred.promise; } @@ -374,8 +409,8 @@ function DeviceService($http, $q, $window, userService, attributeService, custom var url = '/api/tenant/devices?deviceName=' + deviceName; $http.get(url, config).then(function success(response) { deferred.resolve(response.data); - }, function fail() { - deferred.reject(); + }, function fail(response) { + deferred.reject(response); }); return deferred.promise; } 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 b45d73b816..873d9c5799 100644 --- a/ui/src/app/import-export/import-dialog-csv.controller.js +++ b/ui/src/app/import-export/import-dialog-csv.controller.js @@ -27,13 +27,15 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo vm.addDevices = addDevices; vm.importParams = { - isUpdate: true + isUpdate: true, + isHeader: true }; vm.importTitle = importTitle; vm.importFileLabel = importFileLabel; vm.columnsParam = []; + vm.parseData = []; vm.entityType = types.entityType.device; vm.columnTypes = {}; @@ -108,17 +110,26 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo } function parseCSVData(importData) { + var columnParam = {}; var config = { delim: vm.importParams.delim, header: vm.importParams.isHeader }; parseData = importExport.convertCSVToJson(importData, config); for (var i = 0; i < parseData.headers.length; i++) { - var columnParam = { - type: types.entityGroup.columnType.serverAttribute.value, - key: vm.importParams.isHeader ? parseData.headers[i] : "", - sampleData: parseData.rows[0][i] - }; + if (vm.importParams.isHeader && parseData.headers[i].search(/^(name|type)$/im) === 0) { + columnParam = { + type: types.entityGroup.columnType.entityField.value, + key: parseData.headers[i].toLowerCase(), + sampleData: parseData.rows[0][i] + }; + } else { + columnParam = { + type: types.entityGroup.columnType.serverAttribute.value, + key: vm.importParams.isHeader ? parseData.headers[i] : "", + sampleData: parseData.rows[0][i] + }; + } vm.columnsParam.push(columnParam); } } @@ -132,6 +143,8 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo // ["Device 3", "test", "test", false, 125], // ["Device 4", "test", "test", false, 126], // ["Device 5", "test", "test", false, 127]]}; + arrayParam = vm.columnsParam; + data = parseData; var arrayData = []; var config = { ignoreErrors: true diff --git a/ui/src/app/import-export/import-export.service.js b/ui/src/app/import-export/import-export.service.js index 6ebfbdeaff..7820532de0 100644 --- a/ui/src/app/import-export/import-export.service.js +++ b/ui/src/app/import-export/import-export.service.js @@ -810,7 +810,7 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document, return parseFloat(str.replace(',', '.')); } if (str.search(/^(true|false)$/im) === 0) { - return str.toLowerCase() === 'true'; + return str === 'true'; } if (str === "") { return null; @@ -822,12 +822,16 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document, config = config || {}; const delim = config.delim || ","; const header = config.header || false; + let result = {}; let csvlines = csvdata.split(/[\r\n]+/); let csvheaders = splitCSV(csvlines[0], delim); + if (csvheaders.length < 2) { + toast.showError('A file should contain at least two columns'); + return -1; + } let csvrows = header ? csvlines.slice(1, csvlines.length) : csvlines; - let result = {}; result.headers = csvheaders; result.rows = []; @@ -839,6 +843,10 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document, break; let rowitems = splitCSV(row, delim); + if (rowitems.length !== result.headers.length) { + toast.showError('Invalid file format. Row:' + (header ? result.rows.length + 2: result.rows.length + 1)); + return -1; + } for (let i = 0; i < rowitems.length; i++) { rowitems[i] = parseStringToFormatJS(rowitems[i]); }