diff options
| author | pliablepixels <pliablepixels@gmail.com> | 2016-01-27 16:32:02 -0500 |
|---|---|---|
| committer | pliablepixels <pliablepixels@gmail.com> | 2016-01-27 16:32:02 -0500 |
| commit | 1f404962fd9d20c0ff25d026ce2af2f8f6840120 (patch) | |
| tree | 3afe8942a5a232e786442ba3c4632aec3e2afdf9 /www | |
| parent | fd1598f4515777275d58b1d14cce8b75961accd7 (diff) | |
#154 - montage history updates
Former-commit-id: 42cd82e17eef928d53b568989a143842d492b59f
Diffstat (limited to 'www')
| -rw-r--r-- | www/css/style.css | 16 | ||||
| -rw-r--r-- | www/js/DataModel.js | 2 | ||||
| -rw-r--r-- | www/js/MontageHistoryCtrl.js | 208 | ||||
| -rw-r--r-- | www/js/app.js | 1 | ||||
| -rw-r--r-- | www/templates/montage-history.html | 145 |
5 files changed, 270 insertions, 102 deletions
diff --git a/www/css/style.css b/www/css/style.css index ffda637f..52e5ad08 100644 --- a/www/css/style.css +++ b/www/css/style.css @@ -108,16 +108,26 @@ Credit: https://css-tricks.com/snippets/css/a-guide-to-flexbox/ border-color: #444444; border-style: solid; border-width:1px; - opactity:80%; + opacity:80%; } +.header-event-id { + background: #9b59b6; + color:#cccccc; + border-color: #9b59b6; + border-style: solid; + border-width:1px; + opacity:80%; +} + + .alarmed-header { background: #ba3e3e; color:#ffffff; border-color: #ba3e3e; border-style: solid; border-width:1px; - opactity:80%; + opacity:80%; } @@ -127,7 +137,7 @@ Credit: https://css-tricks.com/snippets/css/a-guide-to-flexbox/ border-color: #ba3e3e; border-style: solid; border-width:5px; - opactity:80%; + opacity:80%; position:absolute; top:0px; left:0px; diff --git a/www/js/DataModel.js b/www/js/DataModel.js index 8e3915f5..88a0ac38 100644 --- a/www/js/DataModel.js +++ b/www/js/DataModel.js @@ -116,7 +116,7 @@ angular.module('zmApp.controllers') zmLog("Saving all parameters to storage"); - zmDebug ("DataModel/setLogin: writing " + JSON.stringify(newLogin)); + //zmDebug ("DataModel/setLogin: writing " + JSON.stringify(newLogin)); //$localstorage.setObject($rootScope.currentServerGroup, loginData); console.log ("Saving For " + loginData.serverName); diff --git a/www/js/MontageHistoryCtrl.js b/www/js/MontageHistoryCtrl.js index 563dbcc3..bf107a94 100644 --- a/www/js/MontageHistoryCtrl.js +++ b/www/js/MontageHistoryCtrl.js @@ -39,8 +39,6 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc }; - - $scope.footerCollapse = function() { @@ -49,7 +47,7 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc }; - + function footerCollapse() { @@ -62,26 +60,30 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc for (var i=0; i< $scope.MontageMonitors.length; i++) { $scope.MontageMonitors[i].eventUrl = "img/noevent.png"; + $scope.MontageMonitors[i].eventUrlTime=""; + // $scope.MontageMonitors[i].connkey= i; } var TimeObjectFrom = moment($scope.datetimeValue.value).format("YYYY-MM-DD HH:mm"); - - - var TimeObjectTo = moment(TimeObjectFrom).add(1,'hour').format('YYYY-MM-DD HH:mm'); - + var apiurl; if ($scope.sliderVal.exactMatch) { - apiurl= ld.apiurl + "/events/index/StartTime =:"+TimeObjectFrom+".json"; + // grab events that start on or before the time and end on or after the time + // this should only bring up events that span that time + apiurl= ld.apiurl + "/events/index/StartTime <=:"+TimeObjectFrom+"/EndTime >=:"+TimeObjectFrom+".json"; } else { + // grab events for next hour and then do expanded search later + // this is so one monitor does not overwhelm as I'm not reading multiple + // pages apiurl= ld.apiurl + "/events/index/StartTime >=:"+TimeObjectFrom+"/StartTime <=:"+ TimeObjectTo+".json"; } ZMDataModel.zmLog ("Event timeline API is " + apiurl); @@ -91,11 +93,12 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc ZMDataModel.zmDebug ("Got new history events:"+ JSON.stringify(data)); - var eid, mid; + var eid, mid, stime; for (i=0; i<data.events.length; i++) { mid = data.events[i].Event.MonitorId; eid = data.events[i].Event.Id; + stime = data.events[i].Event.StartTime; // only take the first one for each monitor for (var j=0; j < $scope.MontageMonitors.length; j++) @@ -108,11 +111,14 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc if (!ZMDataModel.isBackground()) { $scope.MontageMonitors[j].eventUrl=ld.streamingurl+"/nph-zms?source=event&mode=jpeg&event="+eid+"&frame=1&replay="+($scope.sliderVal.enableGapless?"gapless":"single"); + + $scope.MontageMonitors[j].eventUrlTime = stime; } else { ZMDataModel.zmLog ("Setting img src to null as we are in background"); $scope.MontageMonitors[j].eventUrl=""; + $scope.MontageMonitors[j].eventUrlTime = ""; } } } @@ -163,12 +169,15 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc { $scope.MontageMonitors[i].eventUrl=ld.streamingurl+"/nph-zms?source=event&mode=jpeg&event="+data.events[0].Event.Id+"&frame=1&replay="+($scope.sliderVal.enableGapless?"gapless":"single"); + + $scope.MontageMonitors[i].eventUrlTime = data.events[0].Event.StartTime; ZMDataModel.zmLog ("Found expanded event "+data.events[0].Event.Id+" for monitor " + $scope.MontageMonitors[i].Monitor.Id); } else { $scope.MontageMonitors[i].eventUrl=""; + $scope.MontageMonitors[i].eventUrlTime = ""; ZMDataModel.zmLog ("Setting img src to null as data received in background"); } } @@ -187,6 +196,32 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc $scope.datetimeValue = {value:""}; $scope.datetimeValue.value = tdatetimeValue; + var eventQueryInterval; + + + + + + function checkAllEvents() + { + if (!$scope.sliderVal.showTimeline) + { + ZMDataModel.zmDebug ("Event timelines won't be shown, skipping..."); + return; + } + console.log ("Events are checked...."); + + for (var i=0; i<$scope.MontageMonitors.length; i++) + { + if ($scope.MontageMonitors[i].eventUrl !="" && $scope.MontageMonitors[i].eventUrl !='img/noevent.png') + { + console.log ("Checking event status for " + $scope.MontageMonitors[i].Monitor.Name); + controlEventStream('99','',$scope.MontageMonitors[i].Monitor.Id, i); + + } + } + } + $scope.dateChanged = function() { @@ -208,6 +243,117 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc },true);*/ + $scope.controlEventStream = function (cmd,disp,connkey,ndx) + { + controlEventStream(cmd,disp,connkey,ndx); + }; + + function controlEventStream(cmd, disp, connkey, ndx) { + // console.log("Command value " + cmd); + + if (disp) { + $ionicLoading.hide(); + $ionicLoading.show({ + template: "please wait...", + noBackdrop: true, + duration: zm.loadingTimeout, + }); + } + var loginData = ZMDataModel.getLogin(); + + /* + var CMD_NONE = 0; + var CMD_PAUSE = 1; + var CMD_PLAY = 2; + var CMD_STOP = 3; + var CMD_FASTFWD = 4; + var CMD_SLOWFWD = 5; + var CMD_SLOWREV = 6; + var CMD_FASTREV = 7; + var CMD_ZOOMIN = 8; + var CMD_ZOOMOUT = 9; + var CMD_PAN = 10; + var CMD_SCALE = 11; + var CMD_PREV = 12; + var CMD_NEXT = 13; + var CMD_SEEK = 14; + var CMD_QUERY = 99; + */ + + + + // You need to POST commands to control zms + // Note that I am url encoding the parameters into the URL + // If I leave it as JSON, it gets converted to OPTONS due + // to CORS behaviour and ZM/Apache don't seem to handle it + + //console.log("POST: " + loginData.url + '/index.php'); + + var req = $http({ + method: 'POST', + /*timeout: 15000,*/ + url: loginData.url + '/index.php', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + //'Accept': '*/*', + }, + transformRequest: function (obj) { + var str = []; + for (var p in obj) + str.push(encodeURIComponent(p) + "=" + + encodeURIComponent(obj[p])); + var foo = str.join("&"); + // console.log("****RETURNING " + foo); + return foo; + }, + + data: { + view: "request", + request: "stream", + connkey: connkey, + command: cmd, + auth: $rootScope.authSession, + // user: loginData.username, + // pass: loginData.password + } + }); + req.success(function (resp) { + + console.log("SUCCESS FOR: " + JSON.stringify(resp)); + + if (resp.result=="Ok" && ndx != -1) + { + var ld = ZMDataModel.getLogin(); + var apiurl= ld.apiurl + "/events/"+resp.status.event+".json"; + console.log ("API " + apiurl); + $http.get (apiurl) + .success (function (data) + { + $scope.MontageMonitors[ndx].eventUrlTime=data.event.Event.StartTime; + }) + .error (function (data) + { + $scope.MontageMonitors[ndx].eventUrlTime="-"; + }); + + } + //var str = toast_blurb + "event:" + resp.status.event; + // console.log(str); + // $ionicLoading.hide(); + + + + + }); + + req.error(function (resp) { + //console.log("ERROR: " + JSON.stringify(resp)); + ZMDataModel.zmLog("Error sending event command " + JSON.stringify(resp), "error"); + }); + } + + + $scope.displayDateTimeSliders = true; $scope.showtimers = true; var curYear = new Date().getFullYear(); @@ -221,7 +367,8 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc realRate:100, hideNoEvents:false, enableGapless:true, - exactMatch:false + exactMatch:false, + showTimeline:true }; @@ -437,7 +584,7 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc } - }, 1000); + }, zm.eventHistoryTimer); document.addEventListener("pause", onPause, false); @@ -463,10 +610,6 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc - - - - // Do we have a saved montage array size? No? // if (window.localStorage.getItem("montageArraySize") == undefined) { if (loginData.montageArraySize == '0') { @@ -576,7 +719,7 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc // FIXME: I should probably unregister this instead if (typeof $scope.monitors === undefined) return; - console.log ("***EVENT TRAP***"); + //console.log ("***EVENT TRAP***"); var alarmMonitors = args.message; for (var i=0; i< alarmMonitors.length; i++) { @@ -627,6 +770,7 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc ZMDataModel.zmDebug("MontageCtrl: switch minimal is " + $scope.minimal); ionic.Platform.fullScreen($scope.minimal, !$scope.minimal); $interval.cancel(intervalHandle); + $interval.cancel(eventQueryInterval); if (!$rootScope.isAlarm) { @@ -1108,6 +1252,7 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc function onPause() { ZMDataModel.zmDebug("MontageCtrl: onpause called"); $interval.cancel(intervalHandle); + $interval.cancel(eventQueryInterval); // $interval.cancel(modalIntervalHandle); // FIXME: Do I need to setAwake(false) here? @@ -1117,14 +1262,18 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc function onResume() { if (!$scope.isModalActive) { var ld = ZMDataModel.getLogin(); + + ZMDataModel.zmDebug("MontageCtrl: onresume called"); - ZMDataModel.zmLog("Restarting montage timer on resume"); - $rootScope.rand = Math.floor((Math.random() * 100000) + 1); - $interval.cancel(intervalHandle); - intervalHandle = $interval(function () { - loadNotifications(); + ZMDataModel.zmLog("Restarting eventQuery timer on resume"); + + + //$rootScope.rand = Math.floor((Math.random() * 100000) + 1); + $interval.cancel(eventQueryInterval); + eventQueryInterval = $interval(function () { + checkAllEvents(); // console.log ("Refreshing Image..."); - }.bind(this), ld.refreshSec * 1000); + }.bind(this),zm.eventHistoryTimer); } else // modal is active { // $rootScope.modalRand = Math.floor((Math.random() * 100000) + 1); @@ -1162,20 +1311,23 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc var ld = ZMDataModel.getLogin(); console.log("Setting Awake to " + ZMDataModel.getKeepAwake()); ZMDataModel.setAwake(ZMDataModel.getKeepAwake()); - - $interval.cancel(intervalHandle); - intervalHandle = $interval(function () { - loadNotifications(); + + $interval.cancel(eventQueryInterval); + eventQueryInterval = $interval(function () { + checkAllEvents(); // console.log ("Refreshing Image..."); - }.bind(this), ld.refreshSec * 1000); + }.bind(this), zm.eventHistoryTimer); - loadNotifications(); + }); $scope.$on('$ionicView.beforeLeave', function () { console.log("**VIEW ** Event History Ctrl Left, force removing modal"); if ($scope.modal) $scope.modal.remove(); + ZMDataModel.zmLog("Cancelling event query timer"); + $interval.cancel(eventQueryInterval); + ZMDataModel.zmLog ("Stopping network pull..."); // make sure this is applied in scope digest to stop network pull // thats why we are doing it beforeLeave diff --git a/www/js/app.js b/www/js/app.js index 3f07c1a0..5f67ee44 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -67,6 +67,7 @@ angular.module('zmApp', [ desktopApiUrl: "/api/zm", latestRelease: "https://api.github.com/repos/pliablepixels/zmNinja/releases/latest", nphSwitchTimer:6000, + eventHistoryTimer:10000, }) diff --git a/www/templates/montage-history.html b/www/templates/montage-history.html index 99c61e94..1a1fd3e8 100644 --- a/www/templates/montage-history.html +++ b/www/templates/montage-history.html @@ -1,43 +1,42 @@ <ion-view title="Event Montage" cache-view="false" hide-nav-bar="{{minimal}}"> <ion-nav-buttons side="left"> <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"></button> - - - - + + + + <button data-badge="{{$root.alarmCount}}" class="animated infinite tada button button-icon button-clear ion-ios-bell notification-badge" ng-click="handleAlarms();" ng-if="$root.isAlarm"></button> </ion-nav-buttons> - + <ion-nav-buttons side="right"> - - <button ng-class="packMontage?'button button-icon button-clear ion-android-more-vertical':'button button-icon button-clear ion-android-more-horizontal'" - ng-click="toggleMontageDisplayOrder();"> + + <button ng-class="packMontage?'button button-icon button-clear ion-android-more-vertical':'button button-icon button-clear ion-android-more-horizontal'" ng-click="toggleMontageDisplayOrder();"> </button> - + <span class="rotate-button"> <button class="button button-icon button-clear ion-arrow-swap" ng-click="toggleReorder();"> </button> - </span> + </span> - <!-- + <!-- <button class="button button-icon button-clear ion-android-contract" ng-click="switchMinimal()"> </button>--> <!--<button class="button button-icon ion-ios-help-outline" ng-click="popover.show($event)"></button>--> - - - + + + </ion-nav-buttons> <ion-content has-bouncing="false" style="background-color:#444444"> <ion-refresher pulling-text="Pull to reload Monitors..." spinner="bubbles" on-refresh="doRefresh()"> </ion-refresher> - - - + + + <span ng-show="!minimal"> @@ -59,18 +58,23 @@ </div> </span> - <div ng-style="packMontage ? { '-webkit-column-count':slider.monsize,'-webkit-column-gap':'0px','line-height':'0px','-webkit-column-fill': 'balance', 'column-fill': 'balance' } : {'-webkit-column-count':slider.monsize,'-webkit-column-gap':'0px','line-height':'0px','display':'-webkit-flex','-webkit-flex-direction':'row','flex-direction':'row', 'flex-wrap':'wrap' }"> - - <!--<div ng-style="packMontage ? { '-webkit-column-count':slider.monsize, '-webkit-column-gap':'0px','line-height':'0px' } : { 'flex':'display', '-webkit-column-count':slider.monsize }">--> - - - <span ng-repeat="monitor in MontageMonitors|limitTo: monLimit" - ng-if="monitor.Monitor.Function!='None' && monitor.Monitor.listDisplay!='noshow' && monitor.Monitor.Enabled !='0'"> + <div ng-style="packMontage ? { '-webkit-column-count':slider.monsize,'-webkit-column-gap':'0px','line-height':'0px','-webkit-column-fill': 'balance', 'column-fill': 'balance' } : {'-webkit-column-count':slider.monsize,'-webkit-column-gap':'0px','line-height':'0px','display':'-webkit-flex','-webkit-flex-direction':'row','flex-direction':'row', 'flex-wrap':'wrap' }"> + + <!--<div ng-style="packMontage ? { '-webkit-column-count':slider.monsize, '-webkit-column-gap':'0px','line-height':'0px' } : { 'flex':'display', '-webkit-column-count':slider.monsize }">--> + + + <span ng-repeat="monitor in MontageMonitors|limitTo: monLimit" ng-if="monitor.Monitor.Function!='None' && monitor.Monitor.listDisplay!='noshow' && monitor.Monitor.Enabled !='0'"> - + <div style="position: relative;width:{{devWidth/slider.monsize}}px;"> + + + <div ng-if="!isModalActive"> + + + <div ng-if="$root.authSession!='undefined' && !isBackground()"> <div ng-if = "!minimal && monitor.eventUrl == 'img/noevent.png' && !sliderVal.hideNoEvents"> <img id="img-$index" image-spinner-src="{{isBackground()?'':monitor.eventUrl}}" image-spinner-loader="lines" style=" @@ -84,7 +88,7 @@ </div> <div ng-if = "!minimal && monitor.eventUrl != 'img/noevent.png'"> - <img ng-if="!isBackground()" id="img-$index" image-spinner-src="{{monitor.eventUrl}}&scale={{LoginData.singleImageQuality}}{{$root.authSession}}&rand={{$root.rand}}&rate={{sliderVal.realRate}}" image-spinner-loader="lines" style=" + <img ng-if="!isBackground()" id="img-$index" image-spinner-src="{{monitor.eventUrl}}&scale={{LoginData.singleImageQuality}}{{$root.authSession}}&rand={{$root.rand}}&rate={{sliderVal.realRate}}&connkey={{monitor.Monitor.Id}}" image-spinner-loader="lines" style=" width: 100% !important; height: auto !important;" /> @@ -98,13 +102,14 @@ {{monitor.Monitor.Name}} </div> + <div ng-if="!isBackground() && sliderVal.showTimeline" style="position:absolute; bottom:15px; right:0%;white-space:nowrap;overflow:hidden;" + class="header-event-id"> + <i class="ion-clock"></i> + {{prettifyDate(monitor.eventUrlTime)}} + </div> + </div> - <div ng-if = "minimal"> - <img id="img-$index" image-spinner-src="{{LoginData.streamingurl}}/nph-zms?mode=single&monitor={{monitor.Monitor.Id}}&scale={{LoginData.montageQuality}}{{$root.authSession}}&rand={{$root.rand}}" image-spinner-loader="lines" style="margin-top:0px; - width: 100% !important; - height: auto !important;" /> - </div> </div> @@ -115,12 +120,12 @@ </div> - + </div> </div> - + <div ng-if="isModalActive"> <img id="img-$index" image-spinner-src="img/pausevideo.png" style="margin-top:0px; width: 100% !important; @@ -162,53 +167,53 @@ </span> </div> - - <ion-pull-up-footer class="bar-dark" on-minimize="footerCollapse()" on-collapse="footerCollapse()" initial-state="minimized" default-behavior="expand"> - <ion-pull-up-handle width="100" height="25" toggle="ion-chevron-up ion-chevron-down" style="border-radius: 25px 25px 0 0"> + + <ion-pull-up-footer class="bar-dark" on-minimize="footerCollapse()" on-collapse="footerCollapse()" initial-state="minimized" default-behavior="expand"> + <ion-pull-up-handle width="100" height="25" toggle="ion-chevron-up ion-chevron-down" style="border-radius: 25px 25px 0 0"> <i class="icon ion-chevron-up"></i> </ion-pull-up-handle> <ion-pull-up-bar> <h1 class="title" ion-pull-up-trigger>Event History</h1> </ion-pull-up-bar> <ion-pull-up-content scroll="true"> - - + + <div class="list list-inset"> + + + <ion-toggle ng-model="sliderVal.hideNoEvents" ng-checked="{{sliderVal.hideNoEvents}}" toggle-class="toggle-dark">Hide monitors without events</ion-toggle> + + <ion-toggle ng-model="sliderVal.enableGapless" ng-checked="{{sliderVal.enableGapless}}" toggle-class="toggle-dark">enable gapless playback</ion-toggle> + + + <ion-toggle ng-model="sliderVal.exactMatch" ng-checked="{{sliderVal.exactMatch}}" toggle-class="toggle-dark">exact time match</ion-toggle> - - <ion-toggle ng-model="sliderVal.hideNoEvents" - ng-checked="{{sliderVal.hideNoEvents}}" - toggle-class="toggle-dark">Hide monitors without events</ion-toggle> - - <ion-toggle ng-model="sliderVal.enableGapless" - ng-checked="{{sliderVal.enableGapless}}" - toggle-class="toggle-dark">enable gapless playback</ion-toggle> - - - <ion-toggle ng-model="sliderVal.exactMatch" - ng-checked="{{sliderVal.exactMatch}}" - toggle-class="toggle-dark">exact time match</ion-toggle> - - - - <!--<div class="item item-divider" ion-datetime-picker ng-model="datetimeValue.value"> + <ion-toggle ng-model="sliderVal.showTimeline" ng-checked="{{sliderVal.showTimeline}}" toggle-class="toggle-dark">show event time <p>(resource intensive)</p></ion-toggle> + + + + <!--<div class="item item-divider" ion-datetime-picker ng-model="datetimeValue.value"> Tap to change: {{datetimeValue.value| date: "yyyy-MMM-dd hh:mma"}} </div>--> - - - - + + + + <div class="row"> <div class="col col-75"> - <br/><div style="width:90%;color:black;"><input ng-model="sliderVal.rate" type="text" id="mySlider6" slider options="slider_modal_options_rate"/></div><br/> + <br/> + <div style="width:90%;color:black;"> + <input ng-model="sliderVal.rate" type="text" id="mySlider6" slider options="slider_modal_options_rate" /> + </div> + <br/> </div> <div class="col col-25" style="background-color:#AEA8D3;text-align:center"> - speed + speed </div> </div> - -<!-- + + <!-- <div class="row"> <div class="col col-90"> <br/><div style="width:90%;color:black;"><input ng-model="sliderVal.min" type="text" id="mySlider5" slider options="slider_modal_options_mm"/></div><br/> @@ -253,15 +258,15 @@ yr </div> </div>--> - - - + + + </div> </ion-pull-up-content> </ion-pull-up-footer> - - - - + + + + </ion-view>
\ No newline at end of file |
