diff --git a/ui/src/app/common/thirdparty-fix.js b/ui/src/app/common/thirdparty-fix.js index b00a7822c5..af4222c140 100644 --- a/ui/src/app/common/thirdparty-fix.js +++ b/ui/src/app/common/thirdparty-fix.js @@ -15,10 +15,13 @@ */ import tinycolor from 'tinycolor2'; +import moment from 'moment'; export default angular.module('thingsboard.thirdpartyFix', []) .factory('Fullscreen', Fullscreen) .factory('$mdColorPicker', mdColorPicker) + .provider('$mdpDatePicker', mdpDatePicker) + .provider('$mdpTimePicker', mdpTimePicker) .name; /*@ngInject*/ @@ -193,3 +196,264 @@ function mdColorPicker($q, $mdDialog, mdColorPickerHistory) { /* eslint-enable angular/definedundefined */ } + +function DatePickerCtrl($scope, $mdDialog, $mdMedia, $timeout, currentDate, options) { + var self = this; + + this.date = moment(currentDate); + this.minDate = options.minDate && moment(options.minDate).isValid() ? moment(options.minDate) : null; + this.maxDate = options.maxDate && moment(options.maxDate).isValid() ? moment(options.maxDate) : null; + this.displayFormat = options.displayFormat || "ddd, MMM DD"; + this.dateFilter = angular.isFunction(options.dateFilter) ? options.dateFilter : null; + this.selectingYear = false; + + // validate min and max date + if (this.minDate && this.maxDate) { + if (this.maxDate.isBefore(this.minDate)) { + this.maxDate = moment(this.minDate).add(1, 'days'); + } + } + + if (this.date) { + // check min date + if (this.minDate && this.date.isBefore(this.minDate)) { + this.date = moment(this.minDate); + } + + // check max date + if (this.maxDate && this.date.isAfter(this.maxDate)) { + this.date = moment(this.maxDate); + } + } + + this.yearItems = { + currentIndex_: 0, + PAGE_SIZE: 5, + START: (self.minDate ? self.minDate.year() : 1900), + END: (self.maxDate ? self.maxDate.year() : 0), + getItemAtIndex: function(index) { + if(this.currentIndex_ < index) + this.currentIndex_ = index; + + return this.START + index; + }, + getLength: function() { + return Math.min( + this.currentIndex_ + Math.floor(this.PAGE_SIZE / 2), + Math.abs(this.START - this.END) + 1 + ); + } + }; + + $scope.$mdMedia = $mdMedia; + $scope.year = this.date.year(); + + this.selectYear = function(year) { + self.date.year(year); + $scope.year = year; + self.selectingYear = false; + self.animate(); + }; + + this.showYear = function() { + self.yearTopIndex = (self.date.year() - self.yearItems.START) + Math.floor(self.yearItems.PAGE_SIZE / 2); + self.yearItems.currentIndex_ = (self.date.year() - self.yearItems.START) + 1; + self.selectingYear = true; + }; + + this.showCalendar = function() { + self.selectingYear = false; + }; + + this.cancel = function() { + $mdDialog.cancel(); + }; + + this.confirm = function() { + var date = this.date; + + if (this.minDate && this.date.isBefore(this.minDate)) { + date = moment(this.minDate); + } + + if (this.maxDate && this.date.isAfter(this.maxDate)) { + date = moment(this.maxDate); + } + + $mdDialog.hide(date.toDate()); + }; + + this.animate = function() { + self.animating = true; + $timeout(angular.noop).then(function() { + self.animating = false; + }) + }; +} + +/*@ngInject*/ +function mdpDatePicker() { + var LABEL_OK = "OK", + LABEL_CANCEL = "Cancel", + DISPLAY_FORMAT = "ddd, MMM DD"; + + this.setDisplayFormat = function(format) { + DISPLAY_FORMAT = format; + }; + + this.setOKButtonLabel = function(label) { + LABEL_OK = label; + }; + + this.setCancelButtonLabel = function(label) { + LABEL_CANCEL = label; + }; + + /*@ngInject*/ + this.$get = function($mdDialog) { + var datePicker = function(currentDate, options) { + if (!angular.isDate(currentDate)) currentDate = Date.now(); + if (!angular.isObject(options)) options = {}; + + options.displayFormat = DISPLAY_FORMAT; + + return $mdDialog.show({ + controller: ['$scope', '$mdDialog', '$mdMedia', '$timeout', 'currentDate', 'options', DatePickerCtrl], + controllerAs: 'datepicker', + clickOutsideToClose: true, + template: '' + + '' + + '' + + '' + + '{{ datepicker.date.format(\'YYYY\') }}' + + '{{ datepicker.date.format(datepicker.displayFormat) }} ' + + '' + + '' + + '' + + '' + + '' + + '' + + '{{ item }}' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + LABEL_CANCEL + '' + + '' + LABEL_OK + '' + + '' + + '' + + '' + + '', + targetEvent: options.targetEvent, + locals: { + currentDate: currentDate, + options: options + }, + multiple: true + }); + }; + + return datePicker; + }; + +} + +function TimePickerCtrl($scope, $mdDialog, time, autoSwitch, $mdMedia) { + var self = this; + this.VIEW_HOURS = 1; + this.VIEW_MINUTES = 2; + this.currentView = this.VIEW_HOURS; + this.time = moment(time); + this.autoSwitch = !!autoSwitch; + + this.clockHours = parseInt(this.time.format("h")); + this.clockMinutes = parseInt(this.time.minutes()); + + $scope.$mdMedia = $mdMedia; + + this.switchView = function() { + self.currentView = self.currentView == self.VIEW_HOURS ? self.VIEW_MINUTES : self.VIEW_HOURS; + }; + + this.setAM = function() { + if(self.time.hours() >= 12) + self.time.hour(self.time.hour() - 12); + }; + + this.setPM = function() { + if(self.time.hours() < 12) + self.time.hour(self.time.hour() + 12); + }; + + this.cancel = function() { + $mdDialog.cancel(); + }; + + this.confirm = function() { + $mdDialog.hide(this.time.toDate()); + }; +} + +/*@ngInject*/ +function mdpTimePicker() { + var LABEL_OK = "OK", + LABEL_CANCEL = "Cancel"; + + this.setOKButtonLabel = function(label) { + LABEL_OK = label; + }; + + this.setCancelButtonLabel = function(label) { + LABEL_CANCEL = label; + }; + + /*@ngInject*/ + this.$get = function($mdDialog) { + var timePicker = function(time, options) { + if(!angular.isDate(time)) time = Date.now(); + if (!angular.isObject(options)) options = {}; + + return $mdDialog.show({ + controller: ['$scope', '$mdDialog', 'time', 'autoSwitch', '$mdMedia', TimePickerCtrl], + controllerAs: 'timepicker', + clickOutsideToClose: true, + template: '' + + '' + + '' + + '' + + '{{ timepicker.time.format("h") }}:' + + '{{ timepicker.time.format("mm") }}' + + '' + + '' + + 'AM' + + 'PM' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + + '' + + '' + + '' + LABEL_CANCEL + '' + + '' + LABEL_OK + '' + + '' + + '' + + '' + + '', + targetEvent: options.targetEvent, + locals: { + time: time, + autoSwitch: options.autoSwitch + }, + multiple: true + }); + }; + + return timePicker; + }; +} diff --git a/ui/src/app/dashboard/dashboard.tpl.html b/ui/src/app/dashboard/dashboard.tpl.html index 79653a42c5..a1bb2688c0 100644 --- a/ui/src/app/dashboard/dashboard.tpl.html +++ b/ui/src/app/dashboard/dashboard.tpl.html @@ -74,6 +74,7 @@ settings diff --git a/ui/src/app/entity-view/entity-view.directive.js b/ui/src/app/entity-view/entity-view.directive.js index 25377f4cb4..761930e615 100644 --- a/ui/src/app/entity-view/entity-view.directive.js +++ b/ui/src/app/entity-view/entity-view.directive.js @@ -98,8 +98,8 @@ export default function EntityViewDirective($q, $compile, $templateCache, $filte if (newDate.getTime() > scope.maxStartTimeMs) { scope.startTimeMs = angular.copy(scope.maxStartTimeMs); } - updateMinMaxDates(); } + updateMinMaxDates(); }); scope.$watch('endTimeMs', function (newDate) { @@ -107,18 +107,24 @@ export default function EntityViewDirective($q, $compile, $templateCache, $filte if (newDate.getTime() < scope.minEndTimeMs) { scope.endTimeMs = angular.copy(scope.minEndTimeMs); } - updateMinMaxDates(); } + updateMinMaxDates(); }); function updateMinMaxDates() { - if (scope.endTimeMs) { - scope.maxStartTimeMs = angular.copy(new Date(scope.endTimeMs.getTime())); - scope.entityView.endTimeMs = scope.endTimeMs.getTime(); - } - if (scope.startTimeMs) { - scope.minEndTimeMs = angular.copy(new Date(scope.startTimeMs.getTime())); - scope.entityView.startTimeMs = scope.startTimeMs.getTime(); + if (scope.entityView) { + if (scope.endTimeMs) { + scope.maxStartTimeMs = angular.copy(new Date(scope.endTimeMs.getTime())); + scope.entityView.endTimeMs = scope.endTimeMs.getTime(); + } else { + scope.entityView.endTimeMs = 0; + } + if (scope.startTimeMs) { + scope.minEndTimeMs = angular.copy(new Date(scope.startTimeMs.getTime())); + scope.entityView.startTimeMs = scope.startTimeMs.getTime(); + } else { + scope.entityView.startTimeMs = 0; + } } } diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index b3c89c7729..30e1eb119b 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -774,6 +774,7 @@ }, "entity-view": { "entity-view": "Entity View", + "entity-view-required": "Entity view is required.", "entity-views": "Entity Views", "management": "Entity View management", "view-entity-views": "View Entity Views",