Merge branch 'master' of github.com:ZoneMinder/zoneminder

This commit is contained in:
Isaac Connor 2021-11-09 14:00:25 -05:00
commit 96a58f8c88
9 changed files with 83 additions and 74 deletions

View File

@ -4,7 +4,7 @@
web/api/lib web/api/lib
web/includes/csrf/ web/includes/csrf/
web/js/videojs.zoomrotate.js web/js/videojs.zoomrotate.js
web/skins/classic/js/bootstrap.js web/skins/classic/js/bootstrap-4.5.0.js
web/skins/classic/js/chosen web/skins/classic/js/chosen
web/skins/classic/js/dateTimePicker web/skins/classic/js/dateTimePicker
web/skins/classic/js/jquery-*.js web/skins/classic/js/jquery-*.js

View File

@ -323,32 +323,32 @@ void Event::updateNotes(const StringSetMap &newNoteSetMap) {
bool update = false; bool update = false;
//Info( "Checking notes, %d <> %d", noteSetMap.size(), newNoteSetMap.size() ); //Info( "Checking notes, %d <> %d", noteSetMap.size(), newNoteSetMap.size() );
if ( newNoteSetMap.size() > 0 ) { if (newNoteSetMap.size() > 0) {
if ( noteSetMap.size() == 0 ) { if (noteSetMap.size() == 0) {
noteSetMap = newNoteSetMap; noteSetMap = newNoteSetMap;
update = true; update = true;
} else { } else {
for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); for (StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin();
newNoteSetMapIter != newNoteSetMap.end(); newNoteSetMapIter != newNoteSetMap.end();
++newNoteSetMapIter ) { ++newNoteSetMapIter) {
const std::string &newNoteGroup = newNoteSetMapIter->first; const std::string &newNoteGroup = newNoteSetMapIter->first;
const StringSet &newNoteSet = newNoteSetMapIter->second; const StringSet &newNoteSet = newNoteSetMapIter->second;
//Info( "Got %d new strings", newNoteSet.size() ); //Info( "Got %d new strings", newNoteSet.size() );
if ( newNoteSet.size() > 0 ) { if (newNoteSet.size() > 0) {
StringSetMap::iterator noteSetMapIter = noteSetMap.find(newNoteGroup); StringSetMap::iterator noteSetMapIter = noteSetMap.find(newNoteGroup);
if ( noteSetMapIter == noteSetMap.end() ) { if (noteSetMapIter == noteSetMap.end()) {
//Info( "Can't find note group %s, copying %d strings", newNoteGroup.c_str(), newNoteSet.size() ); //Debug(3, "Can't find note group %s, copying %d strings", newNoteGroup.c_str(), newNoteSet.size());
noteSetMap.insert(StringSetMap::value_type(newNoteGroup, newNoteSet)); noteSetMap.insert(StringSetMap::value_type(newNoteGroup, newNoteSet));
update = true; update = true;
} else { } else {
StringSet &noteSet = noteSetMapIter->second; StringSet &noteSet = noteSetMapIter->second;
//Info( "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size() ); //Debug(3, "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size());
for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); for (StringSet::const_iterator newNoteSetIter = newNoteSet.begin();
newNoteSetIter != newNoteSet.end(); newNoteSetIter != newNoteSet.end();
++newNoteSetIter ) { ++newNoteSetIter) {
const std::string &newNote = *newNoteSetIter; const std::string &newNote = *newNoteSetIter;
StringSet::iterator noteSetIter = noteSet.find(newNote); StringSet::iterator noteSetIter = noteSet.find(newNote);
if ( noteSetIter == noteSet.end() ) { if (noteSetIter == noteSet.end()) {
noteSet.insert(newNote); noteSet.insert(newNote);
update = true; update = true;
} }

View File

@ -141,7 +141,7 @@ bool EventStream::loadEventData(uint64_t event_id) {
event_data->storage_id = dbrow[1] ? atoi(dbrow[1]) : 0; event_data->storage_id = dbrow[1] ? atoi(dbrow[1]) : 0;
event_data->frame_count = dbrow[2] == nullptr ? 0 : atoi(dbrow[2]); event_data->frame_count = dbrow[2] == nullptr ? 0 : atoi(dbrow[2]);
event_data->start_time = SystemTimePoint(Seconds(atoi(dbrow[3]))); event_data->start_time = SystemTimePoint(Seconds(atoi(dbrow[3])));
event_data->end_time = dbrow[4] ? SystemTimePoint(Seconds(atoi(dbrow[4]))) : SystemTimePoint(); event_data->end_time = dbrow[4] ? SystemTimePoint(Seconds(atoi(dbrow[4]))) : std::chrono::system_clock::now();
event_data->duration = std::chrono::duration_cast<Microseconds>(event_data->end_time - event_data->start_time); event_data->duration = std::chrono::duration_cast<Microseconds>(event_data->end_time - event_data->start_time);
event_data->frames_duration = event_data->frames_duration =
std::chrono::duration_cast<Microseconds>(dbrow[5] ? FPSeconds(atof(dbrow[5])) : FPSeconds(0.0)); std::chrono::duration_cast<Microseconds>(dbrow[5] ? FPSeconds(atof(dbrow[5])) : FPSeconds(0.0));

View File

@ -1862,8 +1862,6 @@ bool Monitor::Analyse() {
Debug(3, "signal and active and modect"); Debug(3, "signal and active and modect");
Event::StringSet zoneSet; Event::StringSet zoneSet;
int motion_score = last_motion_score;
if (analysis_fps_limit) { if (analysis_fps_limit) {
double capture_fps = get_capture_fps(); double capture_fps = get_capture_fps();
motion_frame_skip = capture_fps / analysis_fps_limit; motion_frame_skip = capture_fps / analysis_fps_limit;
@ -1880,7 +1878,7 @@ bool Monitor::Analyse() {
} else { } else {
Debug(1, "Detecting motion on image %d, image %p", snap->image_index, snap->image); Debug(1, "Detecting motion on image %d, image %p", snap->image_index, snap->image);
// Get new score. // Get new score.
motion_score = DetectMotion(*(snap->image), zoneSet); int motion_score = DetectMotion(*(snap->image), zoneSet);
snap->zone_stats.reserve(zones.size()); snap->zone_stats.reserve(zones.size());
for (const Zone &zone : zones) { for (const Zone &zone : zones) {
@ -1892,21 +1890,20 @@ bool Monitor::Analyse() {
Debug(3, "After motion detection, score:%d last_motion_score(%d), new motion score(%d)", Debug(3, "After motion detection, score:%d last_motion_score(%d), new motion score(%d)",
score, last_motion_score, motion_score); score, last_motion_score, motion_score);
motion_frame_count += 1; motion_frame_count += 1;
// Why are we updating the last_motion_score too?
last_motion_score = motion_score; last_motion_score = motion_score;
if (motion_score) {
if (cause.length()) cause += ", ";
cause += MOTION_CAUSE;
noteSetMap[MOTION_CAUSE] = zoneSet;
} // end if motion_score
} }
} else { } else {
Debug(1, "no image so skipping motion detection"); Debug(1, "no image so skipping motion detection");
} // end if has image } // end if has image
} else { } else {
Debug(1, "Skipped motion detection last motion score was %d", motion_score); Debug(1, "Skipped motion detection last motion score was %d", last_motion_score);
} }
if (motion_score) { score += last_motion_score;
score += motion_score;
if (cause.length()) cause += ", ";
cause += MOTION_CAUSE;
noteSetMap[MOTION_CAUSE] = zoneSet;
} // end if motion_score
} else { } else {
Debug(1, "Not Active(%d) enabled %d active %d doing motion detection: %d", Debug(1, "Not Active(%d) enabled %d active %d doing motion detection: %d",
Active(), enabled, shared_data->active, Active(), enabled, shared_data->active,
@ -2007,7 +2004,7 @@ bool Monitor::Analyse() {
} // end if ! event } // end if ! event
} // end if RECORDING } // end if RECORDING
if (score and (function == MODECT or function == NODECT)) { if (score and (function != MONITOR)) {
if ((state == IDLE) || (state == TAPE) || (state == PREALARM)) { if ((state == IDLE) || (state == TAPE) || (state == PREALARM)) {
// If we should end then previous continuous event and start a new non-continuous event // If we should end then previous continuous event and start a new non-continuous event
if (event && event->Frames() if (event && event->Frames()
@ -2142,7 +2139,8 @@ bool Monitor::Analyse() {
shared_data->state = state = ((function != MOCORD) ? IDLE : TAPE); shared_data->state = state = ((function != MOCORD) ? IDLE : TAPE);
} else { } else {
Debug(1, Debug(1,
"State %s because image_count(%d)-last_alarm_count(%d) > post_event_count(%d) and timestamp.tv_sec(%" PRIi64 ") - recording.tv_src(%" PRIi64 ") >= min_section_length(%" PRIi64 ")", "State %d %s because analysis_image_count(%d)-last_alarm_count(%d) > post_event_count(%d) and timestamp.tv_sec(%" PRIi64 ") - recording.tv_src(%" PRIi64 ") >= min_section_length(%" PRIi64 ")",
state,
State_Strings[state].c_str(), State_Strings[state].c_str(),
analysis_image_count, analysis_image_count,
last_alarm_count, last_alarm_count,
@ -2161,12 +2159,10 @@ bool Monitor::Analyse() {
// Generate analysis images if necessary // Generate analysis images if necessary
if ((savejpegs > 1) and snap->image) { if ((savejpegs > 1) and snap->image) {
for (const Zone &zone : zones) { for (const Zone &zone : zones) {
if (zone.Alarmed()) { if (zone.Alarmed() and zone.AlarmImage()) {
if (zone.AlarmImage()) {
if (!snap->analysis_image) if (!snap->analysis_image)
snap->analysis_image = new Image(*(snap->image)); snap->analysis_image = new Image(*(snap->image));
snap->analysis_image->Overlay(*(zone.AlarmImage())); snap->analysis_image->Overlay(*(zone.AlarmImage()));
}
} // end if zone is alarmed } // end if zone is alarmed
} // end foreach zone } // end foreach zone
} // end if savejpegs } // end if savejpegs

View File

@ -67,20 +67,19 @@ if (isset($_REQUEST['sort'])) {
// Offset specifies the starting row to return, used for pagination // Offset specifies the starting row to return, used for pagination
$offset = 0; $offset = 0;
if ( isset($_REQUEST['offset']) ) { if (isset($_REQUEST['offset'])) {
if ( ( !is_int($_REQUEST['offset']) and !ctype_digit($_REQUEST['offset']) ) ) { if ((!is_int($_REQUEST['offset']) and !ctype_digit($_REQUEST['offset']))) {
ZM\Error('Invalid value for offset: ' . $_REQUEST['offset']); ZM\Error('Invalid value for offset: ' . $_REQUEST['offset']);
} else { } else {
$offset = $_REQUEST['offset']; $offset = $_REQUEST['offset'];
} }
} }
// Limit specifies the number of rows to return // Limit specifies the number of rows to return
// Set the default to 0 for events view, to prevent an issue with ALL pagination // Set the default to 0 for events view, to prevent an issue with ALL pagination
$limit = 0; $limit = 0;
if ( isset($_REQUEST['limit']) ) { if (isset($_REQUEST['limit'])) {
if ( ( !is_int($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) { if ((!is_int($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']))) {
ZM\Error('Invalid value for limit: ' . $_REQUEST['limit']); ZM\Error('Invalid value for limit: ' . $_REQUEST['limit']);
} else { } else {
$limit = $_REQUEST['limit']; $limit = $_REQUEST['limit'];
@ -91,25 +90,24 @@ if ( isset($_REQUEST['limit']) ) {
// MAIN LOOP // MAIN LOOP
// //
switch ( $task ) { switch ($task) {
case 'archive' : case 'archive' :
foreach ( $eids as $eid ) archiveRequest($task, $eid); foreach ($eids as $eid) archiveRequest($task, $eid);
break; break;
case 'unarchive' : case 'unarchive' :
# The idea is that anyone can archive, but only people with Event Edit permission can unarchive.. # The idea is that anyone can archive, but only people with Event Edit permission can unarchive..
if ( !canEdit('Events') ) { if (!canEdit('Events')) {
ajaxError('Insufficient permissions for user '.$user['Username']); ajaxError('Insufficient permissions for user '.$user['Username']);
return; return;
} }
foreach ( $eids as $eid ) archiveRequest($task, $eid); foreach ($eids as $eid) archiveRequest($task, $eid);
break; break;
case 'delete' : case 'delete' :
if ( !canEdit('Events') ) { if (!canEdit('Events')) {
ajaxError('Insufficient permissions for user '.$user['Username']); ajaxError('Insufficient permissions for user '.$user['Username']);
return; return;
} }
foreach ($eids as $eid) $data[] = deleteRequest($eid);
foreach ( $eids as $eid ) $data[] = deleteRequest($eid);
break; break;
case 'query' : case 'query' :
$data = queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $limit); $data = queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $limit);
@ -139,6 +137,8 @@ function deleteRequest($eid) {
$message[] = array($eid=>'Event not found.'); $message[] = array($eid=>'Event not found.');
} else if ( $event->Archived() ) { } else if ( $event->Archived() ) {
$message[] = array($eid=>'Event is archived, cannot delete it.'); $message[] = array($eid=>'Event is archived, cannot delete it.');
} else if (!$event->canEdit()) {
$message[] = array($eid=>'You do not have permission to delete event '.$event->Id());
} else { } else {
$event->delete(); $event->delete();
} }
@ -147,7 +147,6 @@ function deleteRequest($eid) {
} }
function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $limit) { function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $limit) {
$data = array( $data = array(
'total' => 0, 'total' => 0,
'totalNotFiltered' => 0, 'totalNotFiltered' => 0,
@ -156,7 +155,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
); );
$failed = !$filter->test_pre_sql_conditions(); $failed = !$filter->test_pre_sql_conditions();
if ( $failed ) { if ($failed) {
ZM\Debug('Pre conditions failed, not doing sql'); ZM\Debug('Pre conditions failed, not doing sql');
return $data; return $data;
} }
@ -171,7 +170,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
// The names of columns shown in the event view that are NOT dB columns in the database // The names of columns shown in the event view that are NOT dB columns in the database
$col_alt = array('Monitor', 'Storage'); $col_alt = array('Monitor', 'Storage');
if ( !in_array($sort, array_merge($columns, $col_alt)) ) { if (!in_array($sort, array_merge($columns, $col_alt))) {
ZM\Error('Invalid sort field: ' . $sort); ZM\Error('Invalid sort field: ' . $sort);
$sort = 'Id'; $sort = 'Id';
} }
@ -186,7 +185,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
$storage_areas = ZM\Storage::find(); $storage_areas = ZM\Storage::find();
$StorageById = array(); $StorageById = array();
foreach ( $storage_areas as $S ) { foreach ($storage_areas as $S) {
$StorageById[$S->Id()] = $S; $StorageById[$S->Id()] = $S;
} }
@ -195,41 +194,43 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
ZM\Debug('Calling the following sql query: ' .$sql); ZM\Debug('Calling the following sql query: ' .$sql);
$query = dbQuery($sql, $values); $query = dbQuery($sql, $values);
if ( $query ) { if (!$query) {
while ( $row = dbFetchNext($query) ) { ajaxError(dbError($sql));
$event = new ZM\Event($row); return;
$event->remove_from_cache();
if ( !$filter->test_post_sql_conditions($event) ) {
continue;
}
$event_ids[] = $event->Id();
$unfiltered_rows[] = $row;
} # end foreach row
} }
while ($row = dbFetchNext($query)) {
$event = new ZM\Event($row);
$event->remove_from_cache();
if (!$filter->test_post_sql_conditions($event)) {
continue;
}
$event_ids[] = $event->Id();
$unfiltered_rows[] = $row;
} # end foreach row
ZM\Debug('Have ' . count($unfiltered_rows) . ' events matching base filter.'); ZM\Debug('Have ' . count($unfiltered_rows) . ' events matching base filter.');
$filtered_rows = null; $filtered_rows = null;
if ( count($advsearch) or $search != '' ) { if (count($advsearch) or $search != '') {
$search_filter = new ZM\Filter(); $search_filter = new ZM\Filter();
$search_filter = $search_filter->addTerm(array('cnj'=>'and', 'attr'=>'Id', 'op'=>'IN', 'val'=>$event_ids)); $search_filter = $search_filter->addTerm(array('cnj'=>'and', 'attr'=>'Id', 'op'=>'IN', 'val'=>$event_ids));
// There are two search bars in the log view, normal and advanced // There are two search bars in the log view, normal and advanced
// Making an exuctive decision to ignore the normal search, when advanced search is in use // Making an exuctive decision to ignore the normal search, when advanced search is in use
// Alternatively we could try to do both // Alternatively we could try to do both
if ( count($advsearch) ) { if (count($advsearch)) {
$terms = array(); $terms = array();
foreach ( $advsearch as $col=>$text ) { foreach ($advsearch as $col=>$text) {
$terms[] = array('cnj'=>'and', 'attr'=>$col, 'op'=>'LIKE', 'val'=>$text); $terms[] = array('cnj'=>'and', 'attr'=>$col, 'op'=>'LIKE', 'val'=>$text);
} # end foreach col in advsearch } # end foreach col in advsearch
$terms[0]['obr'] = 1; $terms[0]['obr'] = 1;
$terms[count($terms)-1]['cbr'] = 1; $terms[count($terms)-1]['cbr'] = 1;
$search_filter->addTerms($terms); $search_filter->addTerms($terms);
} else if ( $search != '' ) { } else if ($search != '') {
$search = '%' .$search. '%'; $search = '%' .$search. '%';
$terms = array(); $terms = array();
foreach ( $columns as $col ) { foreach ($columns as $col) {
$terms[] = array('cnj'=>'or', 'attr'=>$col, 'op'=>'LIKE', 'val'=>$search); $terms[] = array('cnj'=>'or', 'attr'=>$col, 'op'=>'LIKE', 'val'=>$search);
} }
$terms[0]['obr'] = 1; $terms[0]['obr'] = 1;

View File

@ -38,7 +38,7 @@ if ($zmuOutput) {
$ctls = shell_exec('v4l2-ctl -d '.$monitor->Device().' --list-ctrls'); $ctls = shell_exec('v4l2-ctl -d '.$monitor->Device().' --list-ctrls');
if (!$ctls) { if (!$ctls) {
ZM\Warning("Guessing v4l ctrls. We need v4l2-ctl please install it"); ZM\Warning('Guessing v4l ctrls. We need v4l2-ctl please install it');
$ctls = ' $ctls = '
brightness 0x00980900 (int) : min=-10 max=10 step=1 default=0 value=8 brightness 0x00980900 (int) : min=-10 max=10 step=1 default=0 value=8
contrast 0x00980901 (int) : min=0 max=20 step=1 default=10 value=12 contrast 0x00980901 (int) : min=0 max=20 step=1 default=10 value=12
@ -83,10 +83,15 @@ foreach ($ctls as $line) {
} }
} }
$label = translate($setting_uc);
if ($label == $setting_uc) {
$label = ucwords(str_replace('_', ' ', $label));
}
if ($setting == 'brightness' or $setting == 'colour' or $setting == 'contrast' or $setting == 'hue') { if ($setting == 'brightness' or $setting == 'colour' or $setting == 'contrast' or $setting == 'hue') {
echo ' echo '
<tr> <tr>
<th scope="row">'.translate($setting_uc).'</th> <th scope="row">'.$label.'</th>
<td>'.$min.'</td><td><input type="range" title="'.$value.'" min="'.$min.'" max="'.$max.'" step="'.$step.'" default="'.$default.'" value="'.$value.'" id="new'.$setting_uc.'" name="new'.$setting_uc.'" '.(canEdit('Control') ? '' : 'disabled="disabled"') .'/></td><td>'.$max.'</td> <td>'.$min.'</td><td><input type="range" title="'.$value.'" min="'.$min.'" max="'.$max.'" step="'.$step.'" default="'.$default.'" value="'.$value.'" id="new'.$setting_uc.'" name="new'.$setting_uc.'" '.(canEdit('Control') ? '' : 'disabled="disabled"') .'/></td><td>'.$max.'</td>
</tr> </tr>
'; ';
@ -94,7 +99,7 @@ foreach ($ctls as $line) {
if ($type == '(bool)') { if ($type == '(bool)') {
echo ' echo '
<tr> <tr>
<th scope="row">'.translate($setting_uc).'</th> <th scope="row">'.$label.'</th>
<td></td><td>'.html_radio('new'.$setting_uc, array('0'=>translate('True'), '1', translate('False')), $value, array('disabled'=>'disabled')).' <td></td><td>'.html_radio('new'.$setting_uc, array('0'=>translate('True'), '1', translate('False')), $value, array('disabled'=>'disabled')).'
</td><td></td> </td><td></td>
</tr> </tr>
@ -102,14 +107,14 @@ foreach ($ctls as $line) {
} else if ($type == '(int)') { } else if ($type == '(int)') {
echo ' echo '
<tr> <tr>
<th scope="row">'.translate($setting_uc).'</th> <th scope="row">'.$label.'</th>
<td></td><td><input type="range" '.$ctl[1].' disabled="disabled"/></td><td></td> <td></td><td><input type="range" '.$ctl[1].' disabled="disabled"/></td><td></td>
</tr> </tr>
'; ';
} else { } else {
echo ' echo '
<tr> <tr>
<th scope="row">'.translate($setting_uc).'</th> <th scope="row">'.$label.'</th>
<td></td><td>'.$value.'</td><td></td> <td></td><td>'.$value.'</td><td></td>
</tr> </tr>
'; ';

View File

@ -112,7 +112,7 @@ function dbLog($sql, $update=false) {
function dbError($sql) { function dbError($sql) {
global $dbConn; global $dbConn;
$error = $dbConn->errorInfo(); $error = $dbConn->errorInfo();
if ( !$error[0] ) if (!$error[0])
return ''; return '';
$message = "SQL-ERR '".implode("\n", $dbConn->errorInfo())."', statement was '".$sql."'"; $message = "SQL-ERR '".implode("\n", $dbConn->errorInfo())."', statement was '".$sql."'";
@ -130,17 +130,17 @@ function dbEscape( $string ) {
function dbQuery($sql, $params=NULL, $debug = false) { function dbQuery($sql, $params=NULL, $debug = false) {
global $dbConn; global $dbConn;
if ( dbLog($sql, true) ) if (dbLog($sql, true))
return; return;
$result = NULL; $result = NULL;
try { try {
if ( isset($params) ) { if (isset($params)) {
if ( ! $result = $dbConn->prepare($sql) ) { if (!$result = $dbConn->prepare($sql)) {
ZM\Error("SQL: Error preparing $sql: " . $pdo->errorInfo); ZM\Error("SQL: Error preparing $sql: " . $pdo->errorInfo);
return NULL; return NULL;
} }
if ( ! $result->execute($params) ) { if (!$result->execute($params)) {
ZM\Error("SQL: Error executing $sql: " . print_r($result->errorInfo(), true)); ZM\Error("SQL: Error executing $sql: " . print_r($result->errorInfo(), true));
return NULL; return NULL;
} }

View File

@ -35,12 +35,16 @@ var params =
// Called by bootstrap-table to retrieve zm event data // Called by bootstrap-table to retrieve zm event data
function ajaxRequest(params) { function ajaxRequest(params) {
if ( params.data && params.data.filter ) { if (params.data && params.data.filter) {
params.data.advsearch = params.data.filter; params.data.advsearch = params.data.filter;
delete params.data.filter; delete params.data.filter;
} }
$j.getJSON(thisUrl + '?view=request&request=events&task=query'+filterQuery, params.data) $j.getJSON(thisUrl + '?view=request&request=events&task=query'+filterQuery, params.data)
.done(function(data) { .done(function(data) {
if (data.result == 'Error') {
alert(data.message);
return;
}
var rows = processRows(data.rows); var rows = processRows(data.rows);
// rearrange the result into what bootstrap-table expects // rearrange the result into what bootstrap-table expects
params.success({total: data.total, totalNotFiltered: data.totalNotFiltered, rows: rows}); params.success({total: data.total, totalNotFiltered: data.totalNotFiltered, rows: rows});

View File

@ -461,9 +461,12 @@ switch ( $name ) {
<tr class="Id"> <tr class="Id">
<td class="text-right pr-3"><?php echo translate('Id') ?></td> <td class="text-right pr-3"><?php echo translate('Id') ?></td>
<td><input type="number" step="1" min="1" name="newMonitor[Id]" placeholder="leave blank for auto"/><br/> <td><input type="number" step="1" min="1" name="newMonitor[Id]" placeholder="leave blank for auto"/><br/>
10 Available Ids: <?php
<?php echo implode(', ', array_slice($available_monitor_ids, 0, 10)); ?> if (count($available_monitor_ids)) {
</td> echo 'Some available ids: '.implode(', ', array_slice($available_monitor_ids, 0, 10));
}
?>
</td>
</tr> </tr>
<?php <?php