/* * Copyright © 2016 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 deviceAliasesTemplate from './device-aliases.tpl.html'; import dashboardBackgroundTemplate from './dashboard-settings.tpl.html'; import addWidgetTemplate from './add-widget.tpl.html'; /* eslint-enable import/no-unresolved, import/default */ /*@ngInject*/ export default function DashboardController(types, widgetService, userService, dashboardService, itembuffer, hotkeys, $window, $rootScope, $scope, $state, $stateParams, $mdDialog, $timeout, $document, $q, $translate, $filter) { var user = userService.getCurrentUser(); var vm = this; vm.dashboard = null; vm.editingWidget = null; vm.editingWidgetIndex = null; vm.editingWidgetSubtitle = null; vm.forceDashboardMobileMode = false; vm.isAddingWidget = false; vm.isEdit = false; vm.isEditingWidget = false; vm.latestWidgetTypes = []; vm.timeseriesWidgetTypes = []; vm.rpcWidgetTypes = []; vm.widgetEditMode = $state.$current.data.widgetEditMode; vm.widgets = []; vm.addWidget = addWidget; vm.addWidgetFromType = addWidgetFromType; vm.dashboardInited = dashboardInited; vm.dashboardInitFailed = dashboardInitFailed; vm.widgetMouseDown = widgetMouseDown; vm.widgetClicked = widgetClicked; vm.prepareDashboardContextMenu = prepareDashboardContextMenu; vm.prepareWidgetContextMenu = prepareWidgetContextMenu; vm.editWidget = editWidget; vm.isTenantAdmin = isTenantAdmin; vm.loadDashboard = loadDashboard; vm.noData = noData; vm.onAddWidgetClosed = onAddWidgetClosed; vm.onEditWidgetClosed = onEditWidgetClosed; vm.openDeviceAliases = openDeviceAliases; vm.openDashboardSettings = openDashboardSettings; vm.removeWidget = removeWidget; vm.saveDashboard = saveDashboard; vm.saveWidget = saveWidget; vm.toggleDashboardEditMode = toggleDashboardEditMode; vm.onRevertWidgetEdit = onRevertWidgetEdit; vm.helpLinkIdForWidgetType = helpLinkIdForWidgetType; vm.displayTitle = displayTitle; vm.widgetsBundle; $scope.$watch('vm.widgetsBundle', function (newVal, prevVal) { if (newVal !== prevVal && !vm.widgetEditMode) { loadWidgetLibrary(); } }); function loadWidgetLibrary() { vm.latestWidgetTypes = []; vm.timeseriesWidgetTypes = []; vm.rpcWidgetTypes = []; if (vm.widgetsBundle) { var bundleAlias = vm.widgetsBundle.alias; var isSystem = vm.widgetsBundle.tenantId.id === types.id.nullUid; widgetService.getBundleWidgetTypes(bundleAlias, isSystem).then( function (widgetTypes) { widgetTypes = $filter('orderBy')(widgetTypes, ['-name']); var top = 0; var sizeY = 0; if (widgetTypes.length > 0) { loadNext(0); } function loadNextOrComplete(i) { i++; if (i < widgetTypes.length) { loadNext(i); } } function loadNext(i) { var widgetType = widgetTypes[i]; var widgetTypeInfo = widgetService.toWidgetInfo(widgetType); var widget = { isSystemType: isSystem, bundleAlias: bundleAlias, typeAlias: widgetTypeInfo.alias, type: widgetTypeInfo.type, title: widgetTypeInfo.widgetName, sizeX: widgetTypeInfo.sizeX, sizeY: widgetTypeInfo.sizeY, row: top, col: 0, config: angular.fromJson(widgetTypeInfo.defaultConfig) }; widget.config.title = widgetTypeInfo.widgetName; if (widgetTypeInfo.type === types.widgetType.timeseries.value) { vm.timeseriesWidgetTypes.push(widget); } else if (widgetTypeInfo.type === types.widgetType.latest.value) { vm.latestWidgetTypes.push(widget); } else if (widgetTypeInfo.type === types.widgetType.rpc.value) { vm.rpcWidgetTypes.push(widget); } top += sizeY; loadNextOrComplete(i); } } ); } } function loadDashboard() { var deferred = $q.defer(); if (vm.widgetEditMode) { $timeout(function () { vm.widgets = [{ isSystemType: true, bundleAlias: 'customWidgetBundle', typeAlias: 'customWidget', type: $rootScope.editWidgetInfo.type, title: 'My widget', sizeX: $rootScope.editWidgetInfo.sizeX * 2, sizeY: $rootScope.editWidgetInfo.sizeY * 2, row: 2, col: 4, config: angular.fromJson($rootScope.editWidgetInfo.defaultConfig) }]; vm.widgets[0].config.title = vm.widgets[0].config.title || $rootScope.editWidgetInfo.widgetName; deferred.resolve(); var parentScope = $window.parent.angular.element($window.frameElement).scope(); parentScope.$root.$broadcast('widgetEditModeInited'); parentScope.$root.$apply(); $scope.$watch('vm.widgets', function () { var widget = vm.widgets[0]; parentScope.$root.$broadcast('widgetEditUpdated', widget); parentScope.$root.$apply(); }, true); }); } else { dashboardService.getDashboard($stateParams.dashboardId) .then(function success(dashboard) { vm.dashboard = dashboard; if (vm.dashboard.configuration == null) { vm.dashboard.configuration = {widgets: [], deviceAliases: {}}; } if (angular.isUndefined(vm.dashboard.configuration.widgets)) { vm.dashboard.configuration.widgets = []; } if (angular.isUndefined(vm.dashboard.configuration.deviceAliases)) { vm.dashboard.configuration.deviceAliases = {}; } vm.widgets = vm.dashboard.configuration.widgets; deferred.resolve(); }, function fail(e) { deferred.reject(e); }); } return deferred.promise; } function dashboardInitFailed() { var parentScope = $window.parent.angular.element($window.frameElement).scope(); parentScope.$emit('widgetEditModeInited'); parentScope.$apply(); } function dashboardInited(dashboard) { vm.dashboardContainer = dashboard; initHotKeys(); } function isTenantAdmin() { return user.authority === 'TENANT_ADMIN'; } function noData() { return vm.widgets.length == 0; } function openDeviceAliases($event) { var aliasToWidgetsMap = {}; var widgetsTitleList; for (var w in vm.widgets) { var widget = vm.widgets[w]; if (widget.type === types.widgetType.rpc.value) { if (widget.config.targetDeviceAliasIds && widget.config.targetDeviceAliasIds.length > 0) { var targetDeviceAliasId = widget.config.targetDeviceAliasIds[0]; widgetsTitleList = aliasToWidgetsMap[targetDeviceAliasId]; if (!widgetsTitleList) { widgetsTitleList = []; 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 = aliasToWidgetsMap[datasource.deviceAliasId]; if (!widgetsTitleList) { widgetsTitleList = []; aliasToWidgetsMap[datasource.deviceAliasId] = widgetsTitleList; } widgetsTitleList.push(widget.config.title); } } } } $mdDialog.show({ controller: 'DeviceAliasesController', controllerAs: 'vm', templateUrl: deviceAliasesTemplate, locals: { deviceAliases: angular.copy(vm.dashboard.configuration.deviceAliases), aliasToWidgetsMap: aliasToWidgetsMap, isSingleDevice: false, singleDeviceAlias: null }, parent: angular.element($document[0].body), skipHide: true, fullscreen: true, targetEvent: $event }).then(function (deviceAliases) { vm.dashboard.configuration.deviceAliases = deviceAliases; }, function () { }); } function openDashboardSettings($event) { $mdDialog.show({ controller: 'DashboardSettingsController', controllerAs: 'vm', templateUrl: dashboardBackgroundTemplate, locals: { gridSettings: angular.copy(vm.dashboard.configuration.gridSettings) }, parent: angular.element($document[0].body), skipHide: true, fullscreen: true, targetEvent: $event }).then(function (gridSettings) { vm.dashboard.configuration.gridSettings = gridSettings; }, function () { }); } function editWidget($event, widget) { $event.stopPropagation(); var newEditingIndex = vm.widgets.indexOf(widget); if (vm.editingWidgetIndex === newEditingIndex) { $timeout(onEditWidgetClosed()); } else { var transition = !vm.forceDashboardMobileMode; vm.editingWidgetIndex = vm.widgets.indexOf(widget); vm.editingWidget = angular.copy(widget); vm.editingWidgetSubtitle = widgetService.getInstantWidgetInfo(vm.editingWidget).widgetName; vm.forceDashboardMobileMode = true; vm.isEditingWidget = true; if (vm.dashboardContainer) { var delayOffset = transition ? 350 : 0; var delay = transition ? 400 : 300; $timeout(function () { vm.dashboardContainer.highlightWidget(widget, delay); }, delayOffset, false); } } } function widgetMouseDown($event, widget) { if (vm.isEdit && !vm.isEditingWidget) { vm.dashboardContainer.selectWidget(widget, 0); } } function widgetClicked($event, widget) { if (vm.isEditingWidget) { editWidget($event, widget); } } function initHotKeys() { $translate(['action.copy', 'action.paste', 'action.delete']).then(function (translations) { hotkeys.bindTo($scope) .add({ combo: 'ctrl+c', description: translations['action.copy'], allowIn: ['INPUT', 'SELECT', 'TEXTAREA'], callback: function (event) { if (vm.isEdit && !vm.isEditingWidget && !vm.widgetEditMode) { var widget = vm.dashboardContainer.getSelectedWidget(); if (widget) { event.preventDefault(); copyWidget(event, widget); } } } }) .add({ combo: 'ctrl+v', description: translations['action.paste'], allowIn: ['INPUT', 'SELECT', 'TEXTAREA'], callback: function (event) { if (vm.isEdit && !vm.isEditingWidget && !vm.widgetEditMode) { if (itembuffer.hasWidget()) { event.preventDefault(); pasteWidget(event); } } } }) .add({ combo: 'ctrl+x', description: translations['action.delete'], allowIn: ['INPUT', 'SELECT', 'TEXTAREA'], callback: function (event) { if (vm.isEdit && !vm.isEditingWidget && !vm.widgetEditMode) { var widget = vm.dashboardContainer.getSelectedWidget(); if (widget) { event.preventDefault(); removeWidget(event, widget); } } } }); }); } function prepareDashboardContextMenu() { var dashboardContextActions = []; if (vm.isEdit && !vm.isEditingWidget && !vm.widgetEditMode) { dashboardContextActions.push( { action: openDashboardSettings, enabled: true, value: "dashboard.settings", icon: "settings" } ); dashboardContextActions.push( { action: openDeviceAliases, enabled: true, value: "device.aliases", icon: "devices_other" } ); dashboardContextActions.push( { action: pasteWidget, enabled: itembuffer.hasWidget(), value: "action.paste", icon: "content_paste", shortcut: "M-V" } ); } return dashboardContextActions; } function pasteWidget($event) { var pos = vm.dashboardContainer.getEventGridPosition($event); itembuffer.pasteWidget(vm.dashboard, pos); } function prepareWidgetContextMenu() { var widgetContextActions = []; if (vm.isEdit && !vm.isEditingWidget) { widgetContextActions.push( { action: editWidget, enabled: true, value: "action.edit", icon: "edit" } ); if (!vm.widgetEditMode) { widgetContextActions.push( { action: copyWidget, enabled: true, value: "action.copy", icon: "content_copy", shortcut: "M-C" } ); widgetContextActions.push( { action: removeWidget, enabled: true, value: "action.delete", icon: "clear", shortcut: "M-X" } ); } } return widgetContextActions; } function copyWidget($event, widget) { var aliasesInfo = { datasourceAliases: {}, targetDeviceAliases: {} }; var originalColumns = 24; if (vm.dashboard.configuration.gridSettings && vm.dashboard.configuration.gridSettings.columns) { originalColumns = vm.dashboard.configuration.gridSettings.columns; } if (widget.config && vm.dashboard.configuration && vm.dashboard.configuration.deviceAliases) { var deviceAlias; if (widget.config.datasources) { for (var i=0;i