From 6460992ab3341423fb44ffd4e3318f00fdc80ec2 Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Sun, 17 Dec 2017 12:30:27 -0500 Subject: #570 inital framework for 24 hr moment --- www/css/style.css | 14 ++ www/external/masonry.pkgd.min.js | 9 + www/index.html | 3 + www/js/EventCtrl.js | 13 ++ www/js/MomentCtrl.js | 335 ++++++++++++++++++++++++++++++++++++++ www/js/app.js | 41 +++++ www/lang/locale-en.json | 5 + www/templates/image-modal.html | 2 +- www/templates/menu.html | 6 + www/templates/moment-popover.html | 12 ++ www/templates/moment.html | 35 ++++ 11 files changed, 474 insertions(+), 1 deletion(-) create mode 100644 www/external/masonry.pkgd.min.js create mode 100644 www/js/MomentCtrl.js create mode 100644 www/templates/moment-popover.html create mode 100644 www/templates/moment.html (limited to 'www') diff --git a/www/css/style.css b/www/css/style.css index 934fe0ca..81db03f7 100644 --- a/www/css/style.css +++ b/www/css/style.css @@ -256,8 +256,22 @@ figcaption { left: 0; right: 0; opacity: 1; + font-size: 80%; } +.normal-figheader { + background: rgba(0, 0, 0, 0.2); + color: #FFF; + position: absolute; + top: 0; + left: 0; + right: 0; + opacity: 1; + font-size: 80%; +} + + + .alarmed-figcaption { background: #ba3e3e; color: #ffffff; diff --git a/www/external/masonry.pkgd.min.js b/www/external/masonry.pkgd.min.js new file mode 100644 index 00000000..a61c0ded --- /dev/null +++ b/www/external/masonry.pkgd.min.js @@ -0,0 +1,9 @@ +/*! + * Masonry PACKAGED v4.2.0 + * Cascading grid layout library + * http://masonry.desandro.com + * MIT License + * by David DeSandro + */ + +!function(t,e){"function"==typeof define&&define.amd?define("jquery-bridget/jquery-bridget",["jquery"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("jquery")):t.jQueryBridget=e(t,t.jQuery)}(window,function(t,e){"use strict";function i(i,r,a){function h(t,e,n){var o,r="$()."+i+'("'+e+'")';return t.each(function(t,h){var u=a.data(h,i);if(!u)return void s(i+" not initialized. Cannot call methods, i.e. "+r);var d=u[e];if(!d||"_"==e.charAt(0))return void s(r+" is not a valid method");var l=d.apply(u,n);o=void 0===o?l:o}),void 0!==o?o:t}function u(t,e){t.each(function(t,n){var o=a.data(n,i);o?(o.option(e),o._init()):(o=new r(n,e),a.data(n,i,o))})}a=a||e||t.jQuery,a&&(r.prototype.option||(r.prototype.option=function(t){a.isPlainObject(t)&&(this.options=a.extend(!0,this.options,t))}),a.fn[i]=function(t){if("string"==typeof t){var e=o.call(arguments,1);return h(this,t,e)}return u(this,t),this},n(a))}function n(t){!t||t&&t.bridget||(t.bridget=i)}var o=Array.prototype.slice,r=t.console,s="undefined"==typeof r?function(){}:function(t){r.error(t)};return n(e||t.jQuery),i}),function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}("undefined"!=typeof window?window:this,function(){function t(){}var e=t.prototype;return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[];return-1==n.indexOf(e)&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e);var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||{};return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=i.indexOf(e);return-1!=n&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=0,o=i[n];e=e||[];for(var r=this._onceEvents&&this._onceEvents[t];o;){var s=r&&r[o];s&&(this.off(t,o),delete r[o]),o.apply(this,e),n+=s?0:1,o=i[n]}return this}},t}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("get-size/get-size",[],function(){return e()}):"object"==typeof module&&module.exports?module.exports=e():t.getSize=e()}(window,function(){"use strict";function t(t){var e=parseFloat(t),i=-1==t.indexOf("%")&&!isNaN(e);return i&&e}function e(){}function i(){for(var t={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},e=0;u>e;e++){var i=h[e];t[i]=0}return t}function n(t){var e=getComputedStyle(t);return e||a("Style returned "+e+". Are you running this code in a hidden iframe on Firefox? See http://bit.ly/getsizebug1"),e}function o(){if(!d){d=!0;var e=document.createElement("div");e.style.width="200px",e.style.padding="1px 2px 3px 4px",e.style.borderStyle="solid",e.style.borderWidth="1px 2px 3px 4px",e.style.boxSizing="border-box";var i=document.body||document.documentElement;i.appendChild(e);var o=n(e);r.isBoxSizeOuter=s=200==t(o.width),i.removeChild(e)}}function r(e){if(o(),"string"==typeof e&&(e=document.querySelector(e)),e&&"object"==typeof e&&e.nodeType){var r=n(e);if("none"==r.display)return i();var a={};a.width=e.offsetWidth,a.height=e.offsetHeight;for(var d=a.isBorderBox="border-box"==r.boxSizing,l=0;u>l;l++){var c=h[l],f=r[c],m=parseFloat(f);a[c]=isNaN(m)?0:m}var p=a.paddingLeft+a.paddingRight,g=a.paddingTop+a.paddingBottom,y=a.marginLeft+a.marginRight,v=a.marginTop+a.marginBottom,_=a.borderLeftWidth+a.borderRightWidth,z=a.borderTopWidth+a.borderBottomWidth,E=d&&s,b=t(r.width);b!==!1&&(a.width=b+(E?0:p+_));var x=t(r.height);return x!==!1&&(a.height=x+(E?0:g+z)),a.innerWidth=a.width-(p+_),a.innerHeight=a.height-(g+z),a.outerWidth=a.width+y,a.outerHeight=a.height+v,a}}var s,a="undefined"==typeof console?e:function(t){console.error(t)},h=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"],u=h.length,d=!1;return r}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("desandro-matches-selector/matches-selector",e):"object"==typeof module&&module.exports?module.exports=e():t.matchesSelector=e()}(window,function(){"use strict";var t=function(){var t=window.Element.prototype;if(t.matches)return"matches";if(t.matchesSelector)return"matchesSelector";for(var e=["webkit","moz","ms","o"],i=0;is?"round":"floor";r=Math[a](r),this.cols=Math.max(r,1)},n.getContainerWidth=function(){var t=this._getOption("fitWidth"),i=t?this.element.parentNode:this.element,n=e(i);this.containerWidth=n&&n.innerWidth},n._getItemLayoutPosition=function(t){t.getSize();var e=t.size.outerWidth%this.columnWidth,i=e&&1>e?"round":"ceil",n=Math[i](t.size.outerWidth/this.columnWidth);n=Math.min(n,this.cols);for(var o=this.options.horizontalOrder?"_getHorizontalColPosition":"_getTopColPosition",r=this[o](n,t),s={x:this.columnWidth*r.col,y:r.y},a=r.y+t.size.outerHeight,h=n+r.col,u=r.col;h>u;u++)this.colYs[u]=a;return s},n._getTopColPosition=function(t){var e=this._getTopColGroup(t),i=Math.min.apply(Math,e);return{col:e.indexOf(i),y:i}},n._getTopColGroup=function(t){if(2>t)return this.colYs;for(var e=[],i=this.cols+1-t,n=0;i>n;n++)e[n]=this._getColGroupY(n,t);return e},n._getColGroupY=function(t,e){if(2>e)return this.colYs[t];var i=this.colYs.slice(t,t+e);return Math.max.apply(Math,i)},n._getHorizontalColPosition=function(t,e){var i=this.horizontalColIndex%this.cols,n=t>1&&i+t>this.cols;i=n?0:i;var o=e.size.outerWidth&&e.size.outerHeight;return this.horizontalColIndex=o?i+t:this.horizontalColIndex,{col:i,y:this._getColGroupY(i,t)}},n._manageStamp=function(t){var i=e(t),n=this._getElementOffset(t),o=this._getOption("originLeft"),r=o?n.left:n.right,s=r+i.outerWidth,a=Math.floor(r/this.columnWidth);a=Math.max(0,a);var h=Math.floor(s/this.columnWidth);h-=s%this.columnWidth?0:1,h=Math.min(this.cols-1,h);for(var u=this._getOption("originTop"),d=(u?n.top:n.bottom)+i.outerHeight,l=a;h>=l;l++)this.colYs[l]=Math.max(d,this.colYs[l])},n._getContainerSize=function(){this.maxY=Math.max.apply(Math,this.colYs);var t={height:this.maxY};return this._getOption("fitWidth")&&(t.width=this._getContainerFitWidth()),t},n._getContainerFitWidth=function(){for(var t=0,e=this.cols;--e&&0===this.colYs[e];)t++;return(this.cols-t)*this.columnWidth-this.gutter},n.needsResizeLayout=function(){var t=this.containerWidth;return this.getContainerWidth(),t!=this.containerWidth},i}); \ No newline at end of file diff --git a/www/index.html b/www/index.html index c820a97e..9a18d2a3 100644 --- a/www/index.html +++ b/www/index.html @@ -30,6 +30,7 @@ + @@ -82,6 +83,7 @@ + @@ -128,6 +130,7 @@ + diff --git a/www/js/EventCtrl.js b/www/js/EventCtrl.js index 26d47d33..2bfb18ff 100644 --- a/www/js/EventCtrl.js +++ b/www/js/EventCtrl.js @@ -2771,7 +2771,20 @@ angular.module('zmApp.controllers') $scope.showThumbnail = function (b,f) { + if (!f) {// api update needed + $ionicPopup.alert( + { + title: $translate.instant('kNote'), + template: "{{'kApiUpgrade' | translate }}", + okText: $translate.instant('kButtonOk'), + cancelText: $translate.instant('kButtonCancel'), + }); + return; + + } + + $scope.thumbnailLarge=b+'/index.php?view=image&fid='+f; $ionicModal.fromTemplateUrl('templates/image-modal.html', { diff --git a/www/js/MomentCtrl.js b/www/js/MomentCtrl.js new file mode 100644 index 00000000..f1e1d283 --- /dev/null +++ b/www/js/MomentCtrl.js @@ -0,0 +1,335 @@ +/* jshint -W041 */ +/* jslint browser: true*/ +/* global cordova,StatusBar,angular,console, Masonry */ + + +//https:///zm/api/events/index/AlarmFrames%20%3E=:1/StartTime%20%3E=:2017-12-16%2009:08:50.json?sort=TotScore&direction=desc + +angular.module('zmApp.controllers').controller('zmApp.MomentCtrl', ['$scope', '$rootScope', '$ionicModal', 'NVRDataModel', '$ionicSideMenuDelegate', '$ionicHistory', '$state', '$translate', '$q', '$templateRequest', '$sce', '$compile', '$http', '$ionicLoading', 'zm', '$timeout', '$q', '$ionicPopover','$ionicPopup','message', function($scope, $rootScope, $ionicModal, NVRDataModel, $ionicSideMenuDelegate, $ionicHistory, $state, $translate, $q, $templateRequest, $sce, $compile, $http, $ionicLoading,zm, $timeout, $q, $ionicPopover, $ionicPopup, message) +{ + + var timeFrom; + var timeTo; + var moments = []; + var monitors = []; + + $scope.openMenu = function() + { + $ionicSideMenuDelegate.toggleLeft(); + }; + + //---------------------------------------------------------------- + // Alarm notification handling + //---------------------------------------------------------------- + $scope.handleAlarms = function() + { + $rootScope.isAlarm = !$rootScope.isAlarm; + if (!$rootScope.isAlarm) + { + $rootScope.alarmCount = "0"; + $ionicHistory.nextViewOptions( + { + disableBack: true + }); + $state.go("app.events", + { + "id": 0, + "playEvent": false + }, + { + reload: true + }); + return; + } + }; + + function getMonitorDimensions(mid) { + + for (var i=0; i < monitors.length; i++) { + + if (mid==monitors[i].Monitor.Id) { + return { + width: monitors[i].Monitor.Width, + height:monitors[i].Monitor.Height + } + } + } + + } + + + $scope.reLayout = function () { + NVRDataModel.log ("relaying masonry"); + $timeout (function () {masonry.layout();},300); + + }; + + $scope.toggleCollapse = function(mid,eid) { + NVRDataModel.debug ("toggling collapse for:"+mid); + var collapseCount=0; collapseId=0; + for (var i=0; i < $scope.moments.length; i++) { + if ($scope.moments[i].Event.Id == eid ) { + + $scope.moments[i].Event.hide = false; + collapseId = i; + + $scope.moments[i].Event.icon = $scope.moments[i].Event.icon == "ion-code-working" ? "ion-images" :"ion-code-working" ; + + + + + } + else if ($scope.moments[i].Event.MonitorId == mid ) { + // same monitor, but different ID + + $scope.moments[i].Event.hide = !$scope.moments[i].Event.hide ; + if ($scope.moments[i].Event.hide) collapseCount++; + //console.log ("Hiding " + i); + } + } //for + if (collapseCount) { + $scope.moments[collapseId].Event.collapseCount = collapseCount + } else { + $scope.moments[collapseId].Event.collapseCount=""; + } + + + + $timeout ( function () { + masonry.reloadItems(); + + },100); + + masonry.once( 'layoutComplete', function( laidOutItems ) { + $timeout ( function () {masonry.layout();},300); + } ) + + $timeout ( function () {masonry.layout();},300); + + }; + + + $scope.hourmin = function(str) { + return moment(str).format(NVRDataModel.getTimeFormat()); + + }; + + function humanizeTime(str) + { + //console.log ("Time:"+str+" TO LOCAL " + moment(str).local().toString()); + //if (NVRDataModel.getLogin().useLocalTimeZone) + return moment.tz(str, NVRDataModel.getTimeZoneNow()).fromNow(); + // else + // return moment(str).fromNow(); + + } + + function initMasonry() + { + $ionicLoading.show( + { + template: $translate.instant('kArrangingImages'), + noBackdrop: true, + duration: zm.loadingTimeout + }); + var progressCalled = false; + + var ld = NVRDataModel.getLogin(); + + var elem = angular.element(document.getElementById("mygrid")); + masonry = new Masonry('.grid', + { + itemSelector: '.grid-item', + percentPosition: true, + columnWidth: '.grid-sizer', + horizontalOrder: true, + gutter: 2, + initLayout: true + + }); + //console.log ("**** mygrid is " + JSON.stringify(elem)); + imagesLoaded(elem).on('progress', function(instance, img) + { + masonry.layout(); + + }); + imagesLoaded(elem).once('always', function() + { + + NVRDataModel.debug("All images loaded"); + $ionicLoading.hide(); + + $timeout (function() {masonry.layout();},300); + + if (!progressCalled) + { + NVRDataModel.log("*** PROGRESS WAS NOT CALLED"); + masonry.reloadItems(); + } + + }); + } + + $scope.closeModal = function() + { + NVRDataModel.debug(">>>MomentCtrl:Close & Destroy Modal"); + NVRDataModel.setAwake(false); + if ($scope.modal !== undefined) + { + $scope.modal.remove(); + } + + }; + + $scope.showThumbnail = function (b,f) { + + if (!f) {// api update needed + + $ionicPopup.alert( + { + title: $translate.instant('kNote'), + template: "{{'kApiUpgrade' | translate }}", + okText: $translate.instant('kButtonOk'), + cancelText: $translate.instant('kButtonCancel'), + }); + return; + + } + + $scope.thumbnailLarge=b+'/index.php?view=image&fid='+f; + $ionicModal.fromTemplateUrl('templates/image-modal.html', + { + scope: $scope, + animation: 'slide-in-up', + id: 'thumbnail', + }) + .then(function(modal) + { + $scope.modal = modal; + + + $scope.modal.show(); + + var ld = NVRDataModel.getLogin(); + + }); + + }; + + $scope.getMoments = function (cond) { + getMoments (cond); + } + + function getMoments(sortCondition) { + + if (sortCondition == 'MaxScore') + $scope.type = $translate.instant('kMomentMenuByScore'); + else if (sortCondition == 'StartTime') + $scope.type = $translate.instant('kMomentMenuByTime'); + + $scope.apiurl = NVRDataModel.getLogin().apiurl; + moments.length = 0; + + NVRDataModel.setAwake(false); + var tmptimeto = moment(); + var tmptimefrom = tmptimeto.subtract(24, 'hours'); + var page = 1; + timeFrom = tmptimefrom.format('YYYY-MM-DD HH:mm:ss'); + timeTo = tmptimeto.format('YYYY-MM-DD HH:mm:ss'); + + NVRDataModel.debug ("Moments from "+timeFrom+" to "+timeTo); + + //https:///zm/api/events/index/AlarmFrames%20%3E=:1/StartTime%20%3E=:2017-12-16%2009:08:50.json?sort=TotScore&direction=desc + + var ld = NVRDataModel.getLogin(); + var myurl = ld.apiurl + "/events/index/AlarmFrames >=:1/StartTime >=:"+timeFrom+".json?sort="+sortCondition+"direction=desc"; + NVRDataModel.debug ("Retrieving "+ myurl); + + $http.get(myurl+'/&page='+page) + .then (function (rawdata) { + + + // console.log (JSON.stringify(data)); + var data = rawdata.data; + console.log ("--------> PAGES=" + data.pagination.pageCount); + for (var i=0; i < data.events.length; i++) { + // console.log ("pushing "+ JSON.stringify(data.data.events[i])); + + var d = getMonitorDimensions(data.events[i].Event.MonitorId); + if (d) { + data.events[i].Event.width = d.width; + data.events[i].Event.height= d.height; + //console.log (d.width+"*"+d.height); + + } + + data.events[i].Event.hide = false; + data.events[i].Event.icon = "ion-code-working"; + data.events[i].Event.baseURL = NVRDataModel.getBaseURL(data.events[i].Event.MonitorId); + data.events[i].Event.monitorName = NVRDataModel.getMonitorName(data.events[i].Event.MonitorId); + + data.events[i].Event.dateObject = new Date(data.events[i].Event.StartTime); + + data.events[i].Event.humanizeTime = humanizeTime(data.events[i].Event.StartTime); + + var mid = data.events[i].Event.MonitorId; + data.events[i].Event.order = i; + moments.push (data.events[i]); + } + + // not really sure we need this + // will see later + if (sortCondition == "StartTime") { + moments.sort(function(a, b) { + var da = a.Event.dateObject; + var db = b.Event.dateObject; + return da>db ? -1 : da - + diff --git a/www/templates/menu.html b/www/templates/menu.html index 3caacfd2..16b8a138 100644 --- a/www/templates/menu.html +++ b/www/templates/menu.html @@ -32,6 +32,12 @@ {{'kMenuEvents'|translate}} + + + + {{'kMoment24Heading'|translate}} + + diff --git a/www/templates/moment-popover.html b/www/templates/moment-popover.html new file mode 100644 index 00000000..49dbea89 --- /dev/null +++ b/www/templates/moment-popover.html @@ -0,0 +1,12 @@ + + + + + diff --git a/www/templates/moment.html b/www/templates/moment.html new file mode 100644 index 00000000..40881ae2 --- /dev/null +++ b/www/templates/moment.html @@ -0,0 +1,35 @@ + + {{'kMoment24Heading' | translate}} {{type}} + + + + + + + + + +     + + + + +
+ Nothing to show yet... +
+ +
+
+ +
+
{{moment.Event.monitorName}}{{moment.Event.collapseCount}} 
+ +
{{moment.Event.humanizeTime}}{{hourmin(moment.Event.StartTime)}}
+
+ +
+ +
+
-- cgit v1.2.3