summaryrefslogtreecommitdiff
path: root/www/js/TimelineCtrl.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/js/TimelineCtrl.js')
-rw-r--r--www/js/TimelineCtrl.js359
1 files changed, 359 insertions, 0 deletions
diff --git a/www/js/TimelineCtrl.js b/www/js/TimelineCtrl.js
new file mode 100644
index 00000000..adeed4a9
--- /dev/null
+++ b/www/js/TimelineCtrl.js
@@ -0,0 +1,359 @@
+/* jshint -W041 */
+/* jshint -W083 */
+/*This is for the loop closure I am using in line 143 */
+/* jslint browser: true*/
+/* global vis,cordova,StatusBar,angular,console,moment */
+
+// This controller generates a graph for events
+// the main function is generateChart. I call generate chart with required parameters
+// from the template file
+
+angular.module('zmApp.controllers').controller('zmApp.TimelineCtrl', ['$ionicPlatform', '$scope', 'zm', 'ZMDataModel', '$ionicSideMenuDelegate', '$rootScope', '$http', '$q','message','$state', '$ionicLoading', '$ionicPopover', function ($ionicPlatform, $scope, zm, ZMDataModel, $ionicSideMenuDelegate, $rootScope, $http, $q,message, $state, $ionicLoading, $ionicPopover) {
+
+ console.log("Inside Timeline controller");
+ $scope.openMenu = function () {
+ $ionicSideMenuDelegate.toggleLeft();
+ };
+
+ $scope.leftButtons = [{
+ type: 'button-icon icon ion-navicon',
+ tap: function (e) {
+ $scope.toggleMenu();
+ }
+ }];
+
+ $scope.prettify = function (str) {
+ return moment(str).format('MMMM Do YYYY, h:mm:ssa');
+ };
+
+
+ //-------------------------------------------------
+ // Make sure we delete the timeline
+ // This may be redundant as the root view gets
+ // destroyed but no harm
+ //-------------------------------------------------
+ $scope.$on('$ionicView.leave', function () {
+ //console.log("**Destroying Timeline");
+ //timeline.destroy();
+ });
+
+ $scope.$on('$ionicView.afterEnter', function () {
+ console.log ("***AFTER ENTER");
+
+ if ($rootScope.customTimelineRange)
+ {
+ console.log ("***** CUSTOM RANGE");
+ if (moment($rootScope.fromString).isValid() &&
+ moment($rootScope.toString).isValid())
+ {
+ console.log ("FROM & TO IS CUSTOM");
+ fromDate = $rootScope.fromString;
+ toDate = $rootScope.toString;
+ $scope.fromDate = fromDate;
+ $scope.toDate = toDate;
+ drawGraph(fromDate, toDate, maxItems);
+ }
+ else
+ {
+ console.log ("FROM & TO IS CUSTOM INVALID");
+ }
+ }
+ });
+
+ //-------------------------------------------------
+ // Controller main
+ //-------------------------------------------------
+
+ // Make sure sliding for menu is disabled so it
+ // does not interfere with graph panning
+ $ionicSideMenuDelegate.canDragContent(false);
+
+ // fromDate and toDate will be used to plot the range for the graph
+ // We start in day mode
+ var fromDate = moment().startOf('day').format("YYYY-MM-DD HH:mm:ss");
+ var toDate = moment().endOf('day').format("YYYY-MM-DD HH:mm:ss");
+
+
+
+ $scope.fromDate = fromDate;
+ $scope.toDate = toDate;
+
+ var maxItems = 200;
+
+ //flat colors for graph - https://flatuicolors.com
+ var colors = ['#3498db', '#83adb5', '#c7bbc9', '#f39c12', '#bfb5b2', '#e74c3c'];
+
+ var container ;
+ container = angular.element(document.getElementById('visualization'));
+ var timeline="";
+
+ $scope.monitors = message;
+
+ $ionicPopover.fromTemplateUrl('templates/timeline-popover.html', {
+ scope: $scope,
+ }).then(function(popover) {
+ $scope.popover = popover;
+ });
+
+
+ //drawGraph(fromDate, toDate,maxItems);
+ dummyDrawGraph(fromDate, toDate,maxItems);
+
+ //-------------------------------------------------
+ // Rest graph to sane state after you went
+ // wild zooming and panning :-)
+ //-------------------------------------------------
+ $scope.fit = function () {
+ timeline.fit();
+ };
+
+ //-------------------------------------------------
+ // Called with day/week/month
+ // so we can redraw the graph
+ //-------------------------------------------------
+
+ $scope.buttonClicked = function(index)
+ {
+ //console.log (index);
+ if (index == 0) //month
+ {
+ ZMDataModel.zmLog ("Month view");
+ $rootScope.customTimelineRange = false;
+
+ toDate = moment().format("YYYY-MM-DD HH:mm:ss");
+ fromDate = moment().subtract(1,'month').startOf('day').format("YYYY-MM-DD HH:mm:ss");
+ $scope.fromDate = fromDate;
+ $scope.toDate = toDate;
+ drawGraph(fromDate, toDate,maxItems);
+ }
+ else if (index == 1) //week
+ {
+ $rootScope.customTimelineRange = false;
+ ZMDataModel.zmLog("Week view");
+ toDate = moment().format("YYYY-MM-DD HH:mm:ss");
+ fromDate = moment().subtract(1,'week').startOf('day').format("YYYY-MM-DD HH:mm:ss");
+ $scope.fromDate = fromDate;
+ $scope.toDate = toDate;
+ drawGraph(fromDate, toDate,maxItems);
+ }
+ else if (index==2) //day
+ {
+ $rootScope.customTimelineRange = false;
+ ZMDataModel.zmLog ("Day view");
+ toDate = moment().format("YYYY-MM-DD HH:mm:ss");
+ fromDate = moment().subtract(1,'day').startOf('day').format("YYYY-MM-DD HH:mm:ss");
+ $scope.fromDate = fromDate;
+ $scope.toDate = toDate;
+ drawGraph(fromDate, toDate,maxItems);
+ }
+
+ else // custom
+ {
+ $rootScope.customTimelineRange = true;
+ $state.go('events-date-time-filter');
+ }
+
+ };
+
+ // ------------------------------------------------------
+ // Draws a random graph from Vis timeline performance
+ // -----------------------------------------------------
+ function dummyDrawGraph(fromDate, toDate, count)
+ {
+ if (timeline) timeline.destroy();
+
+ var groups = new vis.DataSet([
+ {id: 1, content: 'Truck 1'},
+ {id: 2, content: 'Truck 2'},
+ {id: 3, content: 'Truck 3'},
+ {id: 4, content: 'Truck 4'}
+ ]);
+
+ // create items
+ var items = new vis.DataSet();
+
+ var order = 1;
+ var truck = 1;
+ for (var j = 0; j < 4; j++) {
+ var date = new Date();
+ for (var i = 0; i < count/4; i++) {
+ date.setHours(date.getHours() + 4 * (Math.random() < 0.2));
+ var start = new Date(date);
+
+ date.setHours(date.getHours() + 2 + Math.floor(Math.random()*4));
+ var end = new Date(date);
+
+ items.add({
+ id: order,
+ group: truck,
+ start: start,
+ end: end,
+ content: 'Order ' + order
+ });
+
+ order++;
+ }
+ truck++;
+ }
+
+ // specify options
+ var options = {
+ stack: false,
+ start: new Date(),
+ end: new Date(1000*60*60*24 + (new Date()).valueOf()),
+ editable: false,
+ margin: {
+ item: 10, // minimal margin between items
+ axis: 5 // minimal margin between items and the axis
+ },
+ orientation: 'top'
+ };
+ timeline = new vis.Timeline(container[0], null, options);
+ timeline.setGroups(groups);
+ timeline.setItems(items);
+ }
+
+
+ //-------------------------------------------------
+ // This function draws the graph
+ // So far struggling with mobile perf
+ // Observations so far:
+ // a) Just about acceptable performance with 100 items
+ // b) Sometimes on panning CPU gets locked at 99%
+ // for over 3-4 seconds
+ //-------------------------------------------------
+
+ function drawGraph(fromDate, toDate, count) {
+
+ $ionicLoading.show({
+ template: "Loading graph...",
+ animation: 'fade-in',
+ showBackdrop: true,
+ maxWidth: 200,
+ showDelay: 0,
+ duration: zm.loadingTimeout, //specifically for Android - http seems to get stuck at times
+ });
+
+ if (timeline) timeline.destroy();
+
+
+
+ var groups = new vis.DataSet();
+ var graphData = new vis.DataSet();
+ //console.log ("AFTER VIS");
+
+
+ var options = {
+ // autoResize: false, // true makes it much slower
+ //configure: true,
+ editable: false,
+ // moveable: true,
+ // zoomable: true,
+ start:fromDate,
+ end:toDate,
+ orientation: 'top',
+ min: fromDate,
+ max: toDate,
+ //width:'90%',
+
+ zoomMin: 1 * 60 * 1000, // 1 min
+ stack: false,
+ format: {
+ minorLabels: {
+ minute: "hh:mm a",
+ hour: 'hh:mm a',
+ second: 's',
+ },
+ majorLabels: {
+ second: "D MMM hh:mm a",
+ }
+ },
+
+ };
+
+ var graphIndex = 1; // will be used for graph ID
+
+ ZMDataModel.getEventsPages(0, fromDate, toDate)
+ .then(function (data) {
+ var pages = parseInt(data.pageCount);
+ var itemsPerPage = parseInt(data.limit);
+ var iterCount;
+
+ // The graph seems to get very slow
+ // even with 200 items. My data comes in pages from
+ // the server - so to make sure I don't exceed 200 items
+ // I figure out how many items the server returns per API page
+ // and divide the # of items I want (currently 200) with # of items per page
+ // So iterCount is the # of HTTP calls I need to make
+ iterCount = Math.round(count/itemsPerPage);
+ console.log("I will make " + iterCount + " HTTP Requests ");
+
+ // I've restructured this part. I was initially using vis DataSets
+ // for dynamic binding which was easier, but due to performance reasons
+ // I am waiting for the full data to load before I draw
+ var promises = [];
+ while ((pages > 0) && (iterCount >0)) {
+ var promise = ZMDataModel.getEvents(0, pages, "none", fromDate, toDate);
+ promises.push(promise);
+ pages--;
+ iterCount--;
+
+ }
+
+ $q.all(promises)
+ .then(function (data) {
+
+
+ // create groups
+ for (var g=0; g<$scope.monitors.length; g++)
+ {
+ groups.add({
+ id: $scope.monitors[g].Monitor.Id,
+ content: ZMDataModel.getMonitorName($scope.monitors[g].Monitor.Id)
+ });
+ }
+ for (var j = 0; j < data.length; j++) {
+ var myevents = data[j];
+
+
+ for (var i = 0; i < myevents.length; i++) {
+
+ graphData.add({
+ id: graphIndex,
+ content: '',
+ start: myevents[i].Event.StartTime,
+ end: myevents[i].Event.EndTime,
+ group: myevents[i].Event.MonitorId,
+ //type: "range",
+ style: "background-color:" + colors[parseInt(myevents[i].Event.MonitorId) % colors.length] + ";border-color:" + colors[parseInt(myevents[i].Event.MonitorId) % colors.length],
+ // title: "Hello"
+
+ });
+
+ graphIndex++;
+
+ }
+ }
+
+ timeline = new vis.Timeline(container[0], null, options);
+ timeline.setItems(graphData);
+ timeline.setGroups(groups);
+ timeline.fit();
+ $ionicLoading.hide();
+ }); // get Events
+ });
+ }
+
+
+ function arrayObjectIndexOf(myArray, searchTerm, property) {
+ for (var i = 0, len = myArray.length; i < len; i++) {
+ if (myArray[i][property] === searchTerm) return i;
+ }
+ return -1;
+ }
+
+
+
+
+
+}]);