Commit f6fccebd52d4dae21f0a936a14f96b044ee49cb5

Authored by Igor Kulikov
1 parent 02be0edf

UI fixes

@@ -15,10 +15,13 @@ @@ -15,10 +15,13 @@
15 */ 15 */
16 16
17 import tinycolor from 'tinycolor2'; 17 import tinycolor from 'tinycolor2';
  18 +import moment from 'moment';
18 19
19 export default angular.module('thingsboard.thirdpartyFix', []) 20 export default angular.module('thingsboard.thirdpartyFix', [])
20 .factory('Fullscreen', Fullscreen) 21 .factory('Fullscreen', Fullscreen)
21 .factory('$mdColorPicker', mdColorPicker) 22 .factory('$mdColorPicker', mdColorPicker)
  23 + .provider('$mdpDatePicker', mdpDatePicker)
  24 + .provider('$mdpTimePicker', mdpTimePicker)
22 .name; 25 .name;
23 26
24 /*@ngInject*/ 27 /*@ngInject*/
@@ -193,3 +196,264 @@ function mdColorPicker($q, $mdDialog, mdColorPickerHistory) { @@ -193,3 +196,264 @@ function mdColorPicker($q, $mdDialog, mdColorPickerHistory) {
193 196
194 /* eslint-enable angular/definedundefined */ 197 /* eslint-enable angular/definedundefined */
195 } 198 }
  199 +
  200 +function DatePickerCtrl($scope, $mdDialog, $mdMedia, $timeout, currentDate, options) {
  201 + var self = this;
  202 +
  203 + this.date = moment(currentDate);
  204 + this.minDate = options.minDate && moment(options.minDate).isValid() ? moment(options.minDate) : null;
  205 + this.maxDate = options.maxDate && moment(options.maxDate).isValid() ? moment(options.maxDate) : null;
  206 + this.displayFormat = options.displayFormat || "ddd, MMM DD";
  207 + this.dateFilter = angular.isFunction(options.dateFilter) ? options.dateFilter : null;
  208 + this.selectingYear = false;
  209 +
  210 + // validate min and max date
  211 + if (this.minDate && this.maxDate) {
  212 + if (this.maxDate.isBefore(this.minDate)) {
  213 + this.maxDate = moment(this.minDate).add(1, 'days');
  214 + }
  215 + }
  216 +
  217 + if (this.date) {
  218 + // check min date
  219 + if (this.minDate && this.date.isBefore(this.minDate)) {
  220 + this.date = moment(this.minDate);
  221 + }
  222 +
  223 + // check max date
  224 + if (this.maxDate && this.date.isAfter(this.maxDate)) {
  225 + this.date = moment(this.maxDate);
  226 + }
  227 + }
  228 +
  229 + this.yearItems = {
  230 + currentIndex_: 0,
  231 + PAGE_SIZE: 5,
  232 + START: (self.minDate ? self.minDate.year() : 1900),
  233 + END: (self.maxDate ? self.maxDate.year() : 0),
  234 + getItemAtIndex: function(index) {
  235 + if(this.currentIndex_ < index)
  236 + this.currentIndex_ = index;
  237 +
  238 + return this.START + index;
  239 + },
  240 + getLength: function() {
  241 + return Math.min(
  242 + this.currentIndex_ + Math.floor(this.PAGE_SIZE / 2),
  243 + Math.abs(this.START - this.END) + 1
  244 + );
  245 + }
  246 + };
  247 +
  248 + $scope.$mdMedia = $mdMedia;
  249 + $scope.year = this.date.year();
  250 +
  251 + this.selectYear = function(year) {
  252 + self.date.year(year);
  253 + $scope.year = year;
  254 + self.selectingYear = false;
  255 + self.animate();
  256 + };
  257 +
  258 + this.showYear = function() {
  259 + self.yearTopIndex = (self.date.year() - self.yearItems.START) + Math.floor(self.yearItems.PAGE_SIZE / 2);
  260 + self.yearItems.currentIndex_ = (self.date.year() - self.yearItems.START) + 1;
  261 + self.selectingYear = true;
  262 + };
  263 +
  264 + this.showCalendar = function() {
  265 + self.selectingYear = false;
  266 + };
  267 +
  268 + this.cancel = function() {
  269 + $mdDialog.cancel();
  270 + };
  271 +
  272 + this.confirm = function() {
  273 + var date = this.date;
  274 +
  275 + if (this.minDate && this.date.isBefore(this.minDate)) {
  276 + date = moment(this.minDate);
  277 + }
  278 +
  279 + if (this.maxDate && this.date.isAfter(this.maxDate)) {
  280 + date = moment(this.maxDate);
  281 + }
  282 +
  283 + $mdDialog.hide(date.toDate());
  284 + };
  285 +
  286 + this.animate = function() {
  287 + self.animating = true;
  288 + $timeout(angular.noop).then(function() {
  289 + self.animating = false;
  290 + })
  291 + };
  292 +}
  293 +
  294 +/*@ngInject*/
  295 +function mdpDatePicker() {
  296 + var LABEL_OK = "OK",
  297 + LABEL_CANCEL = "Cancel",
  298 + DISPLAY_FORMAT = "ddd, MMM DD";
  299 +
  300 + this.setDisplayFormat = function(format) {
  301 + DISPLAY_FORMAT = format;
  302 + };
  303 +
  304 + this.setOKButtonLabel = function(label) {
  305 + LABEL_OK = label;
  306 + };
  307 +
  308 + this.setCancelButtonLabel = function(label) {
  309 + LABEL_CANCEL = label;
  310 + };
  311 +
  312 + /*@ngInject*/
  313 + this.$get = function($mdDialog) {
  314 + var datePicker = function(currentDate, options) {
  315 + if (!angular.isDate(currentDate)) currentDate = Date.now();
  316 + if (!angular.isObject(options)) options = {};
  317 +
  318 + options.displayFormat = DISPLAY_FORMAT;
  319 +
  320 + return $mdDialog.show({
  321 + controller: ['$scope', '$mdDialog', '$mdMedia', '$timeout', 'currentDate', 'options', DatePickerCtrl],
  322 + controllerAs: 'datepicker',
  323 + clickOutsideToClose: true,
  324 + template: '<md-dialog aria-label="" class="mdp-datepicker" ng-class="{ \'portrait\': !$mdMedia(\'gt-xs\') }">' +
  325 + '<md-dialog-content layout="row" layout-wrap>' +
  326 + '<div layout="column" layout-align="start center">' +
  327 + '<md-toolbar layout-align="start start" flex class="mdp-datepicker-date-wrapper md-hue-1 md-primary" layout="column">' +
  328 + '<span class="mdp-datepicker-year" ng-click="datepicker.showYear()" ng-class="{ \'active\': datepicker.selectingYear }">{{ datepicker.date.format(\'YYYY\') }}</span>' +
  329 + '<span class="mdp-datepicker-date" ng-click="datepicker.showCalendar()" ng-class="{ \'active\': !datepicker.selectingYear }">{{ datepicker.date.format(datepicker.displayFormat) }}</span> ' +
  330 + '</md-toolbar>' +
  331 + '</div>' +
  332 + '<div>' +
  333 + '<div class="mdp-datepicker-select-year mdp-animation-zoom" layout="column" layout-align="center start" ng-if="datepicker.selectingYear">' +
  334 + '<md-virtual-repeat-container md-auto-shrink md-top-index="datepicker.yearTopIndex">' +
  335 + '<div flex md-virtual-repeat="item in datepicker.yearItems" md-on-demand class="repeated-year">' +
  336 + '<span class="md-button" ng-click="datepicker.selectYear(item)" md-ink-ripple ng-class="{ \'md-primary current\': item == year }">{{ item }}</span>' +
  337 + '</div>' +
  338 + '</md-virtual-repeat-container>' +
  339 + '</div>' +
  340 + '<mdp-calendar ng-if="!datepicker.selectingYear" class="mdp-animation-zoom" date="datepicker.date" min-date="datepicker.minDate" date-filter="datepicker.dateFilter" max-date="datepicker.maxDate"></mdp-calendar>' +
  341 + '<md-dialog-actions layout="row">' +
  342 + '<span flex></span>' +
  343 + '<md-button ng-click="datepicker.cancel()" aria-label="' + LABEL_CANCEL + '">' + LABEL_CANCEL + '</md-button>' +
  344 + '<md-button ng-click="datepicker.confirm()" class="md-primary" aria-label="' + LABEL_OK + '">' + LABEL_OK + '</md-button>' +
  345 + '</md-dialog-actions>' +
  346 + '</div>' +
  347 + '</md-dialog-content>' +
  348 + '</md-dialog>',
  349 + targetEvent: options.targetEvent,
  350 + locals: {
  351 + currentDate: currentDate,
  352 + options: options
  353 + },
  354 + multiple: true
  355 + });
  356 + };
  357 +
  358 + return datePicker;
  359 + };
  360 +
  361 +}
  362 +
  363 +function TimePickerCtrl($scope, $mdDialog, time, autoSwitch, $mdMedia) {
  364 + var self = this;
  365 + this.VIEW_HOURS = 1;
  366 + this.VIEW_MINUTES = 2;
  367 + this.currentView = this.VIEW_HOURS;
  368 + this.time = moment(time);
  369 + this.autoSwitch = !!autoSwitch;
  370 +
  371 + this.clockHours = parseInt(this.time.format("h"));
  372 + this.clockMinutes = parseInt(this.time.minutes());
  373 +
  374 + $scope.$mdMedia = $mdMedia;
  375 +
  376 + this.switchView = function() {
  377 + self.currentView = self.currentView == self.VIEW_HOURS ? self.VIEW_MINUTES : self.VIEW_HOURS;
  378 + };
  379 +
  380 + this.setAM = function() {
  381 + if(self.time.hours() >= 12)
  382 + self.time.hour(self.time.hour() - 12);
  383 + };
  384 +
  385 + this.setPM = function() {
  386 + if(self.time.hours() < 12)
  387 + self.time.hour(self.time.hour() + 12);
  388 + };
  389 +
  390 + this.cancel = function() {
  391 + $mdDialog.cancel();
  392 + };
  393 +
  394 + this.confirm = function() {
  395 + $mdDialog.hide(this.time.toDate());
  396 + };
  397 +}
  398 +
  399 +/*@ngInject*/
  400 +function mdpTimePicker() {
  401 + var LABEL_OK = "OK",
  402 + LABEL_CANCEL = "Cancel";
  403 +
  404 + this.setOKButtonLabel = function(label) {
  405 + LABEL_OK = label;
  406 + };
  407 +
  408 + this.setCancelButtonLabel = function(label) {
  409 + LABEL_CANCEL = label;
  410 + };
  411 +
  412 + /*@ngInject*/
  413 + this.$get = function($mdDialog) {
  414 + var timePicker = function(time, options) {
  415 + if(!angular.isDate(time)) time = Date.now();
  416 + if (!angular.isObject(options)) options = {};
  417 +
  418 + return $mdDialog.show({
  419 + controller: ['$scope', '$mdDialog', 'time', 'autoSwitch', '$mdMedia', TimePickerCtrl],
  420 + controllerAs: 'timepicker',
  421 + clickOutsideToClose: true,
  422 + template: '<md-dialog aria-label="" class="mdp-timepicker" ng-class="{ \'portrait\': !$mdMedia(\'gt-xs\') }">' +
  423 + '<md-dialog-content layout-gt-xs="row" layout-wrap>' +
  424 + '<md-toolbar layout-gt-xs="column" layout-xs="row" layout-align="center center" flex class="mdp-timepicker-time md-hue-1 md-primary">' +
  425 + '<div class="mdp-timepicker-selected-time">' +
  426 + '<span ng-class="{ \'active\': timepicker.currentView == timepicker.VIEW_HOURS }" ng-click="timepicker.currentView = timepicker.VIEW_HOURS">{{ timepicker.time.format("h") }}</span>:' +
  427 + '<span ng-class="{ \'active\': timepicker.currentView == timepicker.VIEW_MINUTES }" ng-click="timepicker.currentView = timepicker.VIEW_MINUTES">{{ timepicker.time.format("mm") }}</span>' +
  428 + '</div>' +
  429 + '<div layout="column" class="mdp-timepicker-selected-ampm">' +
  430 + '<span ng-click="timepicker.setAM()" ng-class="{ \'active\': timepicker.time.hours() < 12 }">AM</span>' +
  431 + '<span ng-click="timepicker.setPM()" ng-class="{ \'active\': timepicker.time.hours() >= 12 }">PM</span>' +
  432 + '</div>' +
  433 + '</md-toolbar>' +
  434 + '<div>' +
  435 + '<div class="mdp-clock-switch-container" ng-switch="timepicker.currentView" layout layout-align="center center">' +
  436 + '<mdp-clock class="mdp-animation-zoom" auto-switch="timepicker.autoSwitch" time="timepicker.time" type="hours" ng-switch-when="1"></mdp-clock>' +
  437 + '<mdp-clock class="mdp-animation-zoom" auto-switch="timepicker.autoSwitch" time="timepicker.time" type="minutes" ng-switch-when="2"></mdp-clock>' +
  438 + '</div>' +
  439 +
  440 + '<md-dialog-actions layout="row">' +
  441 + '<span flex></span>' +
  442 + '<md-button ng-click="timepicker.cancel()" aria-label="' + LABEL_CANCEL + '">' + LABEL_CANCEL + '</md-button>' +
  443 + '<md-button ng-click="timepicker.confirm()" class="md-primary" aria-label="' + LABEL_OK + '">' + LABEL_OK + '</md-button>' +
  444 + '</md-dialog-actions>' +
  445 + '</div>' +
  446 + '</md-dialog-content>' +
  447 + '</md-dialog>',
  448 + targetEvent: options.targetEvent,
  449 + locals: {
  450 + time: time,
  451 + autoSwitch: options.autoSwitch
  452 + },
  453 + multiple: true
  454 + });
  455 + };
  456 +
  457 + return timePicker;
  458 + };
  459 +}
@@ -74,6 +74,7 @@ @@ -74,6 +74,7 @@
74 <md-icon aria-label="{{ 'dashboard.settings' | translate }}" class="material-icons">settings</md-icon> 74 <md-icon aria-label="{{ 'dashboard.settings' | translate }}" class="material-icons">settings</md-icon>
75 </md-button> 75 </md-button>
76 <tb-dashboard-select ng-show="!vm.isEdit && !vm.widgetEditMode && vm.displayDashboardsSelect()" 76 <tb-dashboard-select ng-show="!vm.isEdit && !vm.widgetEditMode && vm.displayDashboardsSelect()"
  77 + md-theme="tb-dark"
77 ng-model="vm.currentDashboardId" 78 ng-model="vm.currentDashboardId"
78 dashboards-scope="{{vm.currentDashboardScope}}" 79 dashboards-scope="{{vm.currentDashboardScope}}"
79 customer-id="vm.currentCustomerId"> 80 customer-id="vm.currentCustomerId">
@@ -98,8 +98,8 @@ export default function EntityViewDirective($q, $compile, $templateCache, $filte @@ -98,8 +98,8 @@ export default function EntityViewDirective($q, $compile, $templateCache, $filte
98 if (newDate.getTime() > scope.maxStartTimeMs) { 98 if (newDate.getTime() > scope.maxStartTimeMs) {
99 scope.startTimeMs = angular.copy(scope.maxStartTimeMs); 99 scope.startTimeMs = angular.copy(scope.maxStartTimeMs);
100 } 100 }
101 - updateMinMaxDates();  
102 } 101 }
  102 + updateMinMaxDates();
103 }); 103 });
104 104
105 scope.$watch('endTimeMs', function (newDate) { 105 scope.$watch('endTimeMs', function (newDate) {
@@ -107,18 +107,24 @@ export default function EntityViewDirective($q, $compile, $templateCache, $filte @@ -107,18 +107,24 @@ export default function EntityViewDirective($q, $compile, $templateCache, $filte
107 if (newDate.getTime() < scope.minEndTimeMs) { 107 if (newDate.getTime() < scope.minEndTimeMs) {
108 scope.endTimeMs = angular.copy(scope.minEndTimeMs); 108 scope.endTimeMs = angular.copy(scope.minEndTimeMs);
109 } 109 }
110 - updateMinMaxDates();  
111 } 110 }
  111 + updateMinMaxDates();
112 }); 112 });
113 113
114 function updateMinMaxDates() { 114 function updateMinMaxDates() {
115 - if (scope.endTimeMs) {  
116 - scope.maxStartTimeMs = angular.copy(new Date(scope.endTimeMs.getTime()));  
117 - scope.entityView.endTimeMs = scope.endTimeMs.getTime();  
118 - }  
119 - if (scope.startTimeMs) {  
120 - scope.minEndTimeMs = angular.copy(new Date(scope.startTimeMs.getTime()));  
121 - scope.entityView.startTimeMs = scope.startTimeMs.getTime(); 115 + if (scope.entityView) {
  116 + if (scope.endTimeMs) {
  117 + scope.maxStartTimeMs = angular.copy(new Date(scope.endTimeMs.getTime()));
  118 + scope.entityView.endTimeMs = scope.endTimeMs.getTime();
  119 + } else {
  120 + scope.entityView.endTimeMs = 0;
  121 + }
  122 + if (scope.startTimeMs) {
  123 + scope.minEndTimeMs = angular.copy(new Date(scope.startTimeMs.getTime()));
  124 + scope.entityView.startTimeMs = scope.startTimeMs.getTime();
  125 + } else {
  126 + scope.entityView.startTimeMs = 0;
  127 + }
122 } 128 }
123 } 129 }
124 130
@@ -774,6 +774,7 @@ @@ -774,6 +774,7 @@
774 }, 774 },
775 "entity-view": { 775 "entity-view": {
776 "entity-view": "Entity View", 776 "entity-view": "Entity View",
  777 + "entity-view-required": "Entity view is required.",
777 "entity-views": "Entity Views", 778 "entity-views": "Entity Views",
778 "management": "Entity View management", 779 "management": "Entity View management",
779 "view-entity-views": "View Entity Views", 780 "view-entity-views": "View Entity Views",