Import export extension configuration
This commit is contained in:
		
							parent
							
								
									32ece471e9
								
							
						
					
					
						commit
						5795e7f259
					
				@ -70,6 +70,7 @@
 | 
			
		||||
        <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.grid.operatingItem().additionalInfo.gateway" md-on-select="vm.grid.triggerResize()" label="{{ 'extension.extensions' | translate }}">
 | 
			
		||||
            <tb-extension-table flex
 | 
			
		||||
                                entity-id="vm.grid.operatingItem().id.id"
 | 
			
		||||
                                entity-name="vm.grid.operatingItem().name"
 | 
			
		||||
                                entity-type="{{vm.types.entityType.device}}">
 | 
			
		||||
            </tb-extension-table>
 | 
			
		||||
        </md-tab>
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,8 @@ export default function ExtensionTableDirective() {
 | 
			
		||||
        scope: true,
 | 
			
		||||
        bindToController: {
 | 
			
		||||
            entityId: '=',
 | 
			
		||||
            entityType: '@'
 | 
			
		||||
            entityType: '@',
 | 
			
		||||
            entityName: '='
 | 
			
		||||
        },
 | 
			
		||||
        controller: ExtensionTableController,
 | 
			
		||||
        controllerAs: 'vm',
 | 
			
		||||
@ -43,7 +44,7 @@ export default function ExtensionTableDirective() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*@ngInject*/
 | 
			
		||||
function ExtensionTableController($scope, $filter, $document, $translate, types, $mdDialog, attributeService, telemetryWebsocketService) {
 | 
			
		||||
function ExtensionTableController($scope, $filter, $document, $translate, types, $mdDialog, attributeService, telemetryWebsocketService, importExport) {
 | 
			
		||||
 | 
			
		||||
    let vm = this;
 | 
			
		||||
 | 
			
		||||
@ -328,4 +329,21 @@ function ExtensionTableController($scope, $filter, $document, $translate, types,
 | 
			
		||||
            return num;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vm.importExtensions = function () {
 | 
			
		||||
        importExport.importExtension({"entityType":vm.entityType, "entityId":vm.entityId, "successFunc":reloadExtensions});
 | 
			
		||||
    };
 | 
			
		||||
    vm.exportExtensions = function () {
 | 
			
		||||
        importExport.exportToPc(vm.extensionsJSON,  vm.entityName + '_configuration.json');
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    vm.exportExtension = function ($event, extension) {
 | 
			
		||||
        if ($event) {
 | 
			
		||||
            $event.stopPropagation();
 | 
			
		||||
        }
 | 
			
		||||
        importExport.exportToPc(extension,  vm.entityName +'_'+ extension.id +'_configuration.json');
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -16,10 +16,19 @@
 | 
			
		||||
@import '../../scss/constants';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.extension-table md-input-container .md-errors-spacer {
 | 
			
		||||
  min-height: 0;
 | 
			
		||||
.extension-table {
 | 
			
		||||
 | 
			
		||||
  md-input-container .md-errors-spacer {
 | 
			
		||||
    min-height: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &.tb-data-table table.md-table tbody tr td.tb-action-cell,
 | 
			
		||||
  &.tb-data-table table.md-table.md-row-select tbody tr td.tb-action-cell {
 | 
			
		||||
    width: 114px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.extension__syncStatus--black {
 | 
			
		||||
  color: #000000!important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -23,6 +23,19 @@
 | 
			
		||||
            <div class="md-toolbar-tools">
 | 
			
		||||
                <span translate>{{ 'extension.extensions' }}</span>
 | 
			
		||||
                <span flex></span>
 | 
			
		||||
 | 
			
		||||
                <md-button class="md-icon-button" ng-click="vm.importExtensions($event)">
 | 
			
		||||
                    <md-icon>file_upload</md-icon>
 | 
			
		||||
                    <md-tooltip md-direction="top">
 | 
			
		||||
                        {{ 'extension.sync.import-extensions-configuration' | translate }}
 | 
			
		||||
                    </md-tooltip>
 | 
			
		||||
                </md-button>
 | 
			
		||||
                <md-button class="md-icon-button" ng-click="vm.exportExtensions()">
 | 
			
		||||
                    <md-icon>file_download</md-icon>
 | 
			
		||||
                    <md-tooltip md-direction="top">
 | 
			
		||||
                        {{ 'extension.sync.export-extensions-configuration' | translate }}
 | 
			
		||||
                    </md-tooltip>
 | 
			
		||||
                </md-button>
 | 
			
		||||
                <md-button class="md-icon-button" ng-click="vm.addExtension($event)">
 | 
			
		||||
                    <md-icon>add</md-icon>
 | 
			
		||||
                    <md-tooltip md-direction="top">
 | 
			
		||||
@ -44,7 +57,7 @@
 | 
			
		||||
            </div>
 | 
			
		||||
        </md-toolbar>
 | 
			
		||||
        <md-toolbar class="md-table-toolbar md-default" ng-show="!vm.selectedExtensions.length
 | 
			
		||||
                                                                 && vm.query.search != null"">
 | 
			
		||||
                                                                 && vm.query.search != null">
 | 
			
		||||
            <div class="md-toolbar-tools">
 | 
			
		||||
                <md-button class="md-icon-button" aria-label="{{ 'action.search' | translate }}">
 | 
			
		||||
                    <md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons">search</md-icon>
 | 
			
		||||
@ -111,6 +124,12 @@
 | 
			
		||||
                    <td md-cell>{{ extension.id }}</td>
 | 
			
		||||
                    <td md-cell>{{ extension.type }}</td>
 | 
			
		||||
                    <td md-cell class="tb-action-cell">
 | 
			
		||||
                        <md-button class="md-icon-button" aria-label="{{ 'action.edit' | translate }}" ng-click="vm.exportExtension($event, extension)">
 | 
			
		||||
                            <md-icon aria-label="{{ 'action.edit' | translate }}" class="material-icons">file_download</md-icon>
 | 
			
		||||
                            <md-tooltip md-direction="top">
 | 
			
		||||
                                {{ 'extension.export-extension' | translate }}
 | 
			
		||||
                            </md-tooltip>
 | 
			
		||||
                        </md-button>
 | 
			
		||||
                        <md-button class="md-icon-button" aria-label="{{ 'action.edit' | translate }}" ng-click="vm.editExtension($event, extension)">
 | 
			
		||||
                            <md-icon aria-label="{{ 'action.edit' | translate }}" class="material-icons">edit</md-icon>
 | 
			
		||||
                            <md-tooltip md-direction="top">
 | 
			
		||||
 | 
			
		||||
@ -24,8 +24,9 @@ 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, itembuffer, utils, types, dashboardUtils,
 | 
			
		||||
                                     entityService, dashboardService, pluginService, ruleService, widgetService, toast) {
 | 
			
		||||
export default function ImportExport($log, $translate, $q, $mdDialog, $document, $http, itembuffer, utils, types,
 | 
			
		||||
                                     dashboardUtils, entityService, dashboardService, pluginService, ruleService,
 | 
			
		||||
                                     widgetService, toast, attributeService) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    var service = {
 | 
			
		||||
@ -40,8 +41,11 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document,
 | 
			
		||||
        exportWidgetType: exportWidgetType,
 | 
			
		||||
        importWidgetType: importWidgetType,
 | 
			
		||||
        exportWidgetsBundle: exportWidgetsBundle,
 | 
			
		||||
        importWidgetsBundle: importWidgetsBundle
 | 
			
		||||
    }
 | 
			
		||||
        importWidgetsBundle: importWidgetsBundle,
 | 
			
		||||
        exportExtension: exportExtension,
 | 
			
		||||
        importExtension: importExtension,
 | 
			
		||||
        exportToPc: exportToPc
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return service;
 | 
			
		||||
 | 
			
		||||
@ -614,6 +618,89 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document,
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function exportExtension(extensionId) {
 | 
			
		||||
 | 
			
		||||
        getExtension(extensionId)
 | 
			
		||||
            .then(
 | 
			
		||||
                function success(extension) {
 | 
			
		||||
                    var name = extension.title;
 | 
			
		||||
                    name = name.toLowerCase().replace(/\W/g,"_");
 | 
			
		||||
                    exportToPc(prepareExport(extension), name + '.json');
 | 
			
		||||
                },
 | 
			
		||||
                function fail(rejection) {
 | 
			
		||||
                    var message = rejection;
 | 
			
		||||
                    if (!message) {
 | 
			
		||||
                        message = $translate.instant('error.unknown-error');
 | 
			
		||||
                    }
 | 
			
		||||
                    toast.showError($translate.instant('extension.export-failed-error', {error: message}));
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        function getExtension(extensionId) {
 | 
			
		||||
            var deferred = $q.defer();
 | 
			
		||||
            var url = '/api/plugins/telemetry/DEVICE/' + extensionId;
 | 
			
		||||
            $http.get(url, null)
 | 
			
		||||
                .then(function success(response) {
 | 
			
		||||
                    deferred.resolve(response.data);
 | 
			
		||||
                }, function fail() {
 | 
			
		||||
                    deferred.reject();
 | 
			
		||||
                });
 | 
			
		||||
            return deferred.promise;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function importExtension(options) {
 | 
			
		||||
        var deferred = $q.defer();
 | 
			
		||||
        openImportDialog(options, 'extension.import-extensions', 'extension.file')
 | 
			
		||||
            .then(
 | 
			
		||||
                function success(extension) {
 | 
			
		||||
                    if (!validateImportedExtension(extension)) {
 | 
			
		||||
                        toast.showError($translate.instant('extension.invalid-file-error'));
 | 
			
		||||
                        deferred.reject();
 | 
			
		||||
                    } else {
 | 
			
		||||
                        attributeService
 | 
			
		||||
                            .saveEntityAttributes(
 | 
			
		||||
                                options.entityType,
 | 
			
		||||
                                options.entityId,
 | 
			
		||||
                                types.attributesScope.shared.value,
 | 
			
		||||
                                [{
 | 
			
		||||
                                    key: "configuration",
 | 
			
		||||
                                    value: angular.toJson(extension)
 | 
			
		||||
                                }]
 | 
			
		||||
                            )
 | 
			
		||||
                            .then(function success() {
 | 
			
		||||
                                options.successFunc();
 | 
			
		||||
                            });
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                function fail() {
 | 
			
		||||
                    deferred.reject();
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
        return deferred.promise;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function validateImportedExtension(configuration) {
 | 
			
		||||
        if (configuration.length) {
 | 
			
		||||
            for (let i = 0; i < configuration.length; i++) {
 | 
			
		||||
                if (angular.isUndefined(configuration[i].configuration) || angular.isUndefined(configuration[i].id )|| angular.isUndefined(configuration[i].type)) {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function processEntityAliases(entityAliases, aliasIds) {
 | 
			
		||||
        var deferred = $q.defer();
 | 
			
		||||
        var missingEntityAliases = {};
 | 
			
		||||
 | 
			
		||||
@ -845,8 +845,16 @@ export default angular.module('thingsboard.locale', [])
 | 
			
		||||
                        "sync": "Sync",
 | 
			
		||||
                        "not-sync": "Not sync",
 | 
			
		||||
                        "last-sync-time": "Last sync time",
 | 
			
		||||
                        "not-available": "Not available"
 | 
			
		||||
                        "not-available": "Not available",
 | 
			
		||||
                        "export-extensions-configuration":"Export extensions configuration",
 | 
			
		||||
                        "import-extensions-configuration":"Import extensions configuration"
 | 
			
		||||
                    },
 | 
			
		||||
 | 
			
		||||
                    "import-extensions": "Import extensions",
 | 
			
		||||
                    "import-extension": "Import extension",
 | 
			
		||||
                    "export-extension": "Export extension",
 | 
			
		||||
                    "file": "Extensions file",
 | 
			
		||||
                    "invalid-file-error": "Invalid extension file"
 | 
			
		||||
                },
 | 
			
		||||
                "fullscreen": {
 | 
			
		||||
                    "expand": "Expand to fullscreen",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user