diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in
index ecb3fe0dc..fe05585e4 100644
--- a/db/zm_create.sql.in
+++ b/db/zm_create.sql.in
@@ -409,7 +409,7 @@ deterministic
begin
- update Storage set DiskSpace = DiskSpace + space where Id = StorageId;
+ update Storage set DiskSpace = COALESCE(DiskSpace,0) + COALESCE(space,0) where Id = StorageId;
end;
@@ -496,7 +496,9 @@ DROP TRIGGER IF EXISTS event_delete_trigger//
CREATE TRIGGER event_delete_trigger BEFORE DELETE ON Events
FOR EACH ROW
BEGIN
- call update_storage_stats(OLD.StorageId, -OLD.DiskSpace);
+ IF ( OLD.DiskSpace ) THEN
+ call update_storage_stats(OLD.StorageId, -OLD.DiskSpace);
+ END IF;
DELETE FROM Events_Hour WHERE EventId=OLD.Id;
DELETE FROM Events_Day WHERE EventId=OLD.Id;
DELETE FROM Events_Week WHERE EventId=OLD.Id;
diff --git a/db/zm_update-1.31.37.sql b/db/zm_update-1.31.37.sql
new file mode 100644
index 000000000..866fd9330
--- /dev/null
+++ b/db/zm_update-1.31.37.sql
@@ -0,0 +1,49 @@
+DROP PROCEDURE IF EXISTS update_storage_stats;
+
+DELIMITER //
+
+CREATE PROCEDURE update_storage_stats(IN StorageId smallint(5), IN space BIGINT)
+
+sql security invoker
+
+deterministic
+
+begin
+
+ update Storage set DiskSpace = COALESCE(DiskSpace,0) + COALESCE(space,0) where Id = StorageId;
+
+end;
+
+//
+
+DROP TRIGGER IF EXISTS event_delete_trigger//
+
+CREATE TRIGGER event_delete_trigger BEFORE DELETE ON Events
+FOR EACH ROW
+ BEGIN
+ IF ( OLD.DiskSpace ) THEN
+ call update_storage_stats(OLD.StorageId, -OLD.DiskSpace);
+ END IF;
+ DELETE FROM Events_Hour WHERE EventId=OLD.Id;
+ DELETE FROM Events_Day WHERE EventId=OLD.Id;
+ DELETE FROM Events_Week WHERE EventId=OLD.Id;
+ DELETE FROM Events_Month WHERE EventId=OLD.Id;
+ IF ( OLD.Archived ) THEN
+ DELETE FROM Events_Archived WHERE EventId=OLD.Id;
+ UPDATE Monitors SET
+ ArchivedEvents = ArchivedEvents - 1,
+ ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),
+ TotalEvents = TotalEvents - 1,
+ TotalEventDiskSpace = COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0)
+ WHERE Id=OLD.MonitorId;
+ ELSE
+ UPDATE Monitors SET
+ TotalEvents = TotalEvents-1,
+ TotalEventDiskSpace=COALESCE(TotalEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0)
+ WHERE Id=OLD.MonitorId;
+ END IF;
+ END;
+
+//
+
+UPDATE Storage SET DiskSpace=(SELECT SUM(COALESCE(DiskSpace,0)) FROM Events WHERE StorageId=Storage.Id)//
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm
index 766436a84..0eb9e2763 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm
@@ -470,7 +470,7 @@ sub DiskSpace {
$_[0]{DiskSpace} = $size;
Debug("DiskSpace for event $_[0]{Id} at $_[0]{Path} Updated to $size bytes");
} else {
- Warning("Event does not exist at $_[0]{Path}");
+ Warning("DiskSpace: Event does not exist at $_[0]{Path}:" . $Event->to_string() );
}
} # end if ! defined DiskSpace
return $_[0]{DiskSpace};
diff --git a/version b/version
index c2db3b3d2..c6e42f25b 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.31.36
+1.31.37
diff --git a/web/skins/classic/css/base/views/montagereview.css b/web/skins/classic/css/base/views/montagereview.css
index e82e5ae95..4fb55a337 100644
--- a/web/skins/classic/css/base/views/montagereview.css
+++ b/web/skins/classic/css/base/views/montagereview.css
@@ -2,7 +2,6 @@
#SpeedDiv{
vertical-align: top;
display: inline-flex;
- border: 1px solid black;
width: 25%;
padding: 4px;
}
@@ -10,6 +9,14 @@
#SpeedDiv label {
margin: 0;
}
+#ButtonsDiv {
+ display: inline-flex;
+ flex-flow: row-wrap;
+}
+#ButtonsDiv button {
+display: inline-flex;
+min-width: 0;
+}
#DateTimeDiv {
display: inline-flex;
}
@@ -23,7 +30,7 @@
#timelinediv {
margin: 2px auto;
position:relative;
- width:93%;
+ width:100%;
}
#timeline {
diff --git a/web/skins/classic/css/base/views/zone.css b/web/skins/classic/css/base/views/zone.css
index 6b35ca287..c2feb6734 100644
--- a/web/skins/classic/css/base/views/zone.css
+++ b/web/skins/classic/css/base/views/zone.css
@@ -52,11 +52,11 @@
}
#imageFrame div {
- background-image: url(../../../graphics/point-g.png);
+ background-image: url(/zm/skins/classic/graphics/point-g.png);
}
#imageFrame div.highlight {
- background-image: url(../../../graphics/point-o.png);
+ background-image: url(/zm/skins/classic/graphics/point-o.png);
}
#imageFrame div.active {
diff --git a/web/skins/classic/includes/export_functions.php b/web/skins/classic/includes/export_functions.php
index 246554564..5d23b1125 100644
--- a/web/skins/classic/includes/export_functions.php
+++ b/web/skins/classic/includes/export_functions.php
@@ -72,7 +72,7 @@ html ul.tabs li.active, html ul.tabs li.active a:hover {
-->
@@ -140,7 +141,11 @@ echo output_link_if_exists( array(
+
+
|
-
-
-
-
-
+
+
+
+
|
$limit ) {
$nEvents = $limit;
}
$pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE);
+#Logger::Debug("Page $page Limit $limit #vents: $nEvents pages: $pages ");
if ( !empty($page) ) {
if ( $page < 0 )
$page = 1;
- else if ( $page > $pages )
+ else if ( $pages and ( $page > $pages ) )
$page = $pages;
$limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE);
diff --git a/web/skins/classic/views/js/console.js b/web/skins/classic/views/js/console.js
index 2121b6e39..b6d08e525 100644
--- a/web/skins/classic/views/js/console.js
+++ b/web/skins/classic/views/js/console.js
@@ -1,22 +1,35 @@
-var jsTranslatedAddText;
-var jsTranslatedCloneText;
function setButtonStates( element ) {
var form = element.form;
var checked = 0;
- for ( var i = 0; i < form.elements.length; i++ ) {
- if ( form.elements[i].type == "checkbox" ) {
+ for ( var i=0; i < form.elements.length; i++ ) {
+ if (
+ form.elements[i].type=="checkbox"
+ &&
+ form.elements[i].name=="markMids[]"
+ ) {
+ var tr = $j(form.elements[i]).closest("tr");
if ( form.elements[i].checked ) {
- if ( checked++ > 1 )
- break;
+ checked ++;
+ tr.addClass("danger");
+ } else {
+ tr.removeClass("danger");
}
}
}
- $(element).closest("tr").toggleClass("danger");
- form.editBtn.disabled = checked ? false : true;
- form.addBtn.value = (checked==1) ? jsTranslatedCloneText:jsTranslatedAddText;
-
- form.deleteBtn.disabled = (checked==0);
+ if ( checked ) {
+ form.editBtn.disabled = false;
+ form.deleteBtn.disabled = false;
+ if ( checked == 1 ) {
+ $j(form.cloneBtn).css('display','inline');
+ } else {
+ form.cloneBtn.hide();
+ }
+ } else {
+ form.cloneBtn.hide();
+ form.editBtn.disabled = true;
+ form.deleteBtn.disabled = true;
+ }
}
function addMonitor(element) {
@@ -75,8 +88,6 @@ function reloadWindow() {
}
function initPage() {
- jsTranslatedAddText = translatedAddText;
- jsTranslatedCloneText = translatedCloneText;
reloadWindow.periodical( consoleRefreshTimeout );
if ( showVersionPopup )
createPopup( '?view=version', 'zmVersion', 'version' );
@@ -84,7 +95,7 @@ function initPage() {
createPopup( '?view=donate', 'zmDonate', 'donate' );
// Makes table sortable
-$j( function() {
+ $j( function() {
$j( "#consoleTableBody" ).sortable({
handle: ".glyphicon-sort",
update: applySort,
diff --git a/web/skins/classic/views/js/console.js.php b/web/skins/classic/views/js/console.js.php
index 006cfc565..f5e65332d 100644
--- a/web/skins/classic/views/js/console.js.php
+++ b/web/skins/classic/views/js/console.js.php
@@ -18,5 +18,3 @@ if ( ZM_CHECK_FOR_UPDATES && canEdit('System') && ZM_DYN_LAST_VERSION && ( verNu
?>
var showVersionPopup = ;
var showDonatePopup = ;
-var translatedAddText = "";
-var translatedCloneText = "";
diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js
index a07a0ccc6..63fce8910 100644
--- a/web/skins/classic/views/js/montagereview.js
+++ b/web/skins/classic/views/js/montagereview.js
@@ -49,28 +49,28 @@ function SetImageSource( monId, time ) {
if ( liveMode == 1 ) {
return monitorImageObject[monId].src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
- } else {
- for ( var i=0, eIdlength = eId.length; i < eIdlength; i++ ) {
- // Search for the event matching this time. Would be more efficient if we had events indexed by monitor
- if ( eMonId[i] == monId && time >= eStartSecs[i] && time <= eEndSecs[i] ) {
- var duration = eEndSecs[i]-eStartSecs[i];
- var frame = parseInt((time - eStartSecs[i])/(duration)*eventFrames[i])+1;
- var storage = Storage[eStorageId[i]];
- if ( storage.ServerId ) {
- var server = Servers[storage.ServerId];
- if ( server ) {
-//console.log( server.Hostname + " for event " + eId[i] );
- return location.protocol + '//' + server.Hostname + '/index.php?view=image&eid=' + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height;
- } else {
- console.log("No server found for " + storage.ServerId );
- }
- }
- //console.log("No storage found for " + eStorageId[i] );
- return "index.php?view=image&eid=" + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height;
- }
- } // end for
- return "no data";
}
+
+ for ( var i=0, eIdlength = eId.length; i < eIdlength; i++ ) {
+ // Search for the event matching this time. Would be more efficient if we had events indexed by monitor
+ if ( eMonId[i] == monId && time >= eStartSecs[i] && time <= eEndSecs[i] ) {
+ var duration = eEndSecs[i]-eStartSecs[i];
+ var frame = parseInt((time - eStartSecs[i])/(duration)*eventFrames[i])+1;
+ var storage = Storage[eStorageId[i]];
+ if ( storage.ServerId ) {
+ var server = Servers[storage.ServerId];
+ if ( server ) {
+//console.log( server.Hostname + " for event " + eId[i] );
+ return location.protocol + '//' + server.Hostname + '/index.php?view=image&eid=' + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height;
+ } else {
+ console.log("No server found for " + storage.ServerId );
+ }
+ }
+ //console.log("No storage found for " + eStorageId[i] );
+ return "index.php?view=image&eid=" + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height;
+ }
+ } // end for
+ return "no data";
}
// callback when loading an image. Will load itself to the canvas, or draw no data
@@ -164,7 +164,7 @@ function loadImage2Monitor( monId, url ) {
function timerFire() {
// See if we need to reschedule
- if ( currentDisplayInterval != timerInterval || currentSpeed == 0 ) {
+ if ( ( currentDisplayInterval != timerInterval ) || ( currentSpeed == 0 ) ) {
// zero just turn off interrupts
clearInterval(timerObj);
timerInterval=currentDisplayInterval;
@@ -335,60 +335,61 @@ function drawGraph() {
}
function redrawScreen() {
- if ( liveMode == 1 ) {
+ if ( liveMode == 1 ) {
// if we are not in live view switch to history -- this has to come before fit in case we re-establish the timeline
- $('DateTimeDiv').style.display="none";
- $('SpeedDiv').style.display="none";
- $('timelinediv').style.display="none";
- $('live').innerHTML="History";
- $('zoomin').style.display="none";
- $('zoomout').style.display="none";
- $('panleft').style.display="none";
- $('panright').style.display="none";
- if ($('downloadVideo')) $('downloadVideo').style.display="none";
+ $('DateTimeDiv').style.display="none";
+ $('SpeedDiv').style.display="none";
+ $('timelinediv').style.display="none";
+ $('live').innerHTML="History";
+ $('zoomin').style.display="none";
+ $('zoomout').style.display="none";
+ $('panleft').style.display="none";
+ $('panright').style.display="none";
+ if ($('downloadVideo')) $('downloadVideo').style.display="none";
- } else {
+ } else {
// switch out of liveview mode
- $('DateTimeDiv').style.display="inline";
- $('SpeedDiv').style.display="inline";
- $('SpeedDiv').style.display="inline-flex";
- $('timelinediv').style.display=null;
- $('live').innerHTML="Live";
- $('zoomin').style.display="inline";
- $('zoomin').style.display="inline-flex";
- $('zoomout').style.display="inline";
- $('zoomout').style.display="inline-flex";
- $('panleft').style.display="inline";
- $('panleft').style.display="inline-flex";
- $('panright').style.display="inline";
- $('panright').style.display="inline-flex";
- if ($('downloadVideo')) $('downloadVideo').style.display="inline";
- }
+ $('DateTimeDiv').style.display="inline";
+ $('DateTimeDiv').style.display="inline-flex";
+ $('SpeedDiv').style.display="inline";
+ $('SpeedDiv').style.display="inline-flex";
+ $('timelinediv').style.display=null;
+ $('live').innerHTML="Live";
+ $('zoomin').style.display="inline";
+ $('zoomin').style.display="inline-flex";
+ $('zoomout').style.display="inline";
+ $('zoomout').style.display="inline-flex";
+ $('panleft').style.display="inline";
+ $('panleft').style.display="inline-flex";
+ $('panright').style.display="inline";
+ $('panright').style.display="inline-flex";
+ if ($('downloadVideo')) $('downloadVideo').style.display="inline";
+ }
- if ( fitMode == 1 ) {
- $('ScaleDiv').style.display="none";
- $('fit').innerHTML="Scale";
- var vh=window.innerHeight;
- var vw=window.innerWidth;
- var pos=$('monitors').getPosition();
- var mh=(vh - pos.y - $('fps').getSize().y);
- $('monitors').setStyle('height',mh.toString() + "px"); // leave a small gap at bottom
- if(maxfit2($('monitors').getSize().x,$('monitors').getSize().y) == 0) /// if we fail to fix we back out of fit mode -- ??? This may need some better handling
- fitMode=1-fitMode;
- } else {
- // switch out of fit mode
- // if we fit, then monitors were absolutely positioned already (or will be) otherwise release them to float
- for( var i=0; i
fps
-