Add frontend support for viewing an Event's Frames

Each Event has a 'Frames' button.  Clicking this changes
$scope.stream to false, hides the eventStream div, shows the
eventFrames div, and changes the text of the button to 'Stream'.

Each Frame is laid out in a box, with its associated image file
and details (delta, score, type, time).

The 'src' for each Frame's image was the difficult part.  The 'zpad'
filter is called for each Frame, so that we know how many 0's to pad
the Frame.FrameId with.

Finally if Frame.Type == Alarm, the box for that div is colored red.
This commit is contained in:
Kyle Johnson 2015-01-27 11:19:24 -05:00
parent 786009407c
commit e89e63c5e4
4 changed files with 68 additions and 5 deletions

View File

@ -408,6 +408,7 @@ th.table-th-sort-rev span.table-th-sort-span {
display: flex; display: flex;
-webkit-flex-direction: row; -webkit-flex-direction: row;
flex-direction: row; flex-direction: row;
flex-wrap: wrap;
} }
.monitor { .monitor {
@ -447,3 +448,31 @@ th.table-th-sort-rev span.table-th-sort-span {
background-color: #F5F5F5; background-color: #F5F5F5;
border-right: 1px solid #EEE; border-right: 1px solid #EEE;
} }
#event-frames-stills {
justify-content: center;
height: 480px;
overflow-y: scroll;
}
.frame {
width: 23%;
margin: 5px;
}
.frame .panel-heading, .frame .panel-body {
padding: 5px;
}
.frame ul {
padding-left: 0px;
margin-left: -5px;
list-style: outside none none;
text-align: center;
}
.frame ul > li {
display: inline-block;
padding-right: 5px;
padding-left: 5px;
}

View File

@ -124,6 +124,7 @@ ZoneMinder.controller('EventsController', function($scope, Events, Console, $mod
var modalInstance = $modal.open({ var modalInstance = $modal.open({
templateUrl: '/?view=event&skin=bootstrap', templateUrl: '/?view=event&skin=bootstrap',
controller: 'EventController', controller: 'EventController',
size: 'lg',
resolve: { resolve: {
eventId: function () { return event.Event.Id; }, eventId: function () { return event.Event.Id; },
index: function () { return index; } index: function () { return index; }
@ -141,7 +142,9 @@ ZoneMinder.controller('EventsController', function($scope, Events, Console, $mod
}; };
}); });
ZoneMinder.controller('EventController', function($scope, Event, $modalInstance, eventId, index) { ZoneMinder.controller('EventController', function($scope, Event, $modalInstance, eventId, index, Config) {
$scope.stream = true;
Event.get(eventId).then(function(results) { Event.get(eventId).then(function(results) {
$scope.eventId = eventId; $scope.eventId = eventId;
@ -159,6 +162,13 @@ ZoneMinder.controller('EventController', function($scope, Event, $modalInstance,
$scope.notes = results.data.event.Event.Notes; $scope.notes = results.data.event.Event.Notes;
$scope.archived = results.data.event.Event.Archived; $scope.archived = results.data.event.Event.Archived;
$scope.archive_text = $scope.archived == 0 ? 'Archive' : 'Unarchive'; $scope.archive_text = $scope.archived == 0 ? 'Archive' : 'Unarchive';
$scope.eventView_text = 'Frames';
$scope.frames = results.data.event.Frame;
$scope.basePath = results.data.event.Event.BasePath;
Config.findByName('ZM_EVENT_IMAGE_DIGITS').then(function(results) {
$scope.event_image_digits = results.data.config.Value;
});
}); });
$scope.cancel = function () { $scope.cancel = function () {
@ -178,6 +188,11 @@ ZoneMinder.controller('EventController', function($scope, Event, $modalInstance,
$scope.archive_text = $scope.archived == 0 ? 'Archive' : 'Unarchive'; $scope.archive_text = $scope.archived == 0 ? 'Archive' : 'Unarchive';
}); });
}; };
$scope.eventView = function() {
$scope.eventView_text = 'Stream';
$scope.stream = $scope.stream == true ? false : true;
};
}); });
ZoneMinder.controller('MonitorController', function($scope, $http, $location, Monitor) { ZoneMinder.controller('MonitorController', function($scope, $http, $location, Monitor) {

View File

@ -0,0 +1,17 @@
<div id="event-frames-stills" ng-hide="stream" class="flexcontainer" >
<div ng-repeat="frame in frames" class="frame panel" ng-class="(frame.Type == 'Alarm') ? 'panel-danger' : 'panel-default'">
<div class="panel-heading">
<span class="pull-right" ng-bind="frame.FrameId"></span>
<span ng-bind="frame.TimeStamp"></span>
</div>
<div class="panel-body">
<div class="thumbnail">
<img ng-src="{{basePath}}{{ frame.FrameId | zpad:event_image_digits }}-capture.jpg" alt="Frame {{frame.FrameId}}" class="img-responsive" />
</div>
<ul>
<li>Delta: <span ng-bind="frame.Delta"></span></li>
<li>Score: <span ng-bind="frame.Score"></span></li>
</ul>
</div>
</div>
</div>

View File

@ -1,16 +1,15 @@
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" ng-click="cancel()"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button> <span class="pull-right modal-title">Event {{eventId}}</span>
<span class="modal-title">Event {{eventId}}</span> <span ng-bind="startTime"></span>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div id="eventStream"> <div id="eventStream" ng-show="stream">
<img class="img-responsive" ng-src="/cgi-bin/nph-zms?source=event&mode=jpeg&event={{eventId}}&frame=1&scale=100&rate=100&maxfps=30&replay=single&connkey=736818&rand=1419877749" /> <img class="img-responsive" ng-src="/cgi-bin/nph-zms?source=event&mode=jpeg&event={{eventId}}&frame=1&scale=100&rate=100&maxfps=30&replay=single&connkey=736818&rand=1419877749" />
<div> <div>
<span class="pull-right">{{ startTime | DateDiff:endTime:'pretty' }}</span> <span class="pull-right">{{ startTime | DateDiff:endTime:'pretty' }}</span>
<span class="pull-left" ng-bind="startTime"></span>
<div id="controls" class="text-center"> <div id="controls" class="text-center">
Start || Pause Start || Pause
</div> </div>
@ -18,8 +17,11 @@
</div> </div>
</div> </div>
<?php include("event-frames-stills.html"); ?>
<div class="modal-footer"> <div class="modal-footer">
<span class="pull-right glyphicon glyphicon-chevron-right"><span class="sr-only">Next</span></span> <span class="pull-right glyphicon glyphicon-chevron-right"><span class="sr-only">Next</span></span>
<button type="button" class="btn btn-default" ng-click="eventView()">{{ eventView_text }}</button>
<button type="button" class="btn btn-default" ng-click="archive()">{{ archive_text }}</button> <button type="button" class="btn btn-default" ng-click="archive()">{{ archive_text }}</button>
<button type="button" class="btn btn-danger" ng-click="delete()">Delete</button> <button type="button" class="btn btn-danger" ng-click="delete()">Delete</button>
<button type="button" class="btn btn-warning" ng-click="cancel()">Cancel</button> <button type="button" class="btn btn-warning" ng-click="cancel()">Cancel</button>