diff --git a/application/src/main/data/json/system/widget_bundles/date.json b/application/src/main/data/json/system/widget_bundles/date.json
new file mode 100644
index 0000000000..cdde7bcad3
--- /dev/null
+++ b/application/src/main/data/json/system/widget_bundles/date.json
@@ -0,0 +1,25 @@
+{
+ "widgetsBundle": {
+ "alias": "date",
+ "title": "Date",
+ "image": null
+ },
+ "widgetTypes": [
+ {
+ "alias": "date_range_navigator",
+ "name": "Date-range-navigator",
+ "descriptor": {
+ "type": "static",
+ "sizeX": 5,
+ "sizeY": 5.5,
+ "resources": [],
+ "templateHtml": "",
+ "templateCss": "",
+ "controllerScript": "self.onInit = function() {\n scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}",
+ "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"hidePicker\": {\n \"title\": \"Hide date range picker\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"onePanel\": {\n \"title\": \"Date range picker one panel\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"autoConfirm\": {\n \"title\": \"Date range picker auto confirm\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"showTemplate\": {\n \"title\": \"Date range picker show template\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"firstDayOfWeek\": {\n \"title\": \"First day of the week\",\n \"type\": \"number\",\n \"default\": 1\n },\n \"hideInterval\": {\n \"title\": \"Hide interval\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"initialInterval\": {\n\t\t\t\t\"title\": \"Initial interval\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"default\": \"week\"\n\t\t\t},\n \"hideStepSize\": {\n \"title\": \"Hide step size\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"stepSize\": {\n\t\t\t\t\"title\": \"Initial step size\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"default\": \"day\"\n\t\t\t},\n \"hideLabels\": {\n \"title\": \"Hide labels\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"useSessionStorage\": {\n \"title\": \"Use session storage\",\n \"type\": \"boolean\",\n \"default\": true\n }\n }\n },\n \"form\": [\n \"hidePicker\",\n\t\t\"onePanel\",\n\t\t\"autoConfirm\",\n\t\t\"showTemplate\",\n\t\t\"firstDayOfWeek\",\n \"hideInterval\",\n {\n\t\t\t\"key\": \"initialInterval\",\n\t\t\t\"type\": \"rc-select\",\n\t\t\t\"multiple\": false,\n\t\t\t\"items\": [\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"hour\",\n\t\t\t\t\t\"label\": \"Hour\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"day\",\n\t\t\t\t\t\"label\": \"Day\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"week\",\n\t\t\t\t\t\"label\": \"Week\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"twoWeeks\",\n\t\t\t\t\t\"label\": \"2 weeks\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"month\",\n\t\t\t\t\t\"label\": \"Month\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"threeMonths\",\n\t\t\t\t\t\"label\": \"3 months\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"sixMonths\",\n\t\t\t\t\t\"label\": \"6 months\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n \"hideStepSize\",\n {\n\t\t\t\"key\": \"stepSize\",\n\t\t\t\"type\": \"rc-select\",\n\t\t\t\"multiple\": false,\n\t\t\t\"items\": [\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"hour\",\n\t\t\t\t\t\"label\": \"Hour\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"day\",\n\t\t\t\t\t\"label\": \"Day\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"week\",\n\t\t\t\t\t\"label\": \"Week\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"twoWeeks\",\n\t\t\t\t\t\"label\": \"2 weeks\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"month\",\n\t\t\t\t\t\"label\": \"Month\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"threeMonths\",\n\t\t\t\t\t\"label\": \"3 months\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"sixMonths\",\n\t\t\t\t\t\"label\": \"6 months\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t\"hideLabels\",\n\t\t\"useSessionStorage\"\n ]\n}",
+ "dataKeySettingsSchema": "{}\n",
+ "defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"defaultInterval\":\"week\",\"stepSize\":\"day\"},\"title\":\"Date-range-navigator\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 39846f4c4e..84f64c627d 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -5239,12 +5239,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -5259,17 +5261,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -5386,7 +5391,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -5398,6 +5404,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -5412,6 +5419,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -5419,12 +5427,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -5443,6 +5453,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -5523,7 +5534,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -5535,6 +5547,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -5656,6 +5669,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -8344,6 +8358,18 @@
"tinycolor2": "*"
}
},
+ "md-date-range-picker": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/md-date-range-picker/-/md-date-range-picker-0.8.4.tgz",
+ "integrity": "sha512-TgLyozMJypi92yvXaljLcermTFhd1+0rlaVwV+Duo0EplbKfDJfFF3WohWhB7VmPwJNP//o44sUlecY+r/ZvXA==",
+ "requires": {
+ "angular": "^1.5.8",
+ "angular-animate": "^1.5.8",
+ "angular-aria": "^1.5.8",
+ "angular-material": "^1.1.0",
+ "angular-messages": "^1.5.8"
+ }
+ },
"mdPickers": {
"version": "git://github.com/alenaksu/mdPickers.git#72592ae51c81a7260701055ea21870efa57fa7c8",
"from": "git://github.com/alenaksu/mdPickers.git#0.7.5"
diff --git a/ui/package.json b/ui/package.json
index 0a1f4512a1..b6701e4e61 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -67,6 +67,7 @@
"material-ui": "^0.16.1",
"material-ui-number-input": "^5.0.16",
"md-color-picker": "0.2.6",
+ "md-date-range-picker": "^0.8.4",
"mdPickers": "git://github.com/alenaksu/mdPickers.git#0.7.5",
"moment": "^2.15.0",
"ngFlowchart": "git://github.com/thingsboard/ngFlowchart.git#master",
diff --git a/ui/src/app/api/time.service.js b/ui/src/app/api/time.service.js
index 1acea59b5b..6d6fe8b730 100644
--- a/ui/src/app/api/time.service.js
+++ b/ui/src/app/api/time.service.js
@@ -256,13 +256,13 @@ function TimeService($translate, $http, $q, types) {
return timewindow;
}
- function toHistoryTimewindow(timewindow, startTimeMs, endTimeMs) {
-
- var interval = 0;
+ function toHistoryTimewindow(timewindow, startTimeMs, endTimeMs, interval) {
if (timewindow.history) {
- interval = timewindow.history.interval;
+ interval = angular.isDefined(interval) ? interval : timewindow.history.interval;
} else if (timewindow.realtime) {
interval = timewindow.realtime.interval;
+ } else {
+ interval = 0;
}
var aggType;
diff --git a/ui/src/app/api/widget.service.js b/ui/src/app/api/widget.service.js
index 70cf76ff1a..4859f7f409 100644
--- a/ui/src/app/api/widget.service.js
+++ b/ui/src/app/api/widget.service.js
@@ -23,6 +23,7 @@ import thingsboardAlarmsTableWidget from '../widget/lib/alarms-table-widget';
import thingsboardEntitiesTableWidget from '../widget/lib/entities-table-widget';
import thingsboardEntitiesHierarchyWidget from '../widget/lib/entities-hierarchy-widget';
import thingsboardExtensionsTableWidget from '../widget/lib/extensions-table-widget';
+import thingsboardDateRangeNavigatorWidget from '../widget/lib/date-range-navigator/date-range-navigator';
import thingsboardRpcWidgets from '../widget/lib/rpc';
@@ -35,6 +36,7 @@ import TbMapWidget from '../widget/lib/map-widget';
import TbMapWidgetV2 from '../widget/lib/map-widget2';
import TripAnimationWidget from '../widget/lib/tripAnimation/trip-animation-widget';
+
import 'jquery.terminal/js/jquery.terminal.min.js';
import 'jquery.terminal/css/jquery.terminal.min.css';
@@ -44,8 +46,10 @@ import cssjs from '../../vendor/css.js/css';
import thingsboardTypes from '../common/types.constant';
import thingsboardUtils from '../common/utils.service';
-export default angular.module('thingsboard.api.widget', ['oc.lazyLoad', thingsboardLedLight, thingsboardTimeseriesTableWidget,
- thingsboardAlarmsTableWidget, thingsboardEntitiesTableWidget, thingsboardEntitiesHierarchyWidget, thingsboardExtensionsTableWidget, thingsboardRpcWidgets, thingsboardTypes, thingsboardUtils, TripAnimationWidget])
+export default angular.module('thingsboard.api.widget', ['oc.lazyLoad', thingsboardLedLight,
+ thingsboardTimeseriesTableWidget, thingsboardAlarmsTableWidget, thingsboardEntitiesTableWidget,
+ thingsboardEntitiesHierarchyWidget, thingsboardExtensionsTableWidget, thingsboardDateRangeNavigatorWidget,
+ thingsboardRpcWidgets, thingsboardTypes, thingsboardUtils, TripAnimationWidget])
.factory('widgetService', WidgetService)
.name;
diff --git a/ui/src/app/app.js b/ui/src/app/app.js
index 7081415ff5..3fd4115a2b 100644
--- a/ui/src/app/app.js
+++ b/ui/src/app/app.js
@@ -29,6 +29,7 @@ import 'angular-translate-storage-cookie';
import 'angular-translate-handler-log';
import 'angular-translate-interpolation-messageformat';
import 'md-color-picker';
+import 'md-date-range-picker';
import mdPickers from 'mdPickers';
import ngSanitize from 'angular-sanitize';
import FBAngular from 'angular-fullscreen';
@@ -66,6 +67,7 @@ import 'angular-hotkeys/build/hotkeys.min.css';
import 'angular-carousel/dist/angular-carousel.min.css';
import 'angular-material-expansion-panel/dist/md-expansion-panel.min.css';
import 'ngFlowchart/dist/flowchart.css';
+import 'md-date-range-picker/src/md-date-range-picker.css';
import '../scss/main.scss';
import thingsboardThirdpartyFix from './common/thirdparty-fix';
@@ -107,6 +109,7 @@ angular.module('thingsboard', [
angularSocialshare,
'pascalprecht.translate',
'mdColorPicker',
+ 'ngMaterialDateRangePicker',
mdPickers,
ngSanitize,
FBAngular.name,
diff --git a/ui/src/app/components/dashboard.directive.js b/ui/src/app/components/dashboard.directive.js
index 5ffd218acc..831ecc29f6 100644
--- a/ui/src/app/components/dashboard.directive.js
+++ b/ui/src/app/components/dashboard.directive.js
@@ -219,14 +219,14 @@ function DashboardController($scope, $rootScope, $element, $timeout, $mdMedia, $
}
}, 0);
},
- onUpdateTimewindow: function(startTimeMs, endTimeMs) {
+ onUpdateTimewindow: function(startTimeMs, endTimeMs, interval) {
if (!vm.originalDashboardTimewindow) {
vm.originalDashboardTimewindow = angular.copy(vm.dashboardTimewindow);
}
$timeout(function() {
- vm.dashboardTimewindow = timeService.toHistoryTimewindow(vm.dashboardTimewindow, startTimeMs, endTimeMs);
+ vm.dashboardTimewindow = timeService.toHistoryTimewindow(vm.dashboardTimewindow, startTimeMs, endTimeMs, interval);
}, 0);
- }
+ },
};
addResizeListener(gridsterParent[0], onGridsterParentResize); // eslint-disable-line no-undef
diff --git a/ui/src/app/components/widget/widget.controller.js b/ui/src/app/components/widget/widget.controller.js
index a58064320c..b5ad7ac0d5 100644
--- a/ui/src/app/components/widget/widget.controller.js
+++ b/ui/src/app/components/widget/widget.controller.js
@@ -76,9 +76,9 @@ export default function WidgetController($scope, $state, $timeout, $window, $ele
defaultSubscription: null,
dashboardTimewindow: dashboardTimewindow,
timewindowFunctions: {
- onUpdateTimewindow: function(startTimeMs, endTimeMs) {
+ onUpdateTimewindow: function(startTimeMs, endTimeMs, interval) {
if (widgetContext.defaultSubscription) {
- widgetContext.defaultSubscription.onUpdateTimewindow(startTimeMs, endTimeMs);
+ widgetContext.defaultSubscription.onUpdateTimewindow(startTimeMs, endTimeMs, interval);
}
},
onResetTimewindow: function() {
diff --git a/ui/src/app/locale/locale.constant-de_DE.json b/ui/src/app/locale/locale.constant-de_DE.json
index ff55d1bee3..9b3fee13c2 100644
--- a/ui/src/app/locale/locale.constant-de_DE.json
+++ b/ui/src/app/locale/locale.constant-de_DE.json
@@ -1549,6 +1549,65 @@
"widget-type-file": "Widget-Typdatei",
"invalid-widget-type-file-error": "Widget-Typ kann nicht importiert werden: Ungültige Datenstruktur des Widget-Typs."
},
+ "widgets": {
+ "date-range-navigator": {
+ "localizationMap": {
+ "Sun": "So.",
+ "Mon": "Mo.",
+ "Tue": "Di.",
+ "Wed": "Mi.",
+ "Thu": "Do.",
+ "Fri": "Fr.",
+ "Sat": "Sa.",
+ "Jan": "Jan.",
+ "Feb": "Feb.",
+ "Mar": "März",
+ "Apr": "Apr.",
+ "May": "Mai",
+ "Jun": "Juni",
+ "Jul": "Juli",
+ "Aug": "Aug.",
+ "Sep": "Sep.",
+ "Oct": "Okt.",
+ "Nov": "Nov.",
+ "Dec": "Dez.",
+ "January": "Januar",
+ "February": "Februar",
+ "March": "März",
+ "April": "April",
+ "June": "Juni",
+ "July": "Juli",
+ "August": "August",
+ "September": "September",
+ "October": "Oktober",
+ "November": "November",
+ "December": "Dezember",
+ "Custom Date Range": "Benutzerdefinierter Datumsbereich",
+ "Date Range Template": "Datumsbereichsvorlage",
+ "Today": "Heute",
+ "Yesterday": "Gestern",
+ "This Week": "Diese Woche",
+ "Last Week": "Letzte Woche",
+ "This Month": "Diesen Monat",
+ "Last Month": "Im vergangenen Monat",
+ "Year": "Jahr",
+ "This Year": "Dieses Jahr",
+ "Last Year": "Vergangenes Jahr",
+ "Date picker": "Datumsauswahl",
+ "Hour": "Stunde",
+ "Day": "Tag",
+ "Week": "Woche",
+ "2 weeks": "2 Wochen",
+ "Month": "Monat",
+ "3 months": "3 Monate",
+ "6 months": "6 Monate",
+ "Custom interval": "Benutzerdefiniertes Intervall",
+ "Interval": "Intervall",
+ "Step size": "Schrittlänge",
+ "Ok": "Ok"
+ }
+ }
+ },
"icon": {
"icon": "Symbol",
"select-icon": "Symbol auswählen",
diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json
index 0f951d39c7..bc31a90de0 100644
--- a/ui/src/app/locale/locale.constant-en_US.json
+++ b/ui/src/app/locale/locale.constant-en_US.json
@@ -1555,6 +1555,65 @@
"widget-type-file": "Widget type file",
"invalid-widget-type-file-error": "Unable to import widget type: Invalid widget type data structure."
},
+ "widgets": {
+ "date-range-navigator": {
+ "localizationMap": {
+ "Sun": "Sun",
+ "Mon": "Mon",
+ "Tue": "Tue",
+ "Wed": "Wed",
+ "Thu": "Thu",
+ "Fri": "Fri",
+ "Sat": "Sat",
+ "Jan": "Jan",
+ "Feb": "Feb",
+ "Mar": "Mar",
+ "Apr": "Apr",
+ "May": "May",
+ "Jun": "Jun",
+ "Jul": "Jul",
+ "Aug": "Aug",
+ "Sep": "Sep",
+ "Oct": "Oct",
+ "Nov": "Nov",
+ "Dec": "Dec",
+ "January": "January",
+ "February": "February",
+ "March": "March",
+ "April": "April",
+ "June": "June",
+ "July": "July",
+ "August": "August",
+ "September": "September",
+ "October": "October",
+ "November": "November",
+ "December": "December",
+ "Custom Date Range": "Custom Date Range",
+ "Date Range Template": "Date Range Template",
+ "Today": "Today",
+ "Yesterday": "Yesterday",
+ "This Week": "This Week",
+ "Last Week": "Last Week",
+ "This Month": "This Month",
+ "Last Month": "Last Month",
+ "Year": "Year",
+ "This Year": "This Year",
+ "Last Year": "Last Year",
+ "Date picker": "Date picker",
+ "Hour": "Hour",
+ "Day": "Day",
+ "Week": "Week",
+ "2 weeks": "2 Weeks",
+ "Month": "Month",
+ "3 months": "3 Months",
+ "6 months": "6 Months",
+ "Custom interval": "Custom interval",
+ "Interval": "Interval",
+ "Step size": "Step size",
+ "Ok": "Ok"
+ }
+ }
+ },
"icon": {
"icon": "Icon",
"select-icon": "Select icon",
diff --git a/ui/src/app/locale/locale.constant-es_ES.json b/ui/src/app/locale/locale.constant-es_ES.json
index cc5dd7f405..5dd0f51623 100644
--- a/ui/src/app/locale/locale.constant-es_ES.json
+++ b/ui/src/app/locale/locale.constant-es_ES.json
@@ -1549,6 +1549,65 @@
"widget-type-file": "Archivo de tipo de widget",
"invalid-widget-type-file-error": "No se puede importar tipo de widget: Estructura de datos del tipo de widget es inválida."
},
+ "widgets": {
+ "date-range-navigator": {
+ "localizationMap": {
+ "Sun": "Dom.",
+ "Mon": "Lun.",
+ "Tue": "Mar.",
+ "Wed": "Mié",
+ "Thu": "Jue.",
+ "Fri": "Vie.",
+ "Sat": "Sáb.",
+ "Jan": "Ene.",
+ "Feb": "Feb.",
+ "Mar": "Mar.",
+ "Apr": "Abr.",
+ "May": "May.",
+ "Jun": "Jun.",
+ "Jul": "Jul.",
+ "Aug": "Ago.",
+ "Sep": "Sept.",
+ "Oct": "Oct.",
+ "Nov": "Nov.",
+ "Dec": "Dic.",
+ "January": "Enero",
+ "February": "Febrero",
+ "March": "Marzo",
+ "April": "Abril",
+ "June": "Junio",
+ "July": "Julio",
+ "August": "Agosto",
+ "September": "Septiembre",
+ "October": "Octubre",
+ "November": "Noviembre",
+ "December": "Diciembre",
+ "Custom Date Range": "Intervalo de fechas personalizado",
+ "Date Range Template": "Plantilla de rango de fechas",
+ "Today": "Hoy",
+ "Yesterday": "Ayer",
+ "This Week": "Esta semana",
+ "Last Week": "La semana pasada",
+ "This Month": "Este mes",
+ "Last Month": "El mes pasado",
+ "Year": "Año",
+ "This Year": "Este año",
+ "Last Year": "Último",
+ "Date picker": "Date picker",
+ "Hour": "Hora",
+ "Day": "Día",
+ "Week": "Semana",
+ "2 weeks": "2 Semanas",
+ "Month": "Mes",
+ "3 months": "3 Meses",
+ "6 months": "6 Meses",
+ "Custom interval": "Intervalo personalizado",
+ "Interval": "Intervalo",
+ "Step size": "Numero de pie",
+ "Ok": "De acuerdo"
+ }
+ }
+ },
"icon": {
"icon": "Icono",
"select-icon": "Seleccionar icono",
diff --git a/ui/src/app/locale/locale.constant-fa_IR.json b/ui/src/app/locale/locale.constant-fa_IR.json
index 80c8c421cb..a3173c1197 100644
--- a/ui/src/app/locale/locale.constant-fa_IR.json
+++ b/ui/src/app/locale/locale.constant-fa_IR.json
@@ -1549,6 +1549,65 @@
"widget-type-file": "پرونده نوع ويجت",
"invalid-widget-type-file-error": ".وارد کردن نوع ويجت ممکن نيست: ساختار داده نوع ويجت نامعتبر است"
},
+ "widgets": {
+ "date-range-navigator": {
+ "localizationMap": {
+ "Sun": "یکشنبه",
+ "Mon": "دوشنبه",
+ "Tue": "سهشنبه",
+ "Wed": "چهارشنبه",
+ "Thu": "پنجشنبه",
+ "Fri": "جمعه",
+ "Sat": "شنبه",
+ "Jan": "ژانویهٔ",
+ "Feb": "فوریهٔ",
+ "Mar": "مارس",
+ "Apr": "آوریل",
+ "May": "مهٔ",
+ "Jun": "ژوئن",
+ "Jul": "ژوئیهٔ",
+ "Aug": "اوت",
+ "Sep": "سپتامبر",
+ "Oct": "اکتبر",
+ "Nov": "نوامبر",
+ "Dec": "دسامبر",
+ "January": "January",
+ "February": "February",
+ "March": "March",
+ "April": "April",
+ "June": "June",
+ "July": "July",
+ "August": "August",
+ "September": "September",
+ "October": "October",
+ "November": "November",
+ "December": "December",
+ "Custom Date Range": "Custom Date Range",
+ "Date Range Template": "Date Range Template",
+ "Today": "Today",
+ "Yesterday": "Yesterday",
+ "This Week": "This Week",
+ "Last Week": "Last Week",
+ "This Month": "This Month",
+ "Last Month": "Last Month",
+ "Year": "Year",
+ "This Year": "This Year",
+ "Last Year": "Last Year",
+ "Date picker": "Date picker",
+ "Hour": "Hour",
+ "Day": "Day",
+ "Week": "Week",
+ "2 weeks": "2 weeks",
+ "Month": "Month",
+ "3 months": "3 months",
+ "6 months": "6 months",
+ "Custom interval": "Custom interval",
+ "Interval": "Interval",
+ "Step size": "Step size",
+ "Ok": "Ok"
+ }
+ }
+ },
"icon": {
"icon": "آيکون",
"select-icon": "انتخاب آيکون",
diff --git a/ui/src/app/locale/locale.constant-fr_FR.json b/ui/src/app/locale/locale.constant-fr_FR.json
index e10dd54c08..a9159e323f 100644
--- a/ui/src/app/locale/locale.constant-fr_FR.json
+++ b/ui/src/app/locale/locale.constant-fr_FR.json
@@ -1437,6 +1437,65 @@
"invalid-widget-type-file-error": "Impossible d'importer le type de widget: structure de données de type widget invalide.",
"widget-type-file": "Fichier de type Widget"
},
+ "widgets": {
+ "date-range-navigator": {
+ "localizationMap": {
+ "Sun": "Dim.",
+ "Mon": "Lun.",
+ "Tue": "Mar.",
+ "Wed": "Mer.",
+ "Thu": "Jeu.",
+ "Fri": "Ven.",
+ "Sat": "Sam.",
+ "Jan": "Janv.",
+ "Feb": "Févr.",
+ "Mar": "Mars",
+ "Apr": "Avr.",
+ "May": "Mai",
+ "Jun": "Juin",
+ "Jul": "Juil.",
+ "Aug": "Août",
+ "Sep": "Sept.",
+ "Oct": "Oct.",
+ "Nov": "Nov.",
+ "Dec": "Déc.",
+ "January": "Janvier",
+ "February": "Février",
+ "March": "Mars",
+ "April": "Avril",
+ "June": "Juin",
+ "July": "Juillet",
+ "August": "Août",
+ "September": "Septembre",
+ "October": "Octobre",
+ "November": "Novembre",
+ "December": "Décembre",
+ "Custom Date Range": "Plage de dates personnalisée",
+ "Date Range Template": "Modèle de plage de dates",
+ "Today": "Aujourd'hui",
+ "Yesterday": "Hier",
+ "This Week": "Cette semaine",
+ "Last Week": "La semaine dernière",
+ "This Month": "Ce mois-ci",
+ "Last Month": "Le mois dernier",
+ "Year": "Année",
+ "This Year": "Cette année",
+ "Last Year": "L'année dernière",
+ "Date picker": "Sélecteur de date",
+ "Hour": "Heure",
+ "Day": "Journée",
+ "Week": "La semaine",
+ "2 weeks": "2 Semaines",
+ "Month": "Mois",
+ "3 months": "3 Mois",
+ "6 months": "6 Mois",
+ "Custom interval": "Intervalle personnalisé",
+ "Interval": "Intervalle",
+ "Step size": "Taille de pas",
+ "Ok": "Ok"
+ }
+ }
+ },
"widgets-bundle": {
"add": "Ajouter un groupe de widgets",
"add-widgets-bundle-text": "Ajouter un nouveau groupe de widgets",
diff --git a/ui/src/app/locale/locale.constant-it_IT.json b/ui/src/app/locale/locale.constant-it_IT.json
index e2cdb9c3ab..aac0132ab8 100644
--- a/ui/src/app/locale/locale.constant-it_IT.json
+++ b/ui/src/app/locale/locale.constant-it_IT.json
@@ -1554,6 +1554,65 @@
"widget-type-file": "File tipo di widget",
"invalid-widget-type-file-error": "Impossibile importare un tipo di widget: struttura dati del widget non valida."
},
+ "widgets": {
+ "date-range-navigator": {
+ "localizationMap": {
+ "Sun": "Dom",
+ "Mon": "Lun",
+ "Tue": "Mar",
+ "Wed": "Mer",
+ "Thu": "Gio",
+ "Fri": "Ven",
+ "Sat": "Sab",
+ "Jan": "Gen",
+ "Feb": "Feb",
+ "Mar": "Mar",
+ "Apr": "Apr",
+ "May": "Mag",
+ "Jun": "Giu",
+ "Jul": "Lug",
+ "Aug": "Ago",
+ "Sep": "Set",
+ "Oct": "Ott",
+ "Nov": "Nov",
+ "Dec": "Dic",
+ "January": "Gennaio",
+ "February": "Febbraio",
+ "March": "Marzo",
+ "April": "Aprile",
+ "June": "Giugno",
+ "July": "Luglio",
+ "August": "Agosto",
+ "September": "Settembre",
+ "October": "Ottobre",
+ "November": "Novembre",
+ "December": "Dicembre",
+ "Custom Date Range": "Intervallo di date personalizzato",
+ "Date Range Template": "Modello di intervallo di date",
+ "Today": "Oggi",
+ "Yesterday": "Ieri",
+ "This Week": "Questa settimana",
+ "Last Week": "La settimana scorsa",
+ "This Month": "Questo mese",
+ "Last Month": "Lo scorso mese",
+ "Year": "Anno",
+ "This Year": "Quest'anno",
+ "Last Year": "L'anno scorso",
+ "Date picker": "Date picker",
+ "Hour": "Ora",
+ "Day": "Giorno",
+ "Week": "Settimana",
+ "2 weeks": "2 Settimane",
+ "Month": "Mese",
+ "3 months": "3 Mesi",
+ "6 months": "6 Mesi",
+ "Custom interval": "Intervallo personalizzato",
+ "Interval": "Intervallo",
+ "Step size": "Dimensione del passo",
+ "Ok": "Ok"
+ }
+ }
+ },
"icon": {
"icon": "Icona",
"select-icon": "Seleziona icona",
diff --git a/ui/src/app/locale/locale.constant-ja_JA.json b/ui/src/app/locale/locale.constant-ja_JA.json
index 9345359109..7395725867 100644
--- a/ui/src/app/locale/locale.constant-ja_JA.json
+++ b/ui/src/app/locale/locale.constant-ja_JA.json
@@ -1432,6 +1432,65 @@
"widget-type-file": "ウィジェットタイプファイル",
"invalid-widget-type-file-error": "ウィジェットタイプをインポートできません:ウィジェットタイプのデータ構造が無効です。"
},
+ "widgets": {
+ "date-range-navigator": {
+ "localizationMap": {
+ "Sun": "日",
+ "Mon": "月",
+ "Tue": "火",
+ "Wed": "水",
+ "Thu": "木",
+ "Fri": "金",
+ "Sat": "土",
+ "Jan": "1月",
+ "Feb": "2月",
+ "Mar": "3月",
+ "Apr": "4月",
+ "May": "5月",
+ "Jun": "6月",
+ "Jul": "7月",
+ "Aug": "8月",
+ "Sep": "9月",
+ "Oct": "10月",
+ "Nov": "11月",
+ "Dec": "12月",
+ "January": "1月",
+ "February": "2月",
+ "March": "行進",
+ "April": "4月",
+ "June": "六月",
+ "July": "7月",
+ "August": "8月",
+ "September": "9月",
+ "October": "10月",
+ "November": "11月",
+ "December": "12月",
+ "Custom Date Range": "カスタム期間",
+ "Date Range Template": "日付範囲テンプレート",
+ "Today": "今日",
+ "Yesterday": "昨日",
+ "This Week": "今週",
+ "Last Week": "先週",
+ "This Month": "今月",
+ "Last Month": "先月",
+ "Year": "年",
+ "This Year": "今年",
+ "Last Year": "昨年",
+ "Date picker": "日付ピッカー",
+ "Hour": "時",
+ "Day": "日",
+ "Week": "週間",
+ "2 weeks": "2週間",
+ "Month": "月",
+ "3 months": "3ヶ月",
+ "6 months": "6ヵ月",
+ "Custom interval": "カスタム間隔",
+ "Interval": "間隔",
+ "Step size": "刻み幅",
+ "Ok": "Ok"
+ }
+ }
+ },
"icon": {
"icon": "アイコン",
"select-icon": "選択アイコン",
diff --git a/ui/src/app/locale/locale.constant-ko_KR.json b/ui/src/app/locale/locale.constant-ko_KR.json
index 7ef4935df5..e2186b2c32 100644
--- a/ui/src/app/locale/locale.constant-ko_KR.json
+++ b/ui/src/app/locale/locale.constant-ko_KR.json
@@ -1308,6 +1308,65 @@
"widget-type-file": "위젯 타입 파일",
"invalid-widget-type-file-error": "위젯 타입을 가져오기 할 수 없습니다.: 잘못된 위젯 타입 데이터 구조입니다."
},
+ "widgets": {
+ "date-range-navigator": {
+ "localizationMap": {
+ "Sun": "일",
+ "Mon": "월",
+ "Tue": "화",
+ "Wed": "수",
+ "Thu": "목",
+ "Fri": "금",
+ "Sat": "토",
+ "Jan": "1월",
+ "Feb": "2월",
+ "Mar": "3월",
+ "Apr": "4월",
+ "May": "5월",
+ "Jun": "6월",
+ "Jul": "7월",
+ "Aug": "8월",
+ "Sep": "9월",
+ "Oct": "10월",
+ "Nov": "11월",
+ "Dec": "12월",
+ "January": "일월",
+ "February": "이월",
+ "March": "행진",
+ "April": "4 월",
+ "June": "유월",
+ "July": "칠월",
+ "August": "팔월",
+ "September": "구월",
+ "October": "십월",
+ "November": "십일월",
+ "December": "12 월",
+ "Custom Date Range": "맞춤 기간",
+ "Date Range Template": "기간 템플릿",
+ "Today": "오늘",
+ "Yesterday": "어제",
+ "This Week": "이번 주",
+ "Last Week": "지난주",
+ "This Month": "이번 달",
+ "Last Month": "지난 달",
+ "Year": "년",
+ "This Year": "올해",
+ "Last Year": "작년",
+ "Date picker": "날짜 선택기",
+ "Hour": "시간",
+ "Day": "일",
+ "Week": "주",
+ "2 weeks": "이주",
+ "Month": "달",
+ "3 months": "3 개월",
+ "6 months": "6 개월",
+ "Custom interval": "사용자 지정 간격",
+ "Interval": "간격",
+ "Step size": "단계 크기",
+ "Ok": "Ok"
+ }
+ }
+ },
"icon": {
"icon": "Icon",
"select-icon": "Select icon",
diff --git a/ui/src/app/locale/locale.constant-ru_RU.json b/ui/src/app/locale/locale.constant-ru_RU.json
index 7477c6d70e..a69a094403 100644
--- a/ui/src/app/locale/locale.constant-ru_RU.json
+++ b/ui/src/app/locale/locale.constant-ru_RU.json
@@ -1548,6 +1548,65 @@
"widget-type-file": "Файл типа виджета",
"invalid-widget-type-file-error": "Не удалось импортировать виджет: неизвестная схема данных типа виджета."
},
+ "widgets": {
+ "date-range-navigator": {
+ "localizationMap": {
+ "Sun": "Вс",
+ "Mon": "Пн",
+ "Tue": "Вт",
+ "Wed": "Ср",
+ "Thu": "Чт",
+ "Fri": "Пт",
+ "Sat": "Сб",
+ "Jan": "Янв.",
+ "Feb": "Февр.",
+ "Mar": "Март",
+ "Apr": "Апр.",
+ "May": "Май",
+ "Jun": "Июнь",
+ "Jul": "Июль",
+ "Aug": "Авг.",
+ "Sep": "Сент.",
+ "Oct": "Окт.",
+ "Nov": "Нояб.",
+ "Dec": "Дек.",
+ "January": "Январь",
+ "February": "Февраль",
+ "March": "Март",
+ "April": "Апрель",
+ "June": "Июнь",
+ "July": "Июль",
+ "August": "Август",
+ "September": "Сентябрь",
+ "October": "Октября",
+ "November": "Ноябрь",
+ "December": "Декабрь",
+ "Custom Date Range": "Пользовательский диапазон дат",
+ "Date Range Template": "Шаблон диапазона дат",
+ "Today": "Сегодня",
+ "Yesterday": "Вчера",
+ "This Week": "На этой неделе",
+ "Last Week": "Прошлая неделя",
+ "This Month": "Этот месяц",
+ "Last Month": "Прошлый месяц",
+ "Year": "Год",
+ "This Year": "В этом году",
+ "Last Year": "Прошлый год",
+ "Date picker": "Выбор даты",
+ "Hour": "Час",
+ "Day": "День",
+ "Week": "Неделю",
+ "2 weeks": "2 Недели",
+ "Month": "Месяц",
+ "3 months": "3 Месяца",
+ "6 months": "6 Месяцев",
+ "Custom interval": "Пользовательский интервал",
+ "Interval": "Интервал",
+ "Step size": "Размер шага",
+ "Ok": "Ok"
+ }
+ }
+ },
"icon": {
"icon": "Иконка",
"select-icon": "Выбрать иконку",
diff --git a/ui/src/app/locale/locale.constant-tr_TR.json b/ui/src/app/locale/locale.constant-tr_TR.json
index 52dc6cc10a..2652ba5359 100644
--- a/ui/src/app/locale/locale.constant-tr_TR.json
+++ b/ui/src/app/locale/locale.constant-tr_TR.json
@@ -1514,6 +1514,65 @@
"widget-type-file": "Gösterge türü dosyası",
"invalid-widget-type-file-error": "Gösterge türü içe aktarılamadı: Geçersiz gösterge türü veri yapısı."
},
+ "widgets": {
+ "date-range-navigator": {
+ "localizationMap": {
+ "Sun": "Paz",
+ "Mon": "Pzt",
+ "Tue": "Sal",
+ "Wed": "Çar",
+ "Thu": "Per",
+ "Fri": "Cum",
+ "Sat": "Cmt",
+ "Jan": "Oca",
+ "Feb": "Şub",
+ "Mar": "Mar",
+ "Apr": "Nis",
+ "May": "May",
+ "Jun": "Haz",
+ "Jul": "Tem",
+ "Aug": "Ağu",
+ "Sep": "Eyl",
+ "Oct": "Eki",
+ "Nov": "Kas",
+ "Dec": "Ara",
+ "January": "Ocak",
+ "February": "Şubat",
+ "March": "Mart",
+ "April": "Nisan",
+ "June": "Haziran",
+ "July": "Temmuz",
+ "August": "Ağustos",
+ "September": "Eylül",
+ "October": "Ekim",
+ "November": "Kasım",
+ "December": "Aralık",
+ "Custom Date Range": "Özel Tarih Aralığı",
+ "Date Range Template": "Tarih Aralığı Şablonu",
+ "Today": "Bugün",
+ "Yesterday": "Dün",
+ "This Week": "Bu hafta",
+ "Last Week": "Geçen hafta",
+ "This Month": "Bu ay",
+ "Last Month": "Geçen ay",
+ "Year": "Yıl",
+ "This Year": "Bu yıl",
+ "Last Year": "Geçen yıl",
+ "Date picker": "Tarih seçici",
+ "Hour": "Saat",
+ "Day": "Gün",
+ "Week": "Hafta",
+ "2 weeks": "2 Hafta",
+ "Month": "Ay",
+ "3 months": "3 Ay",
+ "6 months": "6 Ay",
+ "Custom interval": "Özel aralık",
+ "Interval": "Aralık",
+ "Step size": "Adım boyutu",
+ "Ok": "Ok"
+ }
+ }
+ },
"icon": {
"icon": "İkon",
"select-icon": "İkon seç",
diff --git a/ui/src/app/locale/locale.constant-zh_CN.json b/ui/src/app/locale/locale.constant-zh_CN.json
index 41089cf611..836908de60 100644
--- a/ui/src/app/locale/locale.constant-zh_CN.json
+++ b/ui/src/app/locale/locale.constant-zh_CN.json
@@ -1418,6 +1418,65 @@
"widget-type-file": "部件类型文件",
"invalid-widget-type-file-error": "无法导入部件类型:无效的部件类型数据结构。"
},
+ "widgets": {
+ "date-range-navigator": {
+ "localizationMap": {
+ "Sun": "周日",
+ "Mon": "周一",
+ "Tue": "周二",
+ "Wed": "周三",
+ "Thu": "周四",
+ "Fri": "周五",
+ "Sat": "周六",
+ "Jan": "1月",
+ "Feb": "2月",
+ "Mar": "3月",
+ "Apr": "4月",
+ "May": "5月",
+ "Jun": "6月",
+ "Jul": "7月",
+ "Aug": "8月",
+ "Sep": "9月",
+ "Oct": "10月",
+ "Nov": "11月",
+ "Dec": "12月",
+ "January": "一月",
+ "February": "二月",
+ "March": "游行",
+ "April": "四月",
+ "June": "六月",
+ "July": "七月",
+ "August": "八月",
+ "September": "九月",
+ "October": "十月",
+ "November": "十一月",
+ "December": "十二月",
+ "Custom Date Range": "自定义日期范围",
+ "Date Range Template": "日期范围模板",
+ "Today": "今天",
+ "Yesterday": "昨天",
+ "This Week": "本星期",
+ "Last Week": "上个星期",
+ "This Month": "这个月",
+ "Last Month": "上个月",
+ "Year": "年",
+ "This Year": "今年",
+ "Last Year": "去年",
+ "Date picker": "日期选择器",
+ "Hour": "小时",
+ "Day": "天",
+ "Week": "周",
+ "2 weeks": "2周",
+ "Month": "月",
+ "3 months": "3个月",
+ "6 months": "6个月",
+ "Custom interval": "自定义间隔",
+ "Interval": "间隔",
+ "Step size": "一步的大小",
+ "Ok": "Ok"
+ }
+ }
+ },
"icon": {
"icon": "图标",
"select-icon": "选择图标",
diff --git a/ui/src/app/widget/lib/date-range-navigator/date-range-navigator.js b/ui/src/app/widget/lib/date-range-navigator/date-range-navigator.js
new file mode 100644
index 0000000000..fbd90a030e
--- /dev/null
+++ b/ui/src/app/widget/lib/date-range-navigator/date-range-navigator.js
@@ -0,0 +1,301 @@
+/*
+ * Copyright © 2016-2019 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* eslint-disable import/no-unresolved, import/default */
+import widgetTpl from './date-range-navigator.tpl.html';
+import './date-range-navigator.scss';
+/* eslint-enable import/no-unresolved, import/default */
+
+export default angular.module('thingsboard.widgets.dateRangeNavigator', [])
+ .directive('dateRangeNavigatorWidget', DateRangeNavigatorWidget)
+ .name;
+
+/*@ngInject*/
+function DateRangeNavigatorWidget() {
+ return {
+ restrict: "E",
+ scope: true,
+ bindToController: {
+ tableId: '=',
+ ctx: '='
+ },
+ controller: DateRangeNavigatorWidgetController,
+ controllerAs: 'vm',
+ templateUrl: widgetTpl
+ };
+}
+
+/*@ngInject*/
+function DateRangeNavigatorWidgetController($scope, $window, $filter) {
+
+ let vm = this,
+ hour = 3600000,
+ day = 86400000,
+ week = 604800000,
+ month = 2629743000,
+ words = [
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat",
+ "Sun",
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December",
+ "Ok",
+ 'Custom Date Range',
+ 'Date Range Template',
+ 'Today',
+ 'Yesterday',
+ 'This Week',
+ 'Last Week',
+ 'Month',
+ 'This Month',
+ 'Last Month',
+ 'Year',
+ 'This Year',
+ 'Last Year'
+ ],
+ firstUpdate = true;
+
+ $scope.datesMap = {
+ hour: {
+ ts: hour,
+ label: "Hour"
+ },
+ day: {
+ ts: day,
+ label: "Day"
+ },
+ week: {
+ ts: week,
+ label: "Week"
+ },
+ twoWeeks: {
+ ts: week * 2,
+ label: "2 weeks"
+ },
+ month: {
+ ts: month,
+ label: "Month"
+ },
+ threeMonths: {
+ ts: month * 3,
+ label: "3 months"
+ },
+ sixMonths: {
+ ts: month * 6,
+ label: "6 months"
+ }
+ };
+ $scope.advancedModel = {};
+ $scope.endRestrictionDate = Date.now();
+ $scope.localizationMap = getLocalizationMap();
+
+ $scope.changeInterval = changeInterval;
+ $scope.goForth = goForth;
+ $scope.goBack = goBack;
+ $scope.triggerChange = triggerChange;
+
+ $scope.$watch('vm.ctx', function () {
+ if (vm.ctx && vm.ctx.dashboard.dashboardTimewindow) {
+ $scope.settings = vm.ctx.widgetConfig.settings;
+ let selection;
+ if ($scope.settings.useSessionStorage) {
+ selection = readFromStorage('date-range');
+ }
+ if (selection) {
+ $scope.advancedModel = {
+ selectedTemplateName: selection.name,
+ dateStart: selection.start,
+ dateEnd: selection.end
+ };
+ } else {
+ let end = new Date();
+ end.setHours(23, 59, 59, 999);
+
+ let formattedDate = getFormattedDate(
+ (end.getTime() + 1) - $scope.datesMap[$scope.settings.initialInterval || "week"].ts,
+ end.getTime()
+ );
+ $scope.advancedModel = formattedDate;
+ }
+ $scope.selectedStepSize = $scope.datesMap[$scope.settings.stepSize || "day"].ts;
+
+ widgetContextTimewindowSync();
+ }
+ });
+
+ $scope.$on('dashboardTimewindowChanged', function () {
+ $scope.dashboardTimewindowChanged = true;
+ widgetContextTimewindowSync();
+ });
+
+ function getLocalizationMap() {
+ let result = {};
+
+ words.forEach(function (key) {
+ result[key] = $filter('translate')('widgets.date-range-navigator.localizationMap.' + key);
+ });
+
+ return result;
+ }
+
+ function triggerChange() {
+ updateTimewindow($scope.advancedModel.dateStart.getTime(), $scope.advancedModel.dateEnd.getTime() + day - 1);
+ }
+
+ function widgetContextTimewindowSync() {
+ if (vm.ctx && vm.ctx.dashboardTimewindow && $scope.dashboardTimewindowChanged &&
+ vm.ctx.dashboard.dashboardTimewindow.history &&
+ vm.ctx.dashboard.dashboardTimewindow.history.fixedTimewindow) {
+
+
+ if (!firstUpdate) {
+ updateAdvancedModel();
+ }
+ updateDateInterval();
+ if ($scope.settings.useSessionStorage) {
+ updateStorageDate();
+ }
+ if (firstUpdate) {
+ updateTimewindow($scope.advancedModel.dateStart.getTime(), $scope.advancedModel.dateEnd.getTime());
+ firstUpdate = false;
+ }
+ }
+ }
+
+ function getFormattedDate(startTime, endTime) {
+ var template;
+
+ let startDate = new Date(startTime);
+ let endDate = new Date(endTime);
+
+ if (getDateDiff(startDate, endDate) === 0) {
+ template = $filter('date')(startDate, 'dd MMM yyyy');
+ } else {
+ template = $filter('date')(
+ startDate,
+ 'dd' + (startDate.getMonth() !== endDate.getMonth() || startDate.getFullYear() !== endDate.getFullYear() ? ' MMM' : '') + (startDate.getFullYear() !== endDate.getFullYear() ? ' yyyy' : '')
+ )
+ + ' - ' +
+ $filter('date')(
+ endDate,
+ 'dd MMM yyyy'
+ );
+ }
+
+ return {
+ selectedTemplateName: template,
+ dateStart: startDate,
+ dateEnd: endDate
+ };
+ }
+
+ function readFromStorage(itemKey) {
+ if ($window.sessionStorage.getItem(itemKey)) {
+ let selection = angular.fromJson($window.sessionStorage.getItem(itemKey));
+ selection.start = new Date(parseInt(selection.start));
+ selection.end = new Date(parseInt(selection.end));
+ return selection;
+ }
+
+ return undefined;
+ }
+
+ function goForth() {
+ let startTime = vm.ctx.dashboard.dashboardTimewindow.history ?
+ vm.ctx.dashboard.dashboardTimewindow.history.fixedTimewindow.startTimeMs :
+ $scope.advancedModel.dateStart.getTime();
+ let endTime = vm.ctx.dashboard.dashboardTimewindow.history ?
+ vm.ctx.dashboard.dashboardTimewindow.history.fixedTimewindow.endTimeMs :
+ $scope.advancedModel.dateEnd.getTime();
+ updateTimewindow(startTime + $scope.selectedStepSize, endTime + $scope.selectedStepSize);
+ }
+
+ function goBack() {
+ let startTime = vm.ctx.dashboard.dashboardTimewindow.history ?
+ vm.ctx.dashboard.dashboardTimewindow.history.fixedTimewindow.startTimeMs :
+ $scope.advancedModel.dateStart.getTime();
+ let endTime = vm.ctx.dashboard.dashboardTimewindow.history ?
+ vm.ctx.dashboard.dashboardTimewindow.history.fixedTimewindow.endTimeMs :
+ $scope.advancedModel.dateEnd.getTime();
+ updateTimewindow(startTime - $scope.selectedStepSize, endTime - $scope.selectedStepSize);
+ }
+
+ function changeInterval() {
+ let endTime = vm.ctx.dashboard.dashboardTimewindow.history ?
+ vm.ctx.dashboard.dashboardTimewindow.history.fixedTimewindow.endTimeMs :
+ $scope.advancedModel.dateEnd.getTime();
+ updateTimewindow(endTime - $scope.selectedDateInterval / 2, endTime + $scope.selectedDateInterval / 2);
+ }
+
+ function getDateDiff(date1, date2) {
+ if (!date1 || !date2) return;
+ var _d1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()),
+ _d2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
+ return _d2 - _d1;
+ }
+
+ function updateTimewindow(startTime, endTime) {
+ vm.ctx.dashboard.dashboardTimewindowApi.onUpdateTimewindow(startTime, endTime, 10);
+ }
+
+ function updateDateInterval() {
+ let interval = $scope.advancedModel.dateEnd.getTime() - $scope.advancedModel.dateStart.getTime();
+
+ for (let i in $scope.datesMap) {
+ if ($scope.datesMap.hasOwnProperty(i)) {
+ if ($scope.datesMap[i].ts === interval || $scope.datesMap[i].ts === interval + 1 || $scope.datesMap[i].ts === interval - 1) {
+ $scope.selectedDateInterval = $scope.datesMap[i].ts;
+ $scope.customInterval = false;
+ return;
+ }
+ }
+ }
+
+ $scope.selectedDateInterval = interval;
+ $scope.customInterval = {ts: interval, label: "Custom interval"};
+ }
+
+ function updateAdvancedModel() {
+ $scope.advancedModel = getFormattedDate(vm.ctx.dashboard.dashboardTimewindow.history.fixedTimewindow.startTimeMs, vm.ctx.dashboard.dashboardTimewindow.history.fixedTimewindow.endTimeMs);
+ }
+
+ function updateStorageDate() {
+ saveIntoStorage('date-range', {
+ start: $scope.advancedModel.dateStart.getTime(),
+ end: $scope.advancedModel.dateEnd.getTime(),
+ name: $scope.advancedModel.selectedTemplateName
+ });
+ }
+
+ function saveIntoStorage(keyName, selection) {
+ if (selection) {
+ $window.sessionStorage.setItem(keyName, angular.toJson(selection));
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/src/app/widget/lib/date-range-navigator/date-range-navigator.scss b/ui/src/app/widget/lib/date-range-navigator/date-range-navigator.scss
new file mode 100644
index 0000000000..7d27db14cd
--- /dev/null
+++ b/ui/src/app/widget/lib/date-range-navigator/date-range-navigator.scss
@@ -0,0 +1,108 @@
+/**
+ * Copyright © 2016-2019 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+.date-range-navigator-widget {
+ display: flex;
+ height: 100%;
+}
+
+.date-range-navigator {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-evenly;
+ width: 100%;
+ margin: auto;
+
+ .drn__element {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ max-width: 100%;
+ height: 60px;
+ margin: 4px 0;
+ }
+
+ .navigation {
+ md-input-container {
+ margin: 0;
+ }
+ }
+
+ .picker {
+ .picker__wrapper {
+ position: relative;
+ max-width: 100%;
+ padding: 2px;
+
+ > label {
+ position: absolute;
+ right: -3px;
+ bottom: 100%;
+ left: 0;
+ padding-left: 3px;
+ color: #787878;
+ transform: scale(.75);
+ transform-origin: left bottom;
+ }
+ }
+
+ .md-select-value {
+ min-width: 225px;
+ border-color: #e1e1e1;
+
+ .md-select-icon {
+ color: #757575;
+ }
+ }
+ }
+
+ &.short-mode {
+ display: block;
+ width: 90%;
+
+ .drn__element {
+ width: 100%;
+
+ md-input-container {
+ flex: 1;
+ }
+ }
+
+ .picker {
+ .picker__wrapper {
+ width: 100%;
+ }
+
+ .md-select-value {
+ min-width: initial;
+ }
+ }
+
+ &.labels-hidden {
+ .drn__element {
+ margin: 0;
+ }
+ }
+ }
+
+ &.long-mode {
+ &.labels-hidden {
+ .drn__element {
+ height: 36px;
+ }
+ }
+ }
+}
diff --git a/ui/src/app/widget/lib/date-range-navigator/date-range-navigator.tpl.html b/ui/src/app/widget/lib/date-range-navigator/date-range-navigator.tpl.html
new file mode 100644
index 0000000000..a3908e55a1
--- /dev/null
+++ b/ui/src/app/widget/lib/date-range-navigator/date-range-navigator.tpl.html
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+ {{'widgets.date-range-navigator.localizationMap.' + customInterval.label | translate}}
+
+ {{'widgets.date-range-navigator.localizationMap.' + dateValue.label | translate}}
+
+
+
+
+
+
+
+ keyboard_arrow_left
+
+
+
+
+
+ {{'widgets.date-range-navigator.localizationMap.'+dateValue.label | translate}}
+
+
+
+
+ keyboard_arrow_right
+
+
+