Showing
27 changed files
with
595 additions
and
95 deletions
@@ -171,6 +171,48 @@ export default class Subscription { | @@ -171,6 +171,48 @@ export default class Subscription { | ||
171 | return deferred.promise; | 171 | return deferred.promise; |
172 | } | 172 | } |
173 | 173 | ||
174 | + getFirstEntityInfo() { | ||
175 | + var entityId; | ||
176 | + var entityName; | ||
177 | + if (this.type === this.ctx.types.widgetType.rpc.value) { | ||
178 | + if (this.targetDeviceId) { | ||
179 | + entityId = { | ||
180 | + entityType: this.ctx.entityType.device, | ||
181 | + id: this.targetDeviceId | ||
182 | + } | ||
183 | + entityName = this.targetDeviceName; | ||
184 | + } | ||
185 | + } else if (this.type == this.ctx.types.widgetType.alarm.value) { | ||
186 | + if (this.alarmSource && this.alarmSource.entityType && this.alarmSource.entityId) { | ||
187 | + entityId = { | ||
188 | + entityType: this.alarmSource.entityType, | ||
189 | + id: this.alarmSource.entityId | ||
190 | + } | ||
191 | + entityName = this.alarmSource.entityName; | ||
192 | + } | ||
193 | + } else { | ||
194 | + for (var i=0;i<this.datasources.length;i++) { | ||
195 | + var datasource = this.datasources[i]; | ||
196 | + if (datasource && datasource.entityType && datasource.entityId) { | ||
197 | + entityId = { | ||
198 | + entityType: datasource.entityType, | ||
199 | + id: datasource.entityId | ||
200 | + } | ||
201 | + entityName = datasource.entityName; | ||
202 | + break; | ||
203 | + } | ||
204 | + } | ||
205 | + } | ||
206 | + if (entityId) { | ||
207 | + return { | ||
208 | + entityId: entityId, | ||
209 | + entityName: entityName | ||
210 | + }; | ||
211 | + } else { | ||
212 | + return null; | ||
213 | + } | ||
214 | + } | ||
215 | + | ||
174 | initAlarmSubscription() { | 216 | initAlarmSubscription() { |
175 | var deferred = this.ctx.$q.defer(); | 217 | var deferred = this.ctx.$q.defer(); |
176 | if (!this.ctx.aliasController) { | 218 | if (!this.ctx.aliasController) { |
@@ -342,6 +384,7 @@ export default class Subscription { | @@ -342,6 +384,7 @@ export default class Subscription { | ||
342 | function success(aliasInfo) { | 384 | function success(aliasInfo) { |
343 | if (aliasInfo.currentEntity && aliasInfo.currentEntity.entityType == subscription.ctx.types.entityType.device) { | 385 | if (aliasInfo.currentEntity && aliasInfo.currentEntity.entityType == subscription.ctx.types.entityType.device) { |
344 | subscription.targetDeviceId = aliasInfo.currentEntity.id; | 386 | subscription.targetDeviceId = aliasInfo.currentEntity.id; |
387 | + subscription.targetDeviceName = aliasInfo.currentEntity.name; | ||
345 | if (subscription.targetDeviceId) { | 388 | if (subscription.targetDeviceId) { |
346 | subscription.rpcEnabled = true; | 389 | subscription.rpcEnabled = true; |
347 | } else { | 390 | } else { |
@@ -626,7 +626,7 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, $tr | @@ -626,7 +626,7 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, $tr | ||
626 | } | 626 | } |
627 | for (var actionSourceId in types.widgetActionSources) { | 627 | for (var actionSourceId in types.widgetActionSources) { |
628 | result.actionSources[actionSourceId] = angular.copy(types.widgetActionSources[actionSourceId]); | 628 | result.actionSources[actionSourceId] = angular.copy(types.widgetActionSources[actionSourceId]); |
629 | - result.actionSources[actionSourceId].name = $translate.instant(result.actionSources[actionSourceId].name); | 629 | + result.actionSources[actionSourceId].name = $translate.instant(result.actionSources[actionSourceId].name) + ''; |
630 | } | 630 | } |
631 | 631 | ||
632 | return result; | 632 | return result; |
@@ -400,8 +400,9 @@ export default angular.module('thingsboard.types', []) | @@ -400,8 +400,9 @@ export default angular.module('thingsboard.types', []) | ||
400 | } | 400 | } |
401 | }, | 401 | }, |
402 | widgetActionSources: { | 402 | widgetActionSources: { |
403 | - 'headerButton': { | 403 | + headerButton: { |
404 | name: 'widget-action.header-button', | 404 | name: 'widget-action.header-button', |
405 | + value: 'headerButton', | ||
405 | multiple: true | 406 | multiple: true |
406 | } | 407 | } |
407 | }, | 408 | }, |
@@ -38,7 +38,11 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | @@ -38,7 +38,11 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | ||
38 | materialColors = [], | 38 | materialColors = [], |
39 | materialIcons = []; | 39 | materialIcons = []; |
40 | 40 | ||
41 | - var commonUsedMaterialIcons = [ 'more_horiz', 'close', 'play_arrow' ]; | 41 | + var commonMaterialIcons = [ 'more_horiz', 'more_vert', 'open_in_new', 'visibility', 'play_arrow', 'arrow_back', 'arrow_downward', |
42 | + 'arrow_forward', 'arrow_upwards', 'close', 'refresh', 'menu', 'show_chart', 'multiline_chart', 'pie_chart', 'insert_chart', 'people', | ||
43 | + 'person', 'domain', 'devices_other', 'now_widgets', 'dashboards', 'map', 'pin_drop', 'my_location', 'extension', 'search', | ||
44 | + 'settings', 'notifications', 'notifications_active', 'info', 'info_outline', 'warning', 'list', 'file_download', 'import_export', | ||
45 | + 'share', 'add', 'edit', 'done' ]; | ||
42 | 46 | ||
43 | predefinedFunctions['Sin'] = "return Math.round(1000*Math.sin(time/5000));"; | 47 | predefinedFunctions['Sin'] = "return Math.round(1000*Math.sin(time/5000));"; |
44 | predefinedFunctions['Cos'] = "return Math.round(1000*Math.cos(time/5000));"; | 48 | predefinedFunctions['Cos'] = "return Math.round(1000*Math.cos(time/5000));"; |
@@ -148,7 +152,8 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | @@ -148,7 +152,8 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | ||
148 | validateDatasources: validateDatasources, | 152 | validateDatasources: validateDatasources, |
149 | createKey: createKey, | 153 | createKey: createKey, |
150 | createLabelFromDatasource: createLabelFromDatasource, | 154 | createLabelFromDatasource: createLabelFromDatasource, |
151 | - insertVariable: insertVariable | 155 | + insertVariable: insertVariable, |
156 | + customTranslation: customTranslation | ||
152 | } | 157 | } |
153 | 158 | ||
154 | return service; | 159 | return service; |
@@ -188,7 +193,7 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | @@ -188,7 +193,7 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | ||
188 | } | 193 | } |
189 | 194 | ||
190 | function getCommonMaterialIcons() { | 195 | function getCommonMaterialIcons() { |
191 | - return commonUsedMaterialIcons; | 196 | + return commonMaterialIcons; |
192 | } | 197 | } |
193 | 198 | ||
194 | function genMaterialColor(str) { | 199 | function genMaterialColor(str) { |
@@ -469,4 +474,16 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | @@ -469,4 +474,16 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | ||
469 | return result; | 474 | return result; |
470 | } | 475 | } |
471 | 476 | ||
477 | + function customTranslation(translationValue, defaultValue) { | ||
478 | + var result = ''; | ||
479 | + var translationId = types.translate.customTranslationsPrefix + translationValue; | ||
480 | + var translation = $translate.instant(translationId); | ||
481 | + if (translation != translationId) { | ||
482 | + result = translation + ''; | ||
483 | + } else { | ||
484 | + result = defaultValue; | ||
485 | + } | ||
486 | + return result; | ||
487 | + } | ||
488 | + | ||
472 | } | 489 | } |
@@ -87,23 +87,32 @@ function DashboardAutocomplete($compile, $templateCache, $q, dashboardService, u | @@ -87,23 +87,32 @@ function DashboardAutocomplete($compile, $templateCache, $q, dashboardService, u | ||
87 | dashboardService.getDashboardInfo(ngModelCtrl.$viewValue).then( | 87 | dashboardService.getDashboardInfo(ngModelCtrl.$viewValue).then( |
88 | function success(dashboard) { | 88 | function success(dashboard) { |
89 | scope.dashboard = dashboard; | 89 | scope.dashboard = dashboard; |
90 | + startWatchers(); | ||
90 | }, | 91 | }, |
91 | function fail() { | 92 | function fail() { |
92 | scope.dashboard = null; | 93 | scope.dashboard = null; |
94 | + scope.updateView(); | ||
95 | + startWatchers(); | ||
93 | } | 96 | } |
94 | ); | 97 | ); |
95 | } else { | 98 | } else { |
96 | scope.dashboard = null; | 99 | scope.dashboard = null; |
100 | + startWatchers(); | ||
97 | } | 101 | } |
98 | } | 102 | } |
99 | 103 | ||
100 | - scope.$watch('dashboard', function () { | ||
101 | - scope.updateView(); | ||
102 | - }); | ||
103 | - | ||
104 | - scope.$watch('disabled', function () { | ||
105 | - scope.updateView(); | ||
106 | - }); | 104 | + function startWatchers() { |
105 | + scope.$watch('dashboard', function (newVal, prevVal) { | ||
106 | + if (!angular.equals(newVal, prevVal)) { | ||
107 | + scope.updateView(); | ||
108 | + } | ||
109 | + }); | ||
110 | + scope.$watch('disabled', function (newVal, prevVal) { | ||
111 | + if (!angular.equals(newVal, prevVal)) { | ||
112 | + scope.updateView(); | ||
113 | + } | ||
114 | + }); | ||
115 | + } | ||
107 | 116 | ||
108 | if (scope.selectFirstDashboard) { | 117 | if (scope.selectFirstDashboard) { |
109 | var pageLink = {limit: 1, textSearch: ''}; | 118 | var pageLink = {limit: 1, textSearch: ''}; |
@@ -111,6 +120,7 @@ function DashboardAutocomplete($compile, $templateCache, $q, dashboardService, u | @@ -111,6 +120,7 @@ function DashboardAutocomplete($compile, $templateCache, $q, dashboardService, u | ||
111 | var dashboards = result.data; | 120 | var dashboards = result.data; |
112 | if (dashboards.length > 0) { | 121 | if (dashboards.length > 0) { |
113 | scope.dashboard = dashboards[0]; | 122 | scope.dashboard = dashboards[0]; |
123 | + scope.updateView(); | ||
114 | } | 124 | } |
115 | }, function fail() { | 125 | }, function fail() { |
116 | }); | 126 | }); |
@@ -187,6 +187,7 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $ | @@ -187,6 +187,7 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $ | ||
187 | vm.showWidgetActions = showWidgetActions; | 187 | vm.showWidgetActions = showWidgetActions; |
188 | vm.widgetTitleStyle = widgetTitleStyle; | 188 | vm.widgetTitleStyle = widgetTitleStyle; |
189 | vm.widgetTitle = widgetTitle; | 189 | vm.widgetTitle = widgetTitle; |
190 | + vm.customWidgetHeaderActions = customWidgetHeaderActions; | ||
190 | vm.widgetActions = widgetActions; | 191 | vm.widgetActions = widgetActions; |
191 | vm.dropWidgetShadow = dropWidgetShadow; | 192 | vm.dropWidgetShadow = dropWidgetShadow; |
192 | vm.enableWidgetFullscreen = enableWidgetFullscreen; | 193 | vm.enableWidgetFullscreen = enableWidgetFullscreen; |
@@ -875,6 +876,15 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $ | @@ -875,6 +876,15 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $ | ||
875 | } | 876 | } |
876 | } | 877 | } |
877 | 878 | ||
879 | + function customWidgetHeaderActions(widget) { | ||
880 | + var ctx = widgetContext(widget); | ||
881 | + if (ctx && ctx.customHeaderActions && ctx.customHeaderActions.length) { | ||
882 | + return ctx.customHeaderActions; | ||
883 | + } else { | ||
884 | + return []; | ||
885 | + } | ||
886 | + } | ||
887 | + | ||
878 | function widgetActions(widget) { | 888 | function widgetActions(widget) { |
879 | var ctx = widgetContext(widget); | 889 | var ctx = widgetContext(widget); |
880 | if (ctx && ctx.widgetActions && ctx.widgetActions.length) { | 890 | if (ctx && ctx.widgetActions && ctx.widgetActions.length) { |
@@ -52,6 +52,16 @@ | @@ -52,6 +52,16 @@ | ||
52 | <tb-timewindow aggregation="{{vm.hasAggregation(widget)}}" ng-if="vm.hasTimewindow(widget)" ng-model="widget.config.timewindow"></tb-timewindow> | 52 | <tb-timewindow aggregation="{{vm.hasAggregation(widget)}}" ng-if="vm.hasTimewindow(widget)" ng-model="widget.config.timewindow"></tb-timewindow> |
53 | </div> | 53 | </div> |
54 | <div class="tb-widget-actions" layout="row" layout-align="start center" ng-show="vm.showWidgetActions(widget)" tb-mousedown="$event.stopPropagation()"> | 54 | <div class="tb-widget-actions" layout="row" layout-align="start center" ng-show="vm.showWidgetActions(widget)" tb-mousedown="$event.stopPropagation()"> |
55 | + <md-button ng-repeat="action in vm.customWidgetHeaderActions(widget)" | ||
56 | + aria-label="{{action.displayName}}" | ||
57 | + ng-show="!vm.isEdit" | ||
58 | + ng-click="action.onAction($event)" | ||
59 | + class="md-icon-button"> | ||
60 | + <md-tooltip md-direction="top"> | ||
61 | + {{action.displayName}} | ||
62 | + </md-tooltip> | ||
63 | + <ng-md-icon size="20" icon="{{action.icon}}"></ng-md-icon> | ||
64 | + </md-button> | ||
55 | <md-button ng-repeat="action in vm.widgetActions(widget)" | 65 | <md-button ng-repeat="action in vm.widgetActions(widget)" |
56 | aria-label="{{ action.name | translate }}" | 66 | aria-label="{{ action.name | translate }}" |
57 | ng-show="!vm.isEdit && action.show" | 67 | ng-show="!vm.isEdit && action.show" |
@@ -14,6 +14,8 @@ | @@ -14,6 +14,8 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | +import './material-icon-select.scss'; | ||
18 | + | ||
17 | import MaterialIconsDialogController from './material-icons-dialog.controller'; | 19 | import MaterialIconsDialogController from './material-icons-dialog.controller'; |
18 | 20 | ||
19 | /* eslint-disable import/no-unresolved, import/default */ | 21 | /* eslint-disable import/no-unresolved, import/default */ |
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +.tb-material-icon-select { | ||
18 | + md-icon { | ||
19 | + padding: 4px; | ||
20 | + margin: 8px 4px 4px; | ||
21 | + cursor: pointer; | ||
22 | + border: solid 1px rgba(0,0,0,0.27); | ||
23 | + } | ||
24 | + md-input-container { | ||
25 | + margin-bottom: 0px; | ||
26 | + } | ||
27 | +} |
@@ -15,12 +15,10 @@ | @@ -15,12 +15,10 @@ | ||
15 | limitations under the License. | 15 | limitations under the License. |
16 | 16 | ||
17 | --> | 17 | --> |
18 | -<div layout="row"> | 18 | +<div class="tb-material-icon-select" layout="row"> |
19 | <md-icon class="material-icons" ng-click="openIconDialog($event)">{{icon}}</md-icon> | 19 | <md-icon class="material-icons" ng-click="openIconDialog($event)">{{icon}}</md-icon> |
20 | <md-input-container flex> | 20 | <md-input-container flex> |
21 | - <md-input-container class="md-block"> | ||
22 | - <label translate>icon.icon</label> | ||
23 | - <input ng-click="openIconDialog($event)" ng-model="icon"> | ||
24 | - </md-input-container> | 21 | + <label translate>icon.icon</label> |
22 | + <input ng-mousedown="openIconDialog($event)" ng-model="icon"> | ||
25 | </md-input-container> | 23 | </md-input-container> |
26 | </div> | 24 | </div> |
@@ -42,7 +42,8 @@ function ManageWidgetActions() { | @@ -42,7 +42,8 @@ function ManageWidgetActions() { | ||
42 | scope: true, | 42 | scope: true, |
43 | bindToController: { | 43 | bindToController: { |
44 | actionSources: '=', | 44 | actionSources: '=', |
45 | - widgetActions: '=' | 45 | + widgetActions: '=', |
46 | + fetchDashboardStates: '&', | ||
46 | }, | 47 | }, |
47 | controller: ManageWidgetActionsController, | 48 | controller: ManageWidgetActionsController, |
48 | controllerAs: 'vm', | 49 | controllerAs: 'vm', |
@@ -55,7 +56,7 @@ function ManageWidgetActions() { | @@ -55,7 +56,7 @@ function ManageWidgetActions() { | ||
55 | 56 | ||
56 | /*@ngInject*/ | 57 | /*@ngInject*/ |
57 | function ManageWidgetActionsController($rootScope, $scope, $document, $mdDialog, $q, $filter, | 58 | function ManageWidgetActionsController($rootScope, $scope, $document, $mdDialog, $q, $filter, |
58 | - $translate, $timeout, types) { | 59 | + $translate, $timeout, utils, types) { |
59 | 60 | ||
60 | let vm = this; | 61 | let vm = this; |
61 | 62 | ||
@@ -165,12 +166,30 @@ function ManageWidgetActionsController($rootScope, $scope, $document, $mdDialog, | @@ -165,12 +166,30 @@ function ManageWidgetActionsController($rootScope, $scope, $document, $mdDialog, | ||
165 | if (!isAdd) { | 166 | if (!isAdd) { |
166 | prevActionId = action.id; | 167 | prevActionId = action.id; |
167 | } | 168 | } |
169 | + var availableActionSources = {}; | ||
170 | + for (var id in vm.actionSources) { | ||
171 | + var actionSource = vm.actionSources[id]; | ||
172 | + if (actionSource.multiple) { | ||
173 | + availableActionSources[id] = actionSource; | ||
174 | + } else { | ||
175 | + if (!isAdd && action.actionSourceId == id) { | ||
176 | + availableActionSources[id] = actionSource; | ||
177 | + } else { | ||
178 | + var result = $filter('filter')(vm.allActions, {actionSourceId: id}); | ||
179 | + if (!result || !result.length) { | ||
180 | + availableActionSources[id] = actionSource; | ||
181 | + } | ||
182 | + } | ||
183 | + } | ||
184 | + } | ||
168 | $mdDialog.show({ | 185 | $mdDialog.show({ |
169 | controller: 'WidgetActionDialogController', | 186 | controller: 'WidgetActionDialogController', |
170 | controllerAs: 'vm', | 187 | controllerAs: 'vm', |
171 | templateUrl: widgetActionDialogTemplate, | 188 | templateUrl: widgetActionDialogTemplate, |
172 | parent: angular.element($document[0].body), | 189 | parent: angular.element($document[0].body), |
173 | - locals: {isAdd: isAdd, actionSources: vm.actionSources, action: angular.copy(action)}, | 190 | + locals: {isAdd: isAdd, fetchDashboardStates: vm.fetchDashboardStates, |
191 | + actionSources: availableActionSources, widgetActions: vm.widgetActions, | ||
192 | + action: angular.copy(action)}, | ||
174 | skipHide: true, | 193 | skipHide: true, |
175 | fullscreen: true, | 194 | fullscreen: true, |
176 | targetEvent: $event | 195 | targetEvent: $event |
@@ -189,7 +208,8 @@ function ManageWidgetActionsController($rootScope, $scope, $document, $mdDialog, | @@ -189,7 +208,8 @@ function ManageWidgetActionsController($rootScope, $scope, $document, $mdDialog, | ||
189 | } | 208 | } |
190 | 209 | ||
191 | function saveAction(action, prevActionId) { | 210 | function saveAction(action, prevActionId) { |
192 | - action.actionSourceName = vm.actionSources[action.actionSourceId].name; | 211 | + var actionSourceName = vm.actionSources[action.actionSourceId].name; |
212 | + action.actionSourceName = utils.customTranslation(actionSourceName, actionSourceName); | ||
193 | action.typeName = $translate.instant(types.widgetActionTypes[action.type].name); | 213 | action.typeName = $translate.instant(types.widgetActionTypes[action.type].name); |
194 | var actionSourceId = action.actionSourceId; | 214 | var actionSourceId = action.actionSourceId; |
195 | var widgetAction = angular.copy(action); | 215 | var widgetAction = angular.copy(action); |
@@ -227,15 +247,10 @@ function ManageWidgetActionsController($rootScope, $scope, $document, $mdDialog, | @@ -227,15 +247,10 @@ function ManageWidgetActionsController($rootScope, $scope, $document, $mdDialog, | ||
227 | var actionSourceActions = vm.widgetActions[actionSourceId]; | 247 | var actionSourceActions = vm.widgetActions[actionSourceId]; |
228 | for (var i=0;i<actionSourceActions.length;i++) { | 248 | for (var i=0;i<actionSourceActions.length;i++) { |
229 | var actionSourceAction = actionSourceActions[i]; | 249 | var actionSourceAction = actionSourceActions[i]; |
230 | - var action = { | ||
231 | - id: actionSourceAction.id, | ||
232 | - actionSourceId: actionSourceId, | ||
233 | - actionSourceName: actionSource.name, | ||
234 | - name: actionSourceAction.name, | ||
235 | - icon: actionSourceAction.icon, | ||
236 | - type: actionSourceAction.type, | ||
237 | - typeName: $translate.instant(types.widgetActionTypes[actionSourceAction.type].name) | ||
238 | - }; | 250 | + var action = angular.copy(actionSourceAction); |
251 | + action.actionSourceId = actionSourceId; | ||
252 | + action.actionSourceName = utils.customTranslation(actionSource.name, actionSource.name); | ||
253 | + action.typeName = $translate.instant(types.widgetActionTypes[actionSourceAction.type].name); | ||
239 | vm.allActions.push(action); | 254 | vm.allActions.push(action); |
240 | } | 255 | } |
241 | } | 256 | } |
@@ -15,14 +15,21 @@ | @@ -15,14 +15,21 @@ | ||
15 | */ | 15 | */ |
16 | 16 | ||
17 | /*@ngInject*/ | 17 | /*@ngInject*/ |
18 | -export default function WidgetActionDialogController($scope, $mdDialog, types, utils, isAdd, actionSources, action) { | 18 | +export default function WidgetActionDialogController($scope, $mdDialog, $filter, $q, dashboardService, dashboardUtils, types, utils, |
19 | + isAdd, fetchDashboardStates, actionSources, widgetActions, action) { | ||
19 | 20 | ||
20 | var vm = this; | 21 | var vm = this; |
21 | 22 | ||
22 | vm.types = types; | 23 | vm.types = types; |
23 | 24 | ||
24 | vm.isAdd = isAdd; | 25 | vm.isAdd = isAdd; |
26 | + vm.fetchDashboardStates = fetchDashboardStates; | ||
25 | vm.actionSources = actionSources; | 27 | vm.actionSources = actionSources; |
28 | + vm.widgetActions = widgetActions; | ||
29 | + | ||
30 | + vm.targetDashboardStateSearchText = ''; | ||
31 | + | ||
32 | + vm.selectedDashboardStateIds = []; | ||
26 | 33 | ||
27 | if (vm.isAdd) { | 34 | if (vm.isAdd) { |
28 | vm.action = { | 35 | vm.action = { |
@@ -32,15 +39,131 @@ export default function WidgetActionDialogController($scope, $mdDialog, types, u | @@ -32,15 +39,131 @@ export default function WidgetActionDialogController($scope, $mdDialog, types, u | ||
32 | vm.action = action; | 39 | vm.action = action; |
33 | } | 40 | } |
34 | 41 | ||
42 | + vm.actionSourceName = actionSourceName; | ||
43 | + | ||
44 | + vm.targetDashboardStateSearchTextChanged = function() { | ||
45 | + } | ||
46 | + | ||
47 | + vm.dashboardStateSearch = dashboardStateSearch; | ||
35 | vm.cancel = cancel; | 48 | vm.cancel = cancel; |
36 | vm.save = save; | 49 | vm.save = save; |
37 | 50 | ||
51 | + $scope.$watch("vm.action.name", function(newVal, prevVal) { | ||
52 | + if (!angular.equals(newVal, prevVal) && vm.action.name != null) { | ||
53 | + checkActionName(); | ||
54 | + } | ||
55 | + }); | ||
56 | + | ||
57 | + $scope.$watch("vm.action.actionSourceId", function(newVal, prevVal) { | ||
58 | + if (!angular.equals(newVal, prevVal) && vm.action.actionSourceId != null) { | ||
59 | + checkActionName(); | ||
60 | + } | ||
61 | + }); | ||
62 | + | ||
63 | + $scope.$watch("vm.action.targetDashboardId", function() { | ||
64 | + vm.selectedDashboardStateIds = []; | ||
65 | + if (vm.action.targetDashboardId) { | ||
66 | + dashboardService.getDashboard(vm.action.targetDashboardId).then( | ||
67 | + function success(dashboard) { | ||
68 | + dashboard = dashboardUtils.validateAndUpdateDashboard(dashboard); | ||
69 | + var states = dashboard.configuration.states; | ||
70 | + vm.selectedDashboardStateIds = Object.keys(states); | ||
71 | + } | ||
72 | + ); | ||
73 | + } | ||
74 | + }); | ||
75 | + | ||
76 | + $scope.$watch('vm.action.type', function(newType) { | ||
77 | + if (newType) { | ||
78 | + switch (newType) { | ||
79 | + case vm.types.widgetActionTypes.openDashboardState.value: | ||
80 | + case vm.types.widgetActionTypes.updateDashboardState.value: | ||
81 | + case vm.types.widgetActionTypes.openDashboard.value: | ||
82 | + if (angular.isUndefined(vm.action.setEntityId)) { | ||
83 | + vm.action.setEntityId = true; | ||
84 | + } | ||
85 | + break; | ||
86 | + } | ||
87 | + } | ||
88 | + }); | ||
89 | + | ||
90 | + function checkActionName() { | ||
91 | + var actionNameIsUnique = true; | ||
92 | + if (vm.action.actionSourceId && vm.action.name) { | ||
93 | + var sourceActions = vm.widgetActions[vm.action.actionSourceId]; | ||
94 | + if (sourceActions) { | ||
95 | + var result = $filter('filter')(sourceActions, {name: vm.action.name}, true); | ||
96 | + if (result && result.length && result[0].id !== vm.action.id) { | ||
97 | + actionNameIsUnique = false; | ||
98 | + } | ||
99 | + } | ||
100 | + } | ||
101 | + $scope.theForm.name.$setValidity('actionNameNotUnique', actionNameIsUnique); | ||
102 | + } | ||
103 | + | ||
104 | + function actionSourceName (actionSource) { | ||
105 | + if (actionSource) { | ||
106 | + return utils.customTranslation(actionSource.name, actionSource.name); | ||
107 | + } else { | ||
108 | + return ''; | ||
109 | + } | ||
110 | + } | ||
111 | + | ||
112 | + function dashboardStateSearch (query) { | ||
113 | + if (vm.action.type == vm.types.widgetActionTypes.openDashboard.value) { | ||
114 | + var deferred = $q.defer(); | ||
115 | + var result = query ? vm.selectedDashboardStateIds.filter( | ||
116 | + createFilterForDashboardState(query)) : vm.selectedDashboardStateIds; | ||
117 | + if (result && result.length) { | ||
118 | + deferred.resolve(result); | ||
119 | + } else { | ||
120 | + deferred.resolve([query]); | ||
121 | + } | ||
122 | + return deferred.promise; | ||
123 | + } else { | ||
124 | + return vm.fetchDashboardStates({query: query}); | ||
125 | + } | ||
126 | + } | ||
127 | + | ||
128 | + function createFilterForDashboardState (query) { | ||
129 | + var lowercaseQuery = angular.lowercase(query); | ||
130 | + return function filterFn(stateId) { | ||
131 | + return (angular.lowercase(stateId).indexOf(lowercaseQuery) === 0); | ||
132 | + }; | ||
133 | + } | ||
134 | + | ||
135 | + function cleanupAction(action) { | ||
136 | + var result = {}; | ||
137 | + result.id = action.id; | ||
138 | + result.actionSourceId = action.actionSourceId; | ||
139 | + result.name = action.name; | ||
140 | + result.icon = action.icon; | ||
141 | + result.type = action.type; | ||
142 | + switch (action.type) { | ||
143 | + case vm.types.widgetActionTypes.openDashboardState.value: | ||
144 | + case vm.types.widgetActionTypes.updateDashboardState.value: | ||
145 | + result.targetDashboardStateId = action.targetDashboardStateId; | ||
146 | + result.openRightLayout = action.openRightLayout; | ||
147 | + result.setEntityId = action.setEntityId; | ||
148 | + break; | ||
149 | + case vm.types.widgetActionTypes.openDashboard.value: | ||
150 | + result.targetDashboardId = action.targetDashboardId; | ||
151 | + result.targetDashboardStateId = action.targetDashboardStateId; | ||
152 | + result.setEntityId = action.setEntityId; | ||
153 | + break; | ||
154 | + case vm.types.widgetActionTypes.custom.value: | ||
155 | + result.customFunction = action.customFunction; | ||
156 | + break; | ||
157 | + } | ||
158 | + return result; | ||
159 | + } | ||
160 | + | ||
38 | function cancel() { | 161 | function cancel() { |
39 | $mdDialog.cancel(); | 162 | $mdDialog.cancel(); |
40 | } | 163 | } |
41 | 164 | ||
42 | function save() { | 165 | function save() { |
43 | $scope.theForm.$setPristine(); | 166 | $scope.theForm.$setPristine(); |
44 | - $mdDialog.hide(vm.action); | 167 | + $mdDialog.hide(cleanupAction(vm.action)); |
45 | } | 168 | } |
46 | } | 169 | } |
@@ -31,12 +31,12 @@ | @@ -31,12 +31,12 @@ | ||
31 | <md-dialog-content> | 31 | <md-dialog-content> |
32 | <div class="md-dialog-content"> | 32 | <div class="md-dialog-content"> |
33 | <md-content class="md-padding" layout="column"> | 33 | <md-content class="md-padding" layout="column"> |
34 | - <fieldset ng-disabled="loading"> | 34 | + <fieldset ng-disabled="loading" layout="column"> |
35 | <md-input-container class="md-block"> | 35 | <md-input-container class="md-block"> |
36 | <label translate>widget-config.action-source</label> | 36 | <label translate>widget-config.action-source</label> |
37 | <md-select name="actionSource" required aria-label="{{ 'widget-config.action-source' | translate }}" ng-model="vm.action.actionSourceId"> | 37 | <md-select name="actionSource" required aria-label="{{ 'widget-config.action-source' | translate }}" ng-model="vm.action.actionSourceId"> |
38 | <md-option ng-repeat="(actionSourceId, actionSource) in vm.actionSources" ng-value="actionSourceId"> | 38 | <md-option ng-repeat="(actionSourceId, actionSource) in vm.actionSources" ng-value="actionSourceId"> |
39 | - {{actionSource.name}} | 39 | + {{vm.actionSourceName(actionSource)}} |
40 | </md-option> | 40 | </md-option> |
41 | </md-select> | 41 | </md-select> |
42 | <div ng-messages="theForm.actionSource.$error"> | 42 | <div ng-messages="theForm.actionSource.$error"> |
@@ -48,6 +48,7 @@ | @@ -48,6 +48,7 @@ | ||
48 | <input name="name" required ng-model="vm.action.name"> | 48 | <input name="name" required ng-model="vm.action.name"> |
49 | <div ng-messages="theForm.name.$error"> | 49 | <div ng-messages="theForm.name.$error"> |
50 | <div ng-message="required" translate>widget-config.action-name-required</div> | 50 | <div ng-message="required" translate>widget-config.action-name-required</div> |
51 | + <div ng-message="actionNameNotUnique" translate>widget-config.action-name-not-unique</div> | ||
51 | </div> | 52 | </div> |
52 | </md-input-container> | 53 | </md-input-container> |
53 | <tb-material-icon-select ng-model="vm.action.icon"> | 54 | <tb-material-icon-select ng-model="vm.action.icon"> |
@@ -63,6 +64,57 @@ | @@ -63,6 +64,57 @@ | ||
63 | <div ng-message="required" translate>widget-config.action-type-required</div> | 64 | <div ng-message="required" translate>widget-config.action-type-required</div> |
64 | </div> | 65 | </div> |
65 | </md-input-container> | 66 | </md-input-container> |
67 | + <div layout="column" | ||
68 | + style="padding-bottom: 20px;" | ||
69 | + ng-if="vm.action.type == vm.types.widgetActionTypes.openDashboard.value"> | ||
70 | + <div class="md-caption tb-required" | ||
71 | + style="padding-left: 3px; padding-bottom: 10px; color: rgba(0,0,0,0.57);" translate>widget-action.target-dashboard</div> | ||
72 | + <tb-dashboard-autocomplete the-form="theForm" | ||
73 | + tb-required="true" | ||
74 | + ng-model="vm.action.targetDashboardId" | ||
75 | + select-first-dashboard="false"> | ||
76 | + </tb-dashboard-autocomplete> | ||
77 | + </div> | ||
78 | + <md-autocomplete ng-if="vm.action.type == vm.types.widgetActionTypes.openDashboardState.value || | ||
79 | + vm.action.type == vm.types.widgetActionTypes.updateDashboardState.value || | ||
80 | + vm.action.type == vm.types.widgetActionTypes.openDashboard.value" | ||
81 | + ng-required="vm.action.type == vm.types.widgetActionTypes.openDashboardState.value" | ||
82 | + md-no-cache="true" | ||
83 | + md-input-name="targetDashboardState" | ||
84 | + ng-model="vm.action.targetDashboardStateId" | ||
85 | + md-selected-item="vm.action.targetDashboardStateId" | ||
86 | + md-search-text="vm.targetDashboardStateSearchText" | ||
87 | + md-search-text-change="vm.targetDashboardStateSearchTextChanged()" | ||
88 | + md-items="item in vm.dashboardStateSearch(vm.targetDashboardStateSearchText)" | ||
89 | + md-item-text="item" | ||
90 | + md-min-length="0" | ||
91 | + md-floating-label="{{ 'widget-action.target-dashboard-state' | translate }}" | ||
92 | + md-select-on-match="true"> | ||
93 | + <md-item-template> | ||
94 | + <div> | ||
95 | + <span md-highlight-text="vm.targetDashboardStateSearchText" md-highlight-flags="^i">{{item}}</span> | ||
96 | + </div> | ||
97 | + </md-item-template> | ||
98 | + <div ng-messages="theForm.targetDashboardState.$error"> | ||
99 | + <div translate ng-message="required">widget-action.target-dashboard-state-required</div> | ||
100 | + </div> | ||
101 | + </md-autocomplete> | ||
102 | + <md-checkbox ng-if="vm.action.type == vm.types.widgetActionTypes.openDashboardState.value || | ||
103 | + vm.action.type == vm.types.widgetActionTypes.updateDashboardState.value" | ||
104 | + flex aria-label="{{ 'widget-action.open-right-layout' | translate }}" | ||
105 | + ng-model="vm.action.openRightLayout">{{ 'widget-action.open-right-layout' | translate }} | ||
106 | + </md-checkbox> | ||
107 | + <md-checkbox ng-if="vm.action.type == vm.types.widgetActionTypes.openDashboardState.value || | ||
108 | + vm.action.type == vm.types.widgetActionTypes.updateDashboardState.value || | ||
109 | + vm.action.type == vm.types.widgetActionTypes.openDashboard.value" | ||
110 | + flex aria-label="{{ 'widget-action.set-entity-from-widget' | translate }}" | ||
111 | + ng-model="vm.action.setEntityId">{{ 'widget-action.set-entity-from-widget' | translate }} | ||
112 | + </md-checkbox> | ||
113 | + <tb-js-func ng-if="vm.action.type == vm.types.widgetActionTypes.custom.value" | ||
114 | + ng-model="vm.action.customFunction" | ||
115 | + function-args="{{ ['$event', 'widgetContext', 'entityId'] }}" | ||
116 | + validation-args="{{ [] }}"> | ||
117 | + </tb-js-func> | ||
66 | </fieldset> | 118 | </fieldset> |
67 | </md-content> | 119 | </md-content> |
68 | </div> | 120 | </div> |
@@ -468,6 +468,7 @@ function WidgetConfig($compile, $templateCache, $rootScope, $translate, $timeout | @@ -468,6 +468,7 @@ function WidgetConfig($compile, $templateCache, $rootScope, $translate, $timeout | ||
468 | aliasController: '=', | 468 | aliasController: '=', |
469 | functionsOnly: '=', | 469 | functionsOnly: '=', |
470 | fetchEntityKeys: '&', | 470 | fetchEntityKeys: '&', |
471 | + fetchDashboardStates: '&', | ||
471 | onCreateEntityAlias: '&', | 472 | onCreateEntityAlias: '&', |
472 | theForm: '=' | 473 | theForm: '=' |
473 | }, | 474 | }, |
@@ -277,7 +277,10 @@ | @@ -277,7 +277,10 @@ | ||
277 | </md-tab> | 277 | </md-tab> |
278 | <md-tab label="{{ 'widget-config.actions' | translate }}"> | 278 | <md-tab label="{{ 'widget-config.actions' | translate }}"> |
279 | <md-content class="md-padding" layout="column"> | 279 | <md-content class="md-padding" layout="column"> |
280 | - <tb-manage-widget-actions action-sources="actionSources" widget-actions="actions"> | 280 | + <tb-manage-widget-actions |
281 | + action-sources="actionSources" | ||
282 | + widget-actions="actions" | ||
283 | + fetch-dashboard-states="fetchDashboardStates({query: query})"> | ||
281 | </tb-manage-widget-actions> | 284 | </tb-manage-widget-actions> |
282 | </md-content> | 285 | </md-content> |
283 | </md-tab> | 286 | </md-tab> |
@@ -20,7 +20,7 @@ import Subscription from '../../api/subscription'; | @@ -20,7 +20,7 @@ import Subscription from '../../api/subscription'; | ||
20 | /* eslint-disable angular/angularelement */ | 20 | /* eslint-disable angular/angularelement */ |
21 | 21 | ||
22 | /*@ngInject*/ | 22 | /*@ngInject*/ |
23 | -export default function WidgetController($scope, $timeout, $window, $element, $q, $log, $injector, $filter, $compile, tbRaf, types, utils, timeService, | 23 | +export default function WidgetController($scope, $state, $timeout, $window, $element, $q, $log, $injector, $filter, $compile, tbRaf, types, utils, timeService, |
24 | datasourceService, alarmService, entityService, deviceService, visibleRect, isEdit, isMobile, stDiff, dashboardTimewindow, | 24 | datasourceService, alarmService, entityService, deviceService, visibleRect, isEdit, isMobile, stDiff, dashboardTimewindow, |
25 | dashboardTimewindowApi, widget, aliasController, stateController, widgetInfo, widgetType) { | 25 | dashboardTimewindowApi, widget, aliasController, stateController, widgetInfo, widgetType) { |
26 | 26 | ||
@@ -44,6 +44,20 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -44,6 +44,20 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
44 | 44 | ||
45 | var cafs = {}; | 45 | var cafs = {}; |
46 | 46 | ||
47 | + var actionDescriptorsBySourceId = {}; | ||
48 | + if (widget.config.actions) { | ||
49 | + for (var actionSourceId in widget.config.actions) { | ||
50 | + var descriptors = widget.config.actions[actionSourceId]; | ||
51 | + var actionDescriptors = []; | ||
52 | + descriptors.forEach(function(descriptor) { | ||
53 | + var actionDescriptor = angular.copy(descriptor); | ||
54 | + actionDescriptor.displayName = utils.customTranslation(descriptor.name, descriptor.name); | ||
55 | + actionDescriptors.push(actionDescriptor); | ||
56 | + }); | ||
57 | + actionDescriptorsBySourceId[actionSourceId] = actionDescriptors; | ||
58 | + } | ||
59 | + } | ||
60 | + | ||
47 | var widgetContext = { | 61 | var widgetContext = { |
48 | inited: false, | 62 | inited: false, |
49 | $container: null, | 63 | $container: null, |
@@ -103,9 +117,32 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -103,9 +117,32 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
103 | utils: { | 117 | utils: { |
104 | formatValue: formatValue | 118 | formatValue: formatValue |
105 | }, | 119 | }, |
120 | + actionsApi: { | ||
121 | + actionDescriptorsBySourceId: actionDescriptorsBySourceId, | ||
122 | + getActionDescriptors: getActionDescriptors, | ||
123 | + handleWidgetAction: handleWidgetAction | ||
124 | + }, | ||
106 | stateController: stateController | 125 | stateController: stateController |
107 | }; | 126 | }; |
108 | 127 | ||
128 | + widgetContext.customHeaderActions = []; | ||
129 | + var headerActionsDescriptors = getActionDescriptors(types.widgetActionSources.headerButton.value); | ||
130 | + for (var i=0;i<headerActionsDescriptors.length;i++) { | ||
131 | + var descriptor = headerActionsDescriptors[i]; | ||
132 | + var headerAction = {}; | ||
133 | + headerAction.name = descriptor.name; | ||
134 | + headerAction.displayName = descriptor.displayName; | ||
135 | + headerAction.icon = descriptor.icon; | ||
136 | + headerAction.descriptor = descriptor; | ||
137 | + headerAction.onAction = function($event) { | ||
138 | + var entityInfo = getFirstEntityInfo(); | ||
139 | + var entityId = entityInfo ? entityInfo.entityId : null; | ||
140 | + var entityName = entityInfo ? entityInfo.entityName : null; | ||
141 | + handleWidgetAction($event, this.descriptor, entityId, entityName); | ||
142 | + } | ||
143 | + widgetContext.customHeaderActions.push(headerAction); | ||
144 | + } | ||
145 | + | ||
109 | var subscriptionContext = { | 146 | var subscriptionContext = { |
110 | $scope: $scope, | 147 | $scope: $scope, |
111 | $q: $q, | 148 | $q: $q, |
@@ -376,6 +413,87 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | @@ -376,6 +413,87 @@ export default function WidgetController($scope, $timeout, $window, $element, $q | ||
376 | return deferred.promise; | 413 | return deferred.promise; |
377 | } | 414 | } |
378 | 415 | ||
416 | + function getActionDescriptors(actionSourceId) { | ||
417 | + var result = widgetContext.actionsApi.actionDescriptorsBySourceId[actionSourceId]; | ||
418 | + if (!result) { | ||
419 | + result = []; | ||
420 | + } | ||
421 | + return result; | ||
422 | + } | ||
423 | + | ||
424 | + function handleWidgetAction($event, descriptor, entityId, entityName) { | ||
425 | + var type = descriptor.type; | ||
426 | + switch (type) { | ||
427 | + case types.widgetActionTypes.openDashboardState.value: | ||
428 | + case types.widgetActionTypes.updateDashboardState.value: | ||
429 | + var targetDashboardStateId = descriptor.targetDashboardStateId; | ||
430 | + var targetEntityId; | ||
431 | + if (descriptor.setEntityId) { | ||
432 | + targetEntityId = entityId; | ||
433 | + } | ||
434 | + var params = {}; | ||
435 | + if (targetEntityId) { | ||
436 | + params.entityId = targetEntityId; | ||
437 | + if (entityName) { | ||
438 | + params.entityName = entityName; | ||
439 | + } | ||
440 | + } | ||
441 | + if (type == types.widgetActionTypes.openDashboardState.value) { | ||
442 | + widgetContext.stateController.openState(targetDashboardStateId, params, descriptor.openRightLayout); | ||
443 | + } else { | ||
444 | + widgetContext.stateController.updateState(targetDashboardStateId, params, descriptor.openRightLayout); | ||
445 | + } | ||
446 | + break; | ||
447 | + case types.widgetActionTypes.openDashboard.value: | ||
448 | + var targetDashboardId = descriptor.targetDashboardId; | ||
449 | + targetDashboardStateId = descriptor.targetDashboardStateId; | ||
450 | + targetEntityId; | ||
451 | + if (descriptor.setEntityId) { | ||
452 | + targetEntityId = entityId; | ||
453 | + } | ||
454 | + var stateObject = {}; | ||
455 | + stateObject.params = {}; | ||
456 | + if (targetEntityId) { | ||
457 | + stateObject.params.entityId = targetEntityId; | ||
458 | + if (entityName) { | ||
459 | + stateObject.params.entityName = entityName; | ||
460 | + } | ||
461 | + } | ||
462 | + if (targetDashboardStateId) { | ||
463 | + stateObject.id = targetDashboardStateId; | ||
464 | + } | ||
465 | + var stateParams = { | ||
466 | + dashboardId: targetDashboardId, | ||
467 | + state: angular.toJson([ stateObject ]) | ||
468 | + } | ||
469 | + $state.go('home.dashboards.dashboard', stateParams); | ||
470 | + break; | ||
471 | + case types.widgetActionTypes.custom.value: | ||
472 | + var customFunction = descriptor.customFunction; | ||
473 | + if (angular.isDefined(customFunction) && customFunction.length > 0) { | ||
474 | + try { | ||
475 | + var customActionFunction = new Function('$event', 'widgetContext', 'entityId', 'entityName', customFunction); | ||
476 | + customActionFunction($event, widgetContext, entityId, entityName); | ||
477 | + } catch (e) { | ||
478 | + // | ||
479 | + } | ||
480 | + } | ||
481 | + break; | ||
482 | + } | ||
483 | + } | ||
484 | + | ||
485 | + function getFirstEntityInfo() { | ||
486 | + var entityInfo; | ||
487 | + for (var id in widgetContext.subscriptions) { | ||
488 | + var subscription = widgetContext.subscriptions[id]; | ||
489 | + entityInfo = subscription.getFirstEntityInfo(); | ||
490 | + if (entityInfo) { | ||
491 | + break; | ||
492 | + } | ||
493 | + } | ||
494 | + return entityInfo; | ||
495 | + } | ||
496 | + | ||
379 | function configureWidgetElement() { | 497 | function configureWidgetElement() { |
380 | 498 | ||
381 | $scope.displayLegend = angular.isDefined(widget.config.showLegend) ? | 499 | $scope.displayLegend = angular.isDefined(widget.config.showLegend) ? |
@@ -36,6 +36,7 @@ export default function AddWidgetController($scope, widgetService, entityService | @@ -36,6 +36,7 @@ export default function AddWidgetController($scope, widgetService, entityService | ||
36 | vm.add = add; | 36 | vm.add = add; |
37 | vm.cancel = cancel; | 37 | vm.cancel = cancel; |
38 | vm.fetchEntityKeys = fetchEntityKeys; | 38 | vm.fetchEntityKeys = fetchEntityKeys; |
39 | + vm.fetchDashboardStates = fetchDashboardStates; | ||
39 | vm.createEntityAlias = createEntityAlias; | 40 | vm.createEntityAlias = createEntityAlias; |
40 | 41 | ||
41 | vm.widgetConfig = { | 42 | vm.widgetConfig = { |
@@ -128,6 +129,26 @@ export default function AddWidgetController($scope, widgetService, entityService | @@ -128,6 +129,26 @@ export default function AddWidgetController($scope, widgetService, entityService | ||
128 | return deferred.promise; | 129 | return deferred.promise; |
129 | } | 130 | } |
130 | 131 | ||
132 | + function fetchDashboardStates (query) { | ||
133 | + var deferred = $q.defer(); | ||
134 | + var stateIds = Object.keys(vm.dashboard.configuration.states); | ||
135 | + var result = query ? stateIds.filter( | ||
136 | + createFilterForDashboardState(query)) : stateIds; | ||
137 | + if (result && result.length) { | ||
138 | + deferred.resolve(result); | ||
139 | + } else { | ||
140 | + deferred.resolve([query]); | ||
141 | + } | ||
142 | + return deferred.promise; | ||
143 | + } | ||
144 | + | ||
145 | + function createFilterForDashboardState (query) { | ||
146 | + var lowercaseQuery = angular.lowercase(query); | ||
147 | + return function filterFn(stateId) { | ||
148 | + return (angular.lowercase(stateId).indexOf(lowercaseQuery) === 0); | ||
149 | + }; | ||
150 | + } | ||
151 | + | ||
131 | function createEntityAlias (event, alias, allowedEntityTypes) { | 152 | function createEntityAlias (event, alias, allowedEntityTypes) { |
132 | 153 | ||
133 | var deferred = $q.defer(); | 154 | var deferred = $q.defer(); |
@@ -42,6 +42,7 @@ | @@ -42,6 +42,7 @@ | ||
42 | alias-controller="vm.aliasController" | 42 | alias-controller="vm.aliasController" |
43 | functions-only="vm.functionsOnly" | 43 | functions-only="vm.functionsOnly" |
44 | fetch-entity-keys="vm.fetchEntityKeys(entityAliasId, query, type)" | 44 | fetch-entity-keys="vm.fetchEntityKeys(entityAliasId, query, type)" |
45 | + fetch-dashboard-states="vm.fetchDashboardStates(query)" | ||
45 | on-create-entity-alias="vm.createEntityAlias(event, alias, allowedEntityTypes)" | 46 | on-create-entity-alias="vm.createEntityAlias(event, alias, allowedEntityTypes)" |
46 | the-form="theForm"></tb-widget-config> | 47 | the-form="theForm"></tb-widget-config> |
47 | </fieldset> | 48 | </fieldset> |
@@ -94,6 +94,26 @@ export default function EditWidgetDirective($compile, $templateCache, types, wid | @@ -94,6 +94,26 @@ export default function EditWidgetDirective($compile, $templateCache, types, wid | ||
94 | return deferred.promise; | 94 | return deferred.promise; |
95 | }; | 95 | }; |
96 | 96 | ||
97 | + scope.fetchDashboardStates = function(query) { | ||
98 | + var deferred = $q.defer(); | ||
99 | + var stateIds = Object.keys(scope.dashboard.configuration.states); | ||
100 | + var result = query ? stateIds.filter( | ||
101 | + createFilterForDashboardState(query)) : stateIds; | ||
102 | + if (result && result.length) { | ||
103 | + deferred.resolve(result); | ||
104 | + } else { | ||
105 | + deferred.resolve([query]); | ||
106 | + } | ||
107 | + return deferred.promise; | ||
108 | + } | ||
109 | + | ||
110 | + function createFilterForDashboardState (query) { | ||
111 | + var lowercaseQuery = angular.lowercase(query); | ||
112 | + return function filterFn(stateId) { | ||
113 | + return (angular.lowercase(stateId).indexOf(lowercaseQuery) === 0); | ||
114 | + }; | ||
115 | + } | ||
116 | + | ||
97 | scope.createEntityAlias = function (event, alias, allowedEntityTypes) { | 117 | scope.createEntityAlias = function (event, alias, allowedEntityTypes) { |
98 | 118 | ||
99 | var deferred = $q.defer(); | 119 | var deferred = $q.defer(); |
@@ -26,6 +26,7 @@ | @@ -26,6 +26,7 @@ | ||
26 | alias-controller="aliasController" | 26 | alias-controller="aliasController" |
27 | functions-only="widgetEditMode" | 27 | functions-only="widgetEditMode" |
28 | fetch-entity-keys="fetchEntityKeys(entityAliasId, query, type)" | 28 | fetch-entity-keys="fetchEntityKeys(entityAliasId, query, type)" |
29 | + fetch-dashboard-states="fetchDashboardStates(query)" | ||
29 | on-create-entity-alias="createEntityAlias(event, alias, allowedEntityTypes)" | 30 | on-create-entity-alias="createEntityAlias(event, alias, allowedEntityTypes)" |
30 | the-form="theForm"></tb-widget-config> | 31 | the-form="theForm"></tb-widget-config> |
31 | </fieldset> | 32 | </fieldset> |
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | 16 | ||
17 | /*@ngInject*/ | 17 | /*@ngInject*/ |
18 | -export default function DefaultStateController($scope, $location, $state, $stateParams, $translate, types, dashboardUtils) { | 18 | +export default function DefaultStateController($scope, $location, $state, $stateParams, utils, types, dashboardUtils) { |
19 | 19 | ||
20 | var vm = this; | 20 | var vm = this; |
21 | 21 | ||
@@ -50,6 +50,9 @@ export default function DefaultStateController($scope, $location, $state, $state | @@ -50,6 +50,9 @@ export default function DefaultStateController($scope, $location, $state, $state | ||
50 | } | 50 | } |
51 | 51 | ||
52 | function updateState(id, params, openRightLayout) { | 52 | function updateState(id, params, openRightLayout) { |
53 | + if (!id) { | ||
54 | + id = getStateId(); | ||
55 | + } | ||
53 | if (vm.states && vm.states[id]) { | 56 | if (vm.states && vm.states[id]) { |
54 | if (!params) { | 57 | if (!params) { |
55 | params = {}; | 58 | params = {}; |
@@ -110,15 +113,7 @@ export default function DefaultStateController($scope, $location, $state, $state | @@ -110,15 +113,7 @@ export default function DefaultStateController($scope, $location, $state, $state | ||
110 | } | 113 | } |
111 | 114 | ||
112 | function getStateName(id, state) { | 115 | function getStateName(id, state) { |
113 | - var result = ''; | ||
114 | - var translationId = types.translate.customTranslationsPrefix + state.name; | ||
115 | - var translation = $translate.instant(translationId); | ||
116 | - if (translation != translationId) { | ||
117 | - result = translation + ''; | ||
118 | - } else { | ||
119 | - result = id; | ||
120 | - } | ||
121 | - return result; | 116 | + return utils.customTranslation(state.name, id); |
122 | } | 117 | } |
123 | 118 | ||
124 | function parseState(stateJson) { | 119 | function parseState(stateJson) { |
@@ -55,6 +55,9 @@ export default function EntityStateController($scope, $location, $state, $stateP | @@ -55,6 +55,9 @@ export default function EntityStateController($scope, $location, $state, $stateP | ||
55 | } | 55 | } |
56 | 56 | ||
57 | function updateState(id, params, openRightLayout) { | 57 | function updateState(id, params, openRightLayout) { |
58 | + if (!id) { | ||
59 | + id = getStateId(); | ||
60 | + } | ||
58 | if (vm.states && vm.states[id]) { | 61 | if (vm.states && vm.states[id]) { |
59 | resolveEntity(params).then( | 62 | resolveEntity(params).then( |
60 | function success(entityName) { | 63 | function success(entityName) { |
@@ -121,17 +124,10 @@ export default function EntityStateController($scope, $location, $state, $stateP | @@ -121,17 +124,10 @@ export default function EntityStateController($scope, $location, $state, $stateP | ||
121 | var result = ''; | 124 | var result = ''; |
122 | if (vm.stateObject[index]) { | 125 | if (vm.stateObject[index]) { |
123 | var stateName = vm.states[vm.stateObject[index].id].name; | 126 | var stateName = vm.states[vm.stateObject[index].id].name; |
124 | - var translationId = types.translate.customTranslationsPrefix + stateName; | ||
125 | - var translation = $translate.instant(translationId); | ||
126 | - if (translation != translationId) { | ||
127 | - stateName = translation + ''; | ||
128 | - } | 127 | + stateName = utils.customTranslation(stateName, stateName); |
129 | var params = vm.stateObject[index].params; | 128 | var params = vm.stateObject[index].params; |
130 | - if (params && params.entityName) { | ||
131 | - result = utils.insertVariable(stateName, 'entityName', params.entityName); | ||
132 | - } else { | ||
133 | - result = stateName; | ||
134 | - } | 129 | + var entityName = params && params.entityName ? params.entityName : ''; |
130 | + result = utils.insertVariable(stateName, 'entityName', entityName); | ||
135 | } | 131 | } |
136 | return result; | 132 | return result; |
137 | } | 133 | } |
@@ -102,6 +102,7 @@ export default function AddWidgetToDashboardDialogController($scope, $mdDialog, | @@ -102,6 +102,7 @@ export default function AddWidgetToDashboardDialogController($scope, $mdDialog, | ||
102 | if (vm.addToDashboardType === 0) { | 102 | if (vm.addToDashboardType === 0) { |
103 | dashboardService.getDashboard(vm.dashboardId).then( | 103 | dashboardService.getDashboard(vm.dashboardId).then( |
104 | function success(dashboard) { | 104 | function success(dashboard) { |
105 | + dashboard = dashboardUtils.validateAndUpdateDashboard(dashboard); | ||
105 | selectTargetState($event, dashboard).then( | 106 | selectTargetState($event, dashboard).then( |
106 | function(targetState) { | 107 | function(targetState) { |
107 | selectTargetLayout($event, dashboard, targetState).then( | 108 | selectTargetLayout($event, dashboard, targetState).then( |
@@ -1104,11 +1104,16 @@ export default angular.module('thingsboard.locale', []) | @@ -1104,11 +1104,16 @@ export default angular.module('thingsboard.locale', []) | ||
1104 | "export": "Export widget" | 1104 | "export": "Export widget" |
1105 | }, | 1105 | }, |
1106 | "widget-action": { | 1106 | "widget-action": { |
1107 | - "header-button": "Header button", | 1107 | + "header-button": "Widget header button", |
1108 | "open-dashboard-state": "Navigate to new dashboard state", | 1108 | "open-dashboard-state": "Navigate to new dashboard state", |
1109 | "update-dashboard-state": "Update current dashboard state", | 1109 | "update-dashboard-state": "Update current dashboard state", |
1110 | "open-dashboard": "Navigate to other dashboard", | 1110 | "open-dashboard": "Navigate to other dashboard", |
1111 | - "custom": "Custom action" | 1111 | + "custom": "Custom action", |
1112 | + "target-dashboard-state": "Target dashboard state", | ||
1113 | + "target-dashboard-state-required": "Target dashboard state is required", | ||
1114 | + "set-entity-from-widget": "Set entity from widget", | ||
1115 | + "target-dashboard": "Target dashboard", | ||
1116 | + "open-right-layout": "Open right dashboard layout (mobile view)" | ||
1112 | }, | 1117 | }, |
1113 | "widgets-bundle": { | 1118 | "widgets-bundle": { |
1114 | "current": "Current bundle", | 1119 | "current": "Current bundle", |
@@ -1174,6 +1179,7 @@ export default angular.module('thingsboard.locale', []) | @@ -1174,6 +1179,7 @@ export default angular.module('thingsboard.locale', []) | ||
1174 | "action-source-required": "Action source is required.", | 1179 | "action-source-required": "Action source is required.", |
1175 | "action-name": "Name", | 1180 | "action-name": "Name", |
1176 | "action-name-required": "Action name is required.", | 1181 | "action-name-required": "Action name is required.", |
1182 | + "action-name-not-unique": "Another action with the same name already exists.<br/>Action name should be unique within the same action source.", | ||
1177 | "action-icon": "Icon", | 1183 | "action-icon": "Icon", |
1178 | "action-type": "Type", | 1184 | "action-type": "Type", |
1179 | "action-type-required": "Action type is required.", | 1185 | "action-type-required": "Action type is required.", |
@@ -1205,6 +1211,10 @@ export default angular.module('thingsboard.locale', []) | @@ -1205,6 +1211,10 @@ export default angular.module('thingsboard.locale', []) | ||
1205 | "es_ES": "Spanish" | 1211 | "es_ES": "Spanish" |
1206 | }, | 1212 | }, |
1207 | "custom": { | 1213 | "custom": { |
1214 | + "widget-action": { | ||
1215 | + "action-cell-button": "Action cell button", | ||
1216 | + "row-click": "On row click" | ||
1217 | + } | ||
1208 | } | 1218 | } |
1209 | } | 1219 | } |
1210 | } | 1220 | } |
@@ -158,13 +158,7 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia | @@ -158,13 +158,7 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia | ||
158 | vm.ctx.widgetActions = [ vm.searchAction ]; | 158 | vm.ctx.widgetActions = [ vm.searchAction ]; |
159 | 159 | ||
160 | if (vm.settings.alarmsTitle && vm.settings.alarmsTitle.length) { | 160 | if (vm.settings.alarmsTitle && vm.settings.alarmsTitle.length) { |
161 | - var translationId = types.translate.customTranslationsPrefix + vm.settings.alarmsTitle; | ||
162 | - var translation = $translate.instant(translationId); | ||
163 | - if (translation != translationId) { | ||
164 | - vm.alarmsTitle = translation + ''; | ||
165 | - } else { | ||
166 | - vm.alarmsTitle = vm.settings.alarmsTitle; | ||
167 | - } | 161 | + vm.alarmsTitle = utils.customTranslation(vm.settings.alarmsTitle, vm.settings.alarmsTitle); |
168 | } else { | 162 | } else { |
169 | vm.alarmsTitle = $translate.instant('alarm.alarms'); | 163 | vm.alarmsTitle = $translate.instant('alarm.alarms'); |
170 | } | 164 | } |
@@ -226,6 +220,9 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia | @@ -226,6 +220,9 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia | ||
226 | 'table.md-table td.md-cell.md-checkbox-cell md-checkbox:not(.md-checked) .md-icon {\n'+ | 220 | 'table.md-table td.md-cell.md-checkbox-cell md-checkbox:not(.md-checked) .md-icon {\n'+ |
227 | 'border-color: ' + mdDarkSecondary + ';\n'+ | 221 | 'border-color: ' + mdDarkSecondary + ';\n'+ |
228 | '}\n'+ | 222 | '}\n'+ |
223 | + 'table.md-table td.md-cell.tb-action-cell button.md-icon-button md-icon {\n'+ | ||
224 | + 'color: ' + mdDarkSecondary + ';\n'+ | ||
225 | + '}\n'+ | ||
229 | 'table.md-table td.md-cell.md-placeholder {\n'+ | 226 | 'table.md-table td.md-cell.md-placeholder {\n'+ |
230 | 'color: ' + mdDarkDisabled + ';\n'+ | 227 | 'color: ' + mdDarkDisabled + ';\n'+ |
231 | '}\n'+ | 228 | '}\n'+ |
@@ -539,13 +536,7 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia | @@ -539,13 +536,7 @@ function AlarmsTableWidgetController($element, $scope, $filter, $mdMedia, $mdDia | ||
539 | for (var d = 0; d < vm.alarmSource.dataKeys.length; d++ ) { | 536 | for (var d = 0; d < vm.alarmSource.dataKeys.length; d++ ) { |
540 | var dataKey = vm.alarmSource.dataKeys[d]; | 537 | var dataKey = vm.alarmSource.dataKeys[d]; |
541 | 538 | ||
542 | - var translationId = types.translate.customTranslationsPrefix + dataKey.label; | ||
543 | - var translation = $translate.instant(translationId); | ||
544 | - if (translation != translationId) { | ||
545 | - dataKey.title = translation + ''; | ||
546 | - } else { | ||
547 | - dataKey.title = dataKey.label; | ||
548 | - } | 539 | + dataKey.title = utils.customTranslation(dataKey.label, dataKey.label); |
549 | 540 | ||
550 | var keySettings = dataKey.settings; | 541 | var keySettings = dataKey.settings; |
551 | 542 |
@@ -65,8 +65,9 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | @@ -65,8 +65,9 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | ||
65 | vm.currentEntity = null; | 65 | vm.currentEntity = null; |
66 | 66 | ||
67 | vm.displayEntityName = true; | 67 | vm.displayEntityName = true; |
68 | + vm.entityNameColumnTitle = ''; | ||
68 | vm.displayEntityType = true; | 69 | vm.displayEntityType = true; |
69 | - vm.displayActions = false; //TODO: Widget actions | 70 | + vm.actionCellDescriptors = []; |
70 | vm.displayPagination = true; | 71 | vm.displayPagination = true; |
71 | vm.defaultPageSize = 10; | 72 | vm.defaultPageSize = 10; |
72 | vm.defaultSortOrder = 'entityName'; | 73 | vm.defaultSortOrder = 'entityName'; |
@@ -92,6 +93,7 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | @@ -92,6 +93,7 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | ||
92 | vm.onReorder = onReorder; | 93 | vm.onReorder = onReorder; |
93 | vm.onPaginate = onPaginate; | 94 | vm.onPaginate = onPaginate; |
94 | vm.onRowClick = onRowClick; | 95 | vm.onRowClick = onRowClick; |
96 | + vm.onActionButtonClick = onActionButtonClick; | ||
95 | vm.isCurrent = isCurrent; | 97 | vm.isCurrent = isCurrent; |
96 | 98 | ||
97 | vm.cellStyle = cellStyle; | 99 | vm.cellStyle = cellStyle; |
@@ -141,14 +143,10 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | @@ -141,14 +143,10 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | ||
141 | 143 | ||
142 | vm.ctx.widgetActions = [ vm.searchAction ]; | 144 | vm.ctx.widgetActions = [ vm.searchAction ]; |
143 | 145 | ||
146 | + vm.actionCellDescriptors = vm.ctx.actionsApi.getActionDescriptors('actionCellButton'); | ||
147 | + | ||
144 | if (vm.settings.entitiesTitle && vm.settings.entitiesTitle.length) { | 148 | if (vm.settings.entitiesTitle && vm.settings.entitiesTitle.length) { |
145 | - var translationId = types.translate.customTranslationsPrefix + vm.settings.entitiesTitle; | ||
146 | - var translation = $translate.instant(translationId); | ||
147 | - if (translation != translationId) { | ||
148 | - vm.entitiesTitle = translation + ''; | ||
149 | - } else { | ||
150 | - vm.entitiesTitle = vm.settings.entitiesTitle; | ||
151 | - } | 149 | + vm.entitiesTitle = utils.customTranslation(vm.settings.entitiesTitle, vm.settings.entitiesTitle); |
152 | } else { | 150 | } else { |
153 | vm.entitiesTitle = $translate.instant('entity.entities'); | 151 | vm.entitiesTitle = $translate.instant('entity.entities'); |
154 | } | 152 | } |
@@ -157,6 +155,13 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | @@ -157,6 +155,13 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | ||
157 | 155 | ||
158 | vm.searchAction.show = angular.isDefined(vm.settings.enableSearch) ? vm.settings.enableSearch : true; | 156 | vm.searchAction.show = angular.isDefined(vm.settings.enableSearch) ? vm.settings.enableSearch : true; |
159 | vm.displayEntityName = angular.isDefined(vm.settings.displayEntityName) ? vm.settings.displayEntityName : true; | 157 | vm.displayEntityName = angular.isDefined(vm.settings.displayEntityName) ? vm.settings.displayEntityName : true; |
158 | + | ||
159 | + if (vm.settings.entityNameColumnTitle && vm.settings.entityNameColumnTitle.length) { | ||
160 | + vm.entityNameColumnTitle = utils.customTranslation(vm.settings.entityNameColumnTitle, vm.settings.entityNameColumnTitle); | ||
161 | + } else { | ||
162 | + vm.entityNameColumnTitle = $translate.instant('entity.entity-name'); | ||
163 | + } | ||
164 | + | ||
160 | vm.displayEntityType = angular.isDefined(vm.settings.displayEntityType) ? vm.settings.displayEntityType : true; | 165 | vm.displayEntityType = angular.isDefined(vm.settings.displayEntityType) ? vm.settings.displayEntityType : true; |
161 | vm.displayPagination = angular.isDefined(vm.settings.displayPagination) ? vm.settings.displayPagination : true; | 166 | vm.displayPagination = angular.isDefined(vm.settings.displayPagination) ? vm.settings.displayPagination : true; |
162 | 167 | ||
@@ -185,6 +190,8 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | @@ -185,6 +190,8 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | ||
185 | //var mdDarkIcon = mdDarkSecondary; | 190 | //var mdDarkIcon = mdDarkSecondary; |
186 | var mdDarkDivider = defaultColor.setAlpha(0.12).toRgbString(); | 191 | var mdDarkDivider = defaultColor.setAlpha(0.12).toRgbString(); |
187 | 192 | ||
193 | + //md-icon.md-default-theme, md-icon { | ||
194 | + | ||
188 | var cssString = 'table.md-table th.md-column {\n'+ | 195 | var cssString = 'table.md-table th.md-column {\n'+ |
189 | 'color: ' + mdDarkSecondary + ';\n'+ | 196 | 'color: ' + mdDarkSecondary + ';\n'+ |
190 | '}\n'+ | 197 | '}\n'+ |
@@ -204,6 +211,9 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | @@ -204,6 +211,9 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | ||
204 | 'table.md-table td.md-cell.md-checkbox-cell md-checkbox:not(.md-checked) .md-icon {\n'+ | 211 | 'table.md-table td.md-cell.md-checkbox-cell md-checkbox:not(.md-checked) .md-icon {\n'+ |
205 | 'border-color: ' + mdDarkSecondary + ';\n'+ | 212 | 'border-color: ' + mdDarkSecondary + ';\n'+ |
206 | '}\n'+ | 213 | '}\n'+ |
214 | + 'table.md-table td.md-cell.tb-action-cell button.md-icon-button md-icon {\n'+ | ||
215 | + 'color: ' + mdDarkSecondary + ';\n'+ | ||
216 | + '}\n'+ | ||
207 | 'table.md-table td.md-cell.md-placeholder {\n'+ | 217 | 'table.md-table td.md-cell.md-placeholder {\n'+ |
208 | 'color: ' + mdDarkDisabled + ';\n'+ | 218 | 'color: ' + mdDarkDisabled + ';\n'+ |
209 | '}\n'+ | 219 | '}\n'+ |
@@ -261,11 +271,37 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | @@ -261,11 +271,37 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | ||
261 | } | 271 | } |
262 | 272 | ||
263 | function onRowClick($event, entity) { | 273 | function onRowClick($event, entity) { |
274 | + if ($event) { | ||
275 | + $event.stopPropagation(); | ||
276 | + } | ||
264 | if (vm.currentEntity != entity) { | 277 | if (vm.currentEntity != entity) { |
265 | vm.currentEntity = entity; | 278 | vm.currentEntity = entity; |
279 | + var descriptors = vm.ctx.actionsApi.getActionDescriptors('rowClick'); | ||
280 | + if (descriptors.length) { | ||
281 | + var entityId; | ||
282 | + var entityName; | ||
283 | + if (vm.currentEntity) { | ||
284 | + entityId = vm.currentEntity.id; | ||
285 | + entityName = vm.currentEntity.entityName; | ||
286 | + } | ||
287 | + vm.ctx.actionsApi.handleWidgetAction($event, descriptors[0], entityId, entityName); | ||
288 | + } | ||
266 | } | 289 | } |
267 | } | 290 | } |
268 | 291 | ||
292 | + function onActionButtonClick($event, entity, actionDescriptor) { | ||
293 | + if ($event) { | ||
294 | + $event.stopPropagation(); | ||
295 | + } | ||
296 | + var entityId; | ||
297 | + var entityName; | ||
298 | + if (entity) { | ||
299 | + entityId = entity.id; | ||
300 | + entityName = entity.entityName; | ||
301 | + } | ||
302 | + vm.ctx.actionsApi.handleWidgetAction($event, actionDescriptor, entityId, entityName); | ||
303 | + } | ||
304 | + | ||
269 | function isCurrent(entity) { | 305 | function isCurrent(entity) { |
270 | return (vm.currentEntity && entity && vm.currentEntity.id && entity.id) && | 306 | return (vm.currentEntity && entity && vm.currentEntity.id && entity.id) && |
271 | (vm.currentEntity.id.id === entity.id.id); | 307 | (vm.currentEntity.id.id === entity.id.id); |
@@ -393,13 +429,7 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | @@ -393,13 +429,7 @@ function EntitiesTableWidgetController($element, $scope, $filter, $mdMedia, $tra | ||
393 | } | 429 | } |
394 | vm.dataKeys.push(dataKey); | 430 | vm.dataKeys.push(dataKey); |
395 | 431 | ||
396 | - var translationId = types.translate.customTranslationsPrefix + dataKey.label; | ||
397 | - var translation = $translate.instant(translationId); | ||
398 | - if (translation != translationId) { | ||
399 | - dataKey.title = translation + ''; | ||
400 | - } else { | ||
401 | - dataKey.title = dataKey.label; | ||
402 | - } | 432 | + dataKey.title = utils.customTranslation(dataKey.label, dataKey.label); |
403 | 433 | ||
404 | var keySettings = dataKey.settings; | 434 | var keySettings = dataKey.settings; |
405 | 435 |
@@ -41,10 +41,10 @@ | @@ -41,10 +41,10 @@ | ||
41 | <table md-table> | 41 | <table md-table> |
42 | <thead md-head md-order="vm.query.order" md-on-reorder="vm.onReorder"> | 42 | <thead md-head md-order="vm.query.order" md-on-reorder="vm.onReorder"> |
43 | <tr md-row> | 43 | <tr md-row> |
44 | - <th md-column ng-if="vm.displayEntityName" md-order-by="entityName"><span translate>entity.entity-name</span></th> | 44 | + <th md-column ng-if="vm.displayEntityName" md-order-by="entityName"><span>{{vm.entityNameColumnTitle}}</span></th> |
45 | <th md-column ng-if="vm.displayEntityType" md-order-by="entityType"><span translate>entity.entity-type</span></th> | 45 | <th md-column ng-if="vm.displayEntityType" md-order-by="entityType"><span translate>entity.entity-type</span></th> |
46 | <th md-column md-order-by="{{ key.name }}" ng-repeat="key in vm.dataKeys"><span>{{ key.title }}</span></th> | 46 | <th md-column md-order-by="{{ key.name }}" ng-repeat="key in vm.dataKeys"><span>{{ key.title }}</span></th> |
47 | - <th md-column ng-if="vm.displayActions"><span> </span></th> | 47 | + <th md-column ng-if="vm.actionCellDescriptors.length"><span> </span></th> |
48 | </tr> | 48 | </tr> |
49 | </thead> | 49 | </thead> |
50 | <tbody md-body> | 50 | <tbody md-body> |
@@ -57,14 +57,18 @@ | @@ -57,14 +57,18 @@ | ||
57 | ng-style="vm.cellStyle(entity, key)" | 57 | ng-style="vm.cellStyle(entity, key)" |
58 | ng-bind-html="vm.cellContent(entity, key)"> | 58 | ng-bind-html="vm.cellContent(entity, key)"> |
59 | </td> | 59 | </td> |
60 | - <td md-cell ng-if="vm.displayActions" class="tb-action-cell"> | ||
61 | - <!--md-button class="md-icon-button" aria-label="{{ 'entity.details' | translate }}" | ||
62 | - ng-click="vm.openEntityDetails($event, entity)"> | ||
63 | - <md-icon aria-label="{{ 'entity.details' | translate }}" class="material-icons">more_horiz</md-icon> | 60 | + <td md-cell ng-if="vm.actionCellDescriptors.length" class="tb-action-cell" |
61 | + ng-style="{minWidth: vm.actionCellDescriptors.length*36+'px', | ||
62 | + maxWidth: vm.actionCellDescriptors.length*36+'px', | ||
63 | + width: vm.actionCellDescriptors.length*36+'px'}"> | ||
64 | + <md-button class="md-icon-button" ng-repeat="actionDescriptor in vm.actionCellDescriptors" | ||
65 | + aria-label="{{ actionDescriptor.displayName }}" | ||
66 | + ng-click="vm.onActionButtonClick($event, entity, actionDescriptor)"> | ||
67 | + <md-icon aria-label="{{ actionDescriptor.displayName }}" class="material-icons">{{actionDescriptor.icon}}</md-icon> | ||
64 | <md-tooltip md-direction="top"> | 68 | <md-tooltip md-direction="top"> |
65 | - {{ 'entity.details' | translate }} | 69 | + {{ actionDescriptor.displayName }} |
66 | </md-tooltip> | 70 | </md-tooltip> |
67 | - </md-button--> | 71 | + </md-button> |
68 | </td> | 72 | </td> |
69 | </tr> | 73 | </tr> |
70 | </tbody> | 74 | </tbody> |