From 2773737e54cf270926cf42aac2c9dacea975f1ad Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 19 Aug 2020 16:57:20 -0400 Subject: [PATCH 001/230] Use gcc builtin functions for cpuid --- src/zm_utils.cpp | 54 ++++++++++-------------------------------------- 1 file changed, 11 insertions(+), 43 deletions(-) diff --git a/src/zm_utils.cpp b/src/zm_utils.cpp index c96851e79..ecb220021 100644 --- a/src/zm_utils.cpp +++ b/src/zm_utils.cpp @@ -229,63 +229,31 @@ void hwcaps_detect() { neonversion = 0; sse_version = 0; #if (defined(__i386__) || defined(__x86_64__)) - /* x86 or x86-64 processor */ - uint32_t r_edx, r_ecx, r_ebx; + __builtin_cpu_init(); -#ifdef __x86_64__ - __asm__ __volatile__( - "push %%rbx\n\t" - "mov $0x0,%%ecx\n\t" - "mov $0x7,%%eax\n\t" - "cpuid\n\t" - "push %%rbx\n\t" - "mov $0x1,%%eax\n\t" - "cpuid\n\t" - "pop %%rax\n\t" - "pop %%rbx\n\t" - : "=d" (r_edx), "=c" (r_ecx), "=a" (r_ebx) - : - : - ); -#else - __asm__ __volatile__( - "push %%ebx\n\t" - "mov $0x0,%%ecx\n\t" - "mov $0x7,%%eax\n\t" - "cpuid\n\t" - "push %%ebx\n\t" - "mov $0x1,%%eax\n\t" - "cpuid\n\t" - "pop %%eax\n\t" - "pop %%ebx\n\t" - : "=d" (r_edx), "=c" (r_ecx), "=a" (r_ebx) - : - : - ); -#endif - if ( r_ebx & 0x00000020 ) { + if ( __builtin_cpu_supports("avx2") ) { sse_version = 52; /* AVX2 */ Debug(1, "Detected a x86\\x86-64 processor with AVX2"); - } else if ( r_ecx & 0x10000000 ) { + } else if ( __builtin_cpu_supports("avx") ) { sse_version = 51; /* AVX */ Debug(1, "Detected a x86\\x86-64 processor with AVX"); - } else if ( r_ecx & 0x00100000 ) { + } else if ( __builtin_cpu_supports("sse4.2") ) { sse_version = 42; /* SSE4.2 */ Debug(1, "Detected a x86\\x86-64 processor with SSE4.2"); - } else if ( r_ecx & 0x00080000 ) { + } else if ( __builtin_cpu_supports("sse4.1") ) { sse_version = 41; /* SSE4.1 */ Debug(1, "Detected a x86\\x86-64 processor with SSE4.1"); - } else if ( r_ecx & 0x00000200 ) { + } else if ( __builtin_cpu_supports("ssse3") ) { sse_version = 35; /* SSSE3 */ Debug(1,"Detected a x86\\x86-64 processor with SSSE3"); - } else if ( r_ecx & 0x00000001 ) { + } else if ( __builtin_cpu_supports("sse3") ) { sse_version = 30; /* SSE3 */ Debug(1, "Detected a x86\\x86-64 processor with SSE3"); - } else if ( r_edx & 0x04000000 ) { + } else if ( __builtin_cpu_supports("sse2") ) { sse_version = 20; /* SSE2 */ Debug(1, "Detected a x86\\x86-64 processor with SSE2"); - } else if ( r_edx & 0x02000000 ) { + } else if ( __builtin_cpu_supports("sse") ) { sse_version = 10; /* SSE */ Debug(1, "Detected a x86\\x86-64 processor with SSE"); } else { @@ -320,7 +288,7 @@ __attribute__((noinline,__target__("sse2"))) #endif void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - if ( bytes > 128 ) { + if(bytes > 128) { unsigned int remainder = bytes % 128; const uint8_t* lastsrc = (uint8_t*)src + (bytes - remainder); @@ -362,7 +330,7 @@ void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes) { } #else /* Non x86\x86-64 platform, use memcpy */ - memcpy(dest, src, bytes); + memcpy(dest,src,bytes); #endif return dest; } From df18359f612bd9d631381e056e14f7dea046599f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 15 Sep 2020 11:12:20 -0400 Subject: [PATCH 002/230] query_string to querystring --- web/skins/classic/views/events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index a1c78b31b..7542061a5 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -97,7 +97,7 @@ if ( !empty($page) ) { } $maxShortcuts = 5; -$pagination = getPagination($pages, $page, $maxShortcuts, $filter->query_string().$sortQuery.$limitQuery); +$pagination = getPagination($pages, $page, $maxShortcuts, $filter->querystring().$sortQuery.$limitQuery); $focusWindow = true; From 624bcdcde0a5d827362567d0af63d7c541c7e7d6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 24 Sep 2020 09:01:30 -0400 Subject: [PATCH 003/230] Add Latitude and Longitude to Monitors and monitor edit as well as using the geolocation api to auto-populate them --- db/zm_create.sql.in | 2 ++ db/zm_update-1.31.30.sql | 20 ++++++++++++++++++++ db/zm_update-1.35.7.sql | 23 +++++++++++++++++++++++ web/includes/Monitor.php | 2 ++ web/skins/classic/views/js/monitor.js | 14 ++++++++++++++ web/skins/classic/views/monitor.php | 20 ++++++++++++++++++++ 6 files changed, 81 insertions(+) create mode 100644 db/zm_update-1.31.30.sql create mode 100644 db/zm_update-1.35.7.sql diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index af6a17182..cd4622df1 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -536,6 +536,8 @@ CREATE TABLE `Monitors` ( `ArchivedEventDiskSpace` bigint default NULL, `ZoneCount` TINYINT NOT NULL DEFAULT 0, `Refresh` int(10) unsigned default NULL, + `Latitude` DECIMAL(10,8), + `Longitude` DECIMAL(10,8), PRIMARY KEY (`Id`) ) ENGINE=@ZM_MYSQL_ENGINE@; diff --git a/db/zm_update-1.31.30.sql b/db/zm_update-1.31.30.sql new file mode 100644 index 000000000..c87b4409a --- /dev/null +++ b/db/zm_update-1.31.30.sql @@ -0,0 +1,20 @@ +DROP TABLE IF EXISTS `Monitor_Status`; +CREATE TABLE `Monitor_Status` ( + `MonitorId` int(10) unsigned NOT NULL, + `Status` enum('Unknown','NotRunning','Running','Connected','Signal') NOT NULL default 'Unknown', + `CaptureFPS` DECIMAL(10,2) NOT NULL default 0, + `AnalysisFPS` DECIMAL(5,2) NOT NULL default 0, + PRIMARY KEY (`MonitorId`) +) ENGINE=MEMORY; + +SET SESSION sql_mode='NO_AUTO_VALUE_ON_ZERO'; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM Storage WHERE Name = 'Default' AND Id=0 AND Path='/var/cache/zoneminder/events' + ) > 0, + "SELECT 'Default Storage Area already exists.'", + "INSERT INTO Storage (Id,Name,Path,Scheme,ServerId) VALUES (0,'Default','/var/cache/zoneminder/events','Medium',NULL)" + )); + +PREPARE stmt FROM @s; +EXECUTE stmt; diff --git a/db/zm_update-1.35.7.sql b/db/zm_update-1.35.7.sql new file mode 100644 index 000000000..84c3dbb1e --- /dev/null +++ b/db/zm_update-1.35.7.sql @@ -0,0 +1,23 @@ +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'Latitude' + ) > 0, +"SELECT 'Column Latitude already exists in Monitors'", +"ALTER TABLE `Monitors` ADD `Latitude` DECIMAL(10,8) AFTER `Refresh`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'Longitude' + ) > 0, +"SELECT 'Column Longitude already exists in Monitors'", +"ALTER TABLE `Monitors` ADD `Longitude` DECIMAL(10,8) AFTER `Latitude`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index 65d1fc3ed..d1bd51509 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -129,6 +129,8 @@ class Monitor extends ZM_Object { 'Refresh' => null, 'DefaultCodec' => 'auto', 'GroupIds' => array('default'=>array(), 'do_not_update'=>1), + 'Latitude' => null, + 'Longitude' => null, ); private $status_fields = array( 'Status' => null, diff --git a/web/skins/classic/views/js/monitor.js b/web/skins/classic/views/js/monitor.js index 0bedf5303..20020dc35 100644 --- a/web/skins/classic/views/js/monitor.js +++ b/web/skins/classic/views/js/monitor.js @@ -241,5 +241,19 @@ function update_estimated_ram_use() { document.getElementById('estimated_ram_use').innerHTML = human_filesize(buffer_count * width * height * colours, 0); } +function updateLatitudeAndLongitude(latitude,longitude) { + var form = document.getElementById('contentForm'); + form.elements['newMonitor[Latitude]'].value = latitude; + form.elements['newMonitor[Longitude]'].value = longitude; +} +function getLocation() { + if('geolocation' in navigator) { + navigator.geolocation.getCurrentPosition((position) => { + updateLatitudeAndLongitude(position.coords.latitude, position.coords.longitude); + }); + } else { + console.log("Geolocation not available"); + } +} window.addEventListener('DOMContentLoaded', initPage); diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index e48d12277..1d4e2d713 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -404,6 +404,7 @@ if ( $monitor->Type() != 'WebSite' ) { if ( ZM_OPT_X10 ) $tabs['x10'] = translate('X10'); $tabs['misc'] = translate('Misc'); + $tabs['location'] = translate('Location'); } if ( isset($_REQUEST['tab']) ) @@ -1151,6 +1152,25 @@ echo htmlSelect('newMonitor[ReturnLocation]', $return_options, $monitor->ReturnL + + + + + + + + + + + + + + From aa875b019df968b47e0f4bbbcd131148c5cccbe4 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 24 Sep 2020 09:02:20 -0400 Subject: [PATCH 004/230] remove auto-generated update file that slipped in --- db/zm_update-1.31.30.sql | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 db/zm_update-1.31.30.sql diff --git a/db/zm_update-1.31.30.sql b/db/zm_update-1.31.30.sql deleted file mode 100644 index c87b4409a..000000000 --- a/db/zm_update-1.31.30.sql +++ /dev/null @@ -1,20 +0,0 @@ -DROP TABLE IF EXISTS `Monitor_Status`; -CREATE TABLE `Monitor_Status` ( - `MonitorId` int(10) unsigned NOT NULL, - `Status` enum('Unknown','NotRunning','Running','Connected','Signal') NOT NULL default 'Unknown', - `CaptureFPS` DECIMAL(10,2) NOT NULL default 0, - `AnalysisFPS` DECIMAL(5,2) NOT NULL default 0, - PRIMARY KEY (`MonitorId`) -) ENGINE=MEMORY; - -SET SESSION sql_mode='NO_AUTO_VALUE_ON_ZERO'; - -SET @s = (SELECT IF( - (SELECT COUNT(*) FROM Storage WHERE Name = 'Default' AND Id=0 AND Path='/var/cache/zoneminder/events' - ) > 0, - "SELECT 'Default Storage Area already exists.'", - "INSERT INTO Storage (Id,Name,Path,Scheme,ServerId) VALUES (0,'Default','/var/cache/zoneminder/events','Medium',NULL)" - )); - -PREPARE stmt FROM @s; -EXECUTE stmt; From 9c7bbd4aa7a53b00829b789ae64f1ad3150d7894 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 24 Sep 2020 09:13:25 -0400 Subject: [PATCH 005/230] introduce output_script_if_exists, use it to link leaflet.js if it exists --- web/skins/classic/includes/functions.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 203d3ffc2..8da07b025 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -50,12 +50,24 @@ function xhtmlHeaders($file, $title) { $html[] = ''; // So we ge a trailing \n return implode(PHP_EOL, $html); } + function output_script_if_exists($files) { + global $skin; + $html = array(); + foreach ( $files as $file ) { + $html[] = ''; + } + $html[] = ''; // So we ge a trailing \n + return implode(PHP_EOL, $html); + } function output_cache_busted_stylesheet_links($files) { $html = array(); foreach ( $files as $file ) { $html[] = ''; } + if ( ! count($html) ) { + ZM\Warning("No files found for $files"); + } $html[] = ''; // So we ge a trailing \n return implode(PHP_EOL, $html); } @@ -109,6 +121,8 @@ if ( $css != 'base' ) echo output_link_if_exists(array('/css/base/views/control.css')); if ( $css != 'base' ) echo output_link_if_exists(array('/css/'.$css.'/views/control.css')); + } else if ( $basename == 'monitor' ) { + echo output_link_if_exists(array('/js/leaflet/leaflet.css')); } ?> - - -

'.translate('ZoneMinderLog').'

-

'.htmlspecialchars(preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG)).'

-

'.count($logs).' '.translate('Logs').'

- - - - '); - foreach ( $logs as $log ) { - $classLevel = $log['Level']; - if ( $classLevel < ZM\Logger::FATAL ) { - $classLevel = ZM\Logger::FATAL; - } else if ( $classLevel > ZM\Logger::DEBUG ) { - $classLevel = ZM\Logger::DEBUG; - } - $logClass = 'log-'.strtolower(ZM\Logger::$codes[$classLevel]); - fprintf($exportFP, ' - ', $logClass, $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line']); - } - fwrite($exportFP, - ' -
'.translate('DateTime').''.translate('Component').''.translate('Server').''.translate('Pid').''.translate('Level').''.translate('Message').''.translate('File').''.translate('Line').'
%s%s%s%d%s%s%s%s
- - '); - break; - } - case 'xml' : - { - fwrite($exportFP, - ' - - '.$_POST['selector'].''); - foreach ( $filter as $field=>$value ) - if ( $value != '' ) - fwrite( $exportFP, - ' - <'.strtolower($field).'>'.htmlspecialchars($value).' - ' ); - fwrite( $exportFP, - ' - - '.translate('DateTime').' - '.translate('Component').' - '.translate('Server').' - '.translate('Pid').' - '.translate('Level').' - '.translate('Message').' - '.translate('File').' - '.translate('Line').' - - - ' ); - foreach ( $logs as $log ) { - fprintf( $exportFP, - ' - %s - %s - %s - %d - %s - - %s - %d - -', $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], utf8_decode( $log['Message'] ), $log['File'], $log['Line'] ); - } - fwrite( $exportFP, - ' - ' ); - break; - } - $exportExt = 'xml'; - break; - } - fclose( $exportFP ); - ajaxResponse( array( - 'key' => $exportKey, - 'format' => $format, - ) ); - break; - } - case 'download' : - { - if ( !canView('System') ) - ajaxError('Insufficient permissions to download logs'); - - if ( empty($_REQUEST['key']) ) - ZM\Fatal('No log export key given'); - $exportKey = $_REQUEST['key']; - if ( empty($_REQUEST['format']) ) - ZM\Fatal('No log export format given'); - $format = $_REQUEST['format']; - - switch ( $format ) { - case 'text' : - $exportExt = 'txt'; - break; - case 'tsv' : - $exportExt = 'tsv'; - break; - case 'html' : - $exportExt = 'html'; - break; - case 'xml' : - $exportExt = 'xml'; - break; - default : - ZM\Fatal("Unrecognised log export format '$format'"); - } - - $exportFile = 'zm-log.'.$exportExt; - $exportPath = ZM_DIR_EXPORTS.'/zm-log-'.$exportKey.$exportExt; - - header('Pragma: public'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Cache-Control: private', false); // required by certain browsers - header('Content-Description: File Transfer'); - header('Content-Disposition: attachment; filename="'.$exportFile.'"'); - header('Content-Transfer-Encoding: binary'); - header('Content-Type: application/force-download'); - header('Content-Length: '.filesize($exportPath)); - readfile($exportPath); - exit(0); - break; - } -} // end switch ( $_REQUEST['task'] ) -ajaxError('Unrecognised action or insufficient permissions'); -?> diff --git a/web/ajax/newlog.php b/web/ajax/newlog.php deleted file mode 100644 index 9e6bd9585..000000000 --- a/web/ajax/newlog.php +++ /dev/null @@ -1,132 +0,0 @@ - "search text" pairs -// Bootstrap table sends json_ecoded array, which we must decode -$advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array(); - -// Sort specifies the name of the column to sort on -$sort = 'TimeKey'; -if ( isset($_REQUEST['sort']) ) { - if ( !in_array($_REQUEST['sort'], array_merge($columns, $col_alt)) ) { - ZM\Error('Invalid sort field: ' . $_REQUEST['sort']); - } else { - $sort = $_REQUEST['sort']; - if ( $sort == 'DateTime' ) $sort = 'TimeKey'; - } -} - -// Offset specifies the starting row to return, used for pagination -$offset = 0; -if ( isset($_REQUEST['offset']) ) { - if ( ( !is_int($_REQUEST['offset']) and !ctype_digit($_REQUEST['offset']) ) ) { - ZM\Error('Invalid value for offset: ' . $_REQUEST['offset']); - } else { - $offset = $_REQUEST['offset']; - } -} - -// Order specifies the sort direction, either asc or desc -$order = (isset($_REQUEST['order']) and (strtolower($_REQUEST['order']) == 'asc')) ? 'ASC' : 'DESC'; - -// Limit specifies the number of rows to return -$limit = 100; -if ( isset($_REQUEST['limit']) ) { - if ( ( !is_int($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) { - ZM\Error('Invalid value for limit: ' . $_REQUEST['limit']); - } else { - $limit = $_REQUEST['limit']; - } -} - -$col_str = implode(', ', $columns); -$data = array(); -$query = array(); -$query['values'] = array(); -$likes = array(); -$where = ''; -// 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 -// Alternatively we could try to do both -if ( count($advsearch) ) { - - foreach ( $advsearch as $col=>$text ) { - if ( !in_array($col, array_merge($columns, $col_alt)) ) { - ZM\Error("'$col' is not a sortable column name"); - continue; - } - $text = '%' .$text. '%'; - array_push($likes, $col.' LIKE ?'); - array_push($query['values'], $text); - } - $wherevalues = $query['values']; - $where = ' WHERE (' .implode(' OR ', $likes). ')'; - -} else if ( $search != '' ) { - - $search = '%' .$search. '%'; - foreach ( $columns as $col ) { - array_push($likes, $col.' LIKE ?'); - array_push($query['values'], $search); - } - $wherevalues = $query['values']; - $where = ' WHERE (' .implode(' OR ', $likes). ')'; -} - -$query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; -array_push($query['values'], $offset, $limit); - -//ZM\Warning('Calling the following sql query: ' .$query['sql']); - -$data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total'); -if ( $search != '' || count($advsearch) ) { - $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues); -} else { - $data['total'] = $data['totalNotFiltered']; -} - -if ( !$Servers ) - $Servers = ZM\Server::find(); -$servers_by_Id = array(); -# There is probably a better way to do this. -foreach ( $Servers as $server ) { - $servers_by_Id[$server->Id()] = $server; -} - -$rows = array(); -foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { - $row['DateTime'] = strftime('%Y-%m-%d %H:%M:%S', intval($row['TimeKey'])); - $row['Server'] = ( $row['ServerId'] and isset($servers_by_Id[$row['ServerId']]) ) ? $servers_by_Id[$row['ServerId']]->Name() : ''; - // First strip out any html tags - // Second strip out all characters that are not ASCII 32-126 (yes, 126) - $row['Message'] = preg_replace('/[^\x20-\x7E]/', '', strip_tags($row['Message'])); - $rows[] = $row; -} -$data['rows'] = $rows; -$data['logstate'] = logState(); -$data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG); - -ajaxResponse($data); - diff --git a/web/skins/classic/views/js/log.js b/web/skins/classic/views/js/log.js index ddaabcfc8..cd645e244 100644 --- a/web/skins/classic/views/js/log.js +++ b/web/skins/classic/views/js/log.js @@ -27,7 +27,7 @@ var params = // Called by bootstrap-table to retrieve zm log data function ajaxRequest(params) { - $j.getJSON(thisUrl + '?view=request&request=newlog&task=query', params.data) + $j.getJSON(thisUrl + '?view=request&request=log&task=query', params.data) .done(function(data) { //console.log('Ajax parameters: ' + JSON.stringify(params)); // rearrange the result into what bootstrap-table expects From 6f45de04f82fd37c1cd88a39916da4c2e8cfda91 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 19 Oct 2020 07:50:11 -0500 Subject: [PATCH 220/230] partial roughin ajax event view server side pagination --- web/ajax/events.php | 219 +++++++++++++++++++++++---- web/skins/classic/views/js/events.js | 26 ++-- 2 files changed, 202 insertions(+), 43 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 16c777ebf..c54fddd06 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -1,41 +1,200 @@ "search text" pairs +// Bootstrap table sends json_ecoded array, which we must decode +$advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array(); + +// Sort specifies the name of the column to sort on +$sort = 'AttrStartTime'; +if ( isset($_REQUEST['sort']) ) { + if ( !in_array($_REQUEST['sort'], array_merge($columns, $col_alt)) ) { + ZM\Error('Invalid sort field: ' . $_REQUEST['sort']); + } else { + $sort = $_REQUEST['sort']; + //if ( $sort == 'DateTime' ) $sort = 'TimeKey'; + } +} + +// Offset specifies the starting row to return, used for pagination +$offset = 0; +if ( isset($_REQUEST['offset']) ) { + if ( ( !is_int($_REQUEST['offset']) and !ctype_digit($_REQUEST['offset']) ) ) { + ZM\Error('Invalid value for offset: ' . $_REQUEST['offset']); + } else { + $offset = $_REQUEST['offset']; + } +} + +// Order specifies the sort direction, either asc or desc +$order = (isset($_REQUEST['order']) and (strtolower($_REQUEST['order']) == 'asc')) ? 'ASC' : 'DESC'; + +// Limit specifies the number of rows to return +$limit = 100; +if ( isset($_REQUEST['limit']) ) { + if ( ( !is_int($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) { + ZM\Error('Invalid value for limit: ' . $_REQUEST['limit']); + } else { + $limit = $_REQUEST['limit']; + } +} + +// +// MAIN LOOP +// + +switch ( $task ) { + case 'archive' : + case 'unarchive' : + foreach ( $eids as $eid ) archiveRequest($task, $eid); + break; + case 'delete' : + foreach ( $eids as $eid ) $data[] = deleteRequest($eid); + break; + case 'query' : + $data = queryRequest($search, $advsearch, $sort, $offset, $order, $limit); + break; + default : + ZM\Fatal("Unrecognised task '$task'"); +} // end switch task + +ajaxResponse($data); + +// +// FUNCTION DEFINITIONS +// + +function archiveRequest($task, $eid) { + $archiveVal = ($task == 'archive') ? 1 : 0; + dbQuery( + 'UPDATE Events SET Archived = ? WHERE Id = ?', + array($archiveVal, $eid) + ); +} + +function deleteRequest($eid) { $message = array(); + $event = new ZM\Event($eid); + if ( !$event->Id() ) { + $message[] = array($eid=>'Event not found.'); + } else if ( $event->Archived() ) { + $message[] = array($eid=>'Event is archived, cannot delete it.'); + } else { + $event->delete(); + } + + return $message; +} - foreach ( $_REQUEST['eids'] as $eid ) { +function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { + // Put server pagination code here + // The table we want our data from + $table = 'Events'; - switch ( $_REQUEST['action'] ) { - case 'archive' : - case 'unarchive' : - $archiveVal = ($_REQUEST['action'] == 'archive') ? 1 : 0; - dbQuery( - 'UPDATE Events SET Archived = ? WHERE Id = ?', - array($archiveVal, $eid) - ); - break; - case 'delete' : - $event = new ZM\Event($eid); - if ( !$event->Id() ) { - $message[] = array($eid=>'Event not found.'); - } else if ( $event->Archived() ) { - $message[] = array($eid=>'Event is archived, cannot delete it.'); - } else { - $event->delete(); + // The names of the dB columns in the log table we are interested in + $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'DiskSpace'); + + // The names of columns shown in the log view that are NOT dB columns in the database + $col_alt = array('Monitor', 'Storage'); + + $col_str = implode(', ', $columns); + $data = array(); + $query = array(); + $query['values'] = array(); + $likes = array(); + $where = ''; + // 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 + // Alternatively we could try to do both + if ( count($advsearch) ) { + + foreach ( $advsearch as $col=>$text ) { + if ( !in_array($col, array_merge($columns, $col_alt)) ) { + ZM\Error("'$col' is not a sortable column name"); + continue; } - break; - } // end switch action - } // end foreach - ajaxResponse($message); -} // end if canEdit('Events') + $text = '%' .$text. '%'; + array_push($likes, $col.' LIKE ?'); + array_push($query['values'], $text); + } + $wherevalues = $query['values']; + $where = ' WHERE (' .implode(' OR ', $likes). ')'; -ajaxError('Unrecognised action '.$_REQUEST['action'].' or insufficient permissions for user '.$user['Username']); + } else if ( $search != '' ) { + + $search = '%' .$search. '%'; + foreach ( $columns as $col ) { + array_push($likes, $col.' LIKE ?'); + array_push($query['values'], $search); + } + $wherevalues = $query['values']; + $where = ' WHERE (' .implode(' OR ', $likes). ')'; + } + + $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; + array_push($query['values'], $offset, $limit); + + //ZM\Warning('Calling the following sql query: ' .$query['sql']); + + $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total'); + if ( $search != '' || count($advsearch) ) { + $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues); + } else { + $data['total'] = $data['totalNotFiltered']; + } + + $storage_areas = ZM\Storage::find(); + $StorageById = array(); + foreach ( $storage_areas as $S ) { + $StorageById[$S->Id()] = $S; + } + + $monitor_names = ZM\Monitor::find(); + $MonitorById = array(); + foreach ( $monitor_names as $S ) { + $MonitorById[$S->Id()] = $S; + } + + $rows = array(); + foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { + // Modify the row data as needed + $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); + $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); + $row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : ''; + $row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : ''; + $rows[] = $row; + } + $data['rows'] = $rows; + $data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG); + + return $data; +} ?> diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 3710f7e80..015d41a01 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -1,3 +1,13 @@ +var backBtn = $j('#backBtn'); +var viewBtn = $j('#viewBtn'); +var archiveBtn = $j('#archiveBtn'); +var unarchiveBtn = $j('#unarchiveBtn'); +var editBtn = $j('#editBtn'); +var exportBtn = $j('#exportBtn'); +var downloadBtn = $j('#downloadBtn'); +var deleteBtn = $j('#deleteBtn'); +var table = $j('#eventTable'); + function thumbnail_onmouseover(event) { var img = event.target; img.src = ''; @@ -56,7 +66,7 @@ function manageDelConfirmModalBtns() { var selections = getIdSelections(); evt.preventDefault(); - $j.getJSON(thisUrl + '?request=events&action=delete&eids[]='+selections.join('&eids[]=')) + $j.getJSON(thisUrl + '?request=events&task=delete&eids[]='+selections.join('&eids[]=')) .done( function(data) { $j('#eventTable').bootstrapTable('refresh'); window.location.reload(true); @@ -85,16 +95,6 @@ function getEventDetailModal(eid) { } function initPage() { - var backBtn = $j('#backBtn'); - var viewBtn = $j('#viewBtn'); - var archiveBtn = $j('#archiveBtn'); - var unarchiveBtn = $j('#unarchiveBtn'); - var editBtn = $j('#editBtn'); - var exportBtn = $j('#exportBtn'); - var downloadBtn = $j('#downloadBtn'); - var deleteBtn = $j('#deleteBtn'); - var table = $j('#eventTable'); - // Load the delete confirmation modal into the DOM getDelConfirmModal(); @@ -169,7 +169,7 @@ function initPage() { var selections = getIdSelections(); evt.preventDefault(); - $j.getJSON(thisUrl + '?request=events&action=archive&eids[]='+selections.join('&eids[]=')) + $j.getJSON(thisUrl + '?request=events&task=archive&eids[]='+selections.join('&eids[]=')) .done( function(data) { $j('#eventTable').bootstrapTable('refresh'); window.location.reload(true); @@ -188,7 +188,7 @@ function initPage() { console.log(selections); evt.preventDefault(); - $j.getJSON(thisUrl + '?request=events&action=unarchive&eids[]='+selections.join('&eids[]=')) + $j.getJSON(thisUrl + '?request=events&task=unarchive&eids[]='+selections.join('&eids[]=')) .done( function(data) { $j('#eventTable').bootstrapTable('refresh'); window.location.reload(true); From 14894dfb0053f579802441c8e45cf1fa3cc09ff7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 19 Oct 2020 09:08:25 -0400 Subject: [PATCH 221/230] remove extra comma --- web/skins/classic/views/event.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index cb683adb8..b9c2d8f38 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -209,7 +209,7 @@ if ( ($codec == 'MP4' || $codec == 'auto' ) && $Event->DefaultVideo() ) { array_map(function($r){return $r/100;}, array_filter( array_keys($rates), - function($r){return $r >= 0 ? true : false;}, + function($r){return $r >= 0 ? true : false;} ))) ?>], "plugins": { "zoomrotate": { "zoom": ""}}}' > From 7ae7e05f14d283872ee5cda0ce1c5d0479aa7091 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 19 Oct 2020 09:29:39 -0500 Subject: [PATCH 222/230] roughin ajax call in event.js for server side pagination --- web/skins/classic/views/js/events.js | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 015d41a01..848ba23c3 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -8,6 +8,49 @@ var downloadBtn = $j('#downloadBtn'); var deleteBtn = $j('#deleteBtn'); var table = $j('#eventTable'); +/* +This is the format of the json object sent by bootstrap-table + +var params = +{ +"type":"get", +"data": + { + "search":"some search text", + "sort":"StartTime", + "order":"asc", + "offset":0, + "limit":25 + "filter": + { + "Name":"some advanced search text" + "StartTime":"some more advanced search text" + } + }, +"cache":true, +"contentType":"application/json", +"dataType":"json" +}; +*/ + +// Called by bootstrap-table to retrieve zm event data +function ajaxRequest(params) { + $j.getJSON(thisUrl + '?view=request&request=events&task=query', params.data) + .done(function(data) { + //console.log('Ajax parameters: ' + JSON.stringify(params)); + // rearrange the result into what bootstrap-table expects + var rows = processRows(data.rows); + params.success({total: data.total, totalNotFiltered: data.totalNotFiltered, rows: rows}); + }) + .fail(logAjaxFail); +} + +function processRows(rows) { + // TO-DO: Inject desired html for the cells in each row + + return rows; +} + function thumbnail_onmouseover(event) { var img = event.target; img.src = ''; From 89f298771fb3689ee0167f2d011f38b18c9bd362 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 19 Oct 2020 12:25:13 -0500 Subject: [PATCH 223/230] server pagination backend improvements --- web/ajax/events.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index c54fddd06..702d85a1f 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -34,7 +34,7 @@ $search = isset($_REQUEST['search']) ? $_REQUEST['search'] : ''; $advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array(); // Sort specifies the name of the column to sort on -$sort = 'AttrStartTime'; +$sort = 'StartTime'; if ( isset($_REQUEST['sort']) ) { if ( !in_array($_REQUEST['sort'], array_merge($columns, $col_alt)) ) { ZM\Error('Invalid sort field: ' . $_REQUEST['sort']); @@ -120,7 +120,7 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $table = 'Events'; // The names of the dB columns in the log table we are interested in - $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'DiskSpace'); + $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'DiskSpace'); // The names of columns shown in the log view that are NOT dB columns in the database $col_alt = array('Monitor', 'Storage'); @@ -186,10 +186,14 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $rows = array(); foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { // Modify the row data as needed + $row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : ''; + $row['Archived'] = $row['Archived'] ? 'Yes' : 'No'; + $row['Emailed'] = $row['Emailed'] ? 'Yes' : 'No'; $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); - $row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : ''; - $row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : ''; + $row['Length'] = gmdate('H:i:s', $row['Length'] ); + $row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : 'Default'; + $row['DiskSpace'] = human_filesize($row['DiskSpace']); $rows[] = $row; } $data['rows'] = $rows; From 4e391708f1f5d0e1098fd57960b5e92958261087 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 19 Oct 2020 14:18:21 -0500 Subject: [PATCH 224/230] event view server pagination WIP --- web/ajax/events.php | 6 ++++-- web/skins/classic/views/js/events.js | 13 ++++++++++++- web/skins/classic/views/js/events.js.php | 4 ++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 702d85a1f..ab2ff6a44 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -186,9 +186,11 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $rows = array(); foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { // Modify the row data as needed + $row['Name'] = validHtmlStr($row['Name']); + $row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No'); + $row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No'); $row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : ''; - $row['Archived'] = $row['Archived'] ? 'Yes' : 'No'; - $row['Emailed'] = $row['Emailed'] ? 'Yes' : 'No'; + $row['Cause'] = validHtmlStr($row['Cause']); $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); $row['Length'] = gmdate('H:i:s', $row['Length'] ); diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 848ba23c3..2c2ce3d17 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -46,7 +46,18 @@ function ajaxRequest(params) { } function processRows(rows) { - // TO-DO: Inject desired html for the cells in each row + // WIP: Inject desired html and formatting for the cells in each row + $j.each(rows, function(ndx, row) { + var eid = row.Id; + var mid = row.MonitorId; + var archived = row.Archived == yesString ? archivedString : ''; + var emailed = row.Emailed == yesString ? emailedString : ''; + + row.Id = '' + eid + ''; + row.Name = '' + row.Name + '' + + '
' + archived + emailed + '
'; + row.Monitor = '' + row.Monitor + ''; + }); return rows; } diff --git a/web/skins/classic/views/js/events.js.php b/web/skins/classic/views/js/events.js.php index 3a60a97ba..48f405dd7 100644 --- a/web/skins/classic/views/js/events.js.php +++ b/web/skins/classic/views/js/events.js.php @@ -7,3 +7,7 @@ var filterQuery = ''; var confirmDeleteEventsString = ""; +var archivedString = ""; +var emailedString = ""; +var yesString = ""; +var noString = ""; From bfa45b0c431adc623d80c217e732b1666cb5bb48 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 20 Oct 2020 08:10:43 -0500 Subject: [PATCH 225/230] continue work on event view server pagination --- web/ajax/events.php | 3 ++- web/skins/classic/views/js/events.js | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index ab2ff6a44..e241067ad 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -120,7 +120,7 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $table = 'Events'; // The names of the dB columns in the log table we are interested in - $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'DiskSpace'); + $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'Notes', 'DiskSpace'); // The names of columns shown in the log view that are NOT dB columns in the database $col_alt = array('Monitor', 'Storage'); @@ -195,6 +195,7 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); $row['Length'] = gmdate('H:i:s', $row['Length'] ); $row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : 'Default'; + $row['Notes'] = htmlspecialchars($row['Notes']); $row['DiskSpace'] = human_filesize($row['DiskSpace']); $rows[] = $row; } diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 2c2ce3d17..b24f65e5f 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -47,6 +47,7 @@ function ajaxRequest(params) { function processRows(rows) { // WIP: Inject desired html and formatting for the cells in each row + // REMINDER: Make these lines dependent on user permissions e.g. canEditEvents $j.each(rows, function(ndx, row) { var eid = row.Id; var mid = row.MonitorId; @@ -57,6 +58,15 @@ function processRows(rows) { row.Name = '' + row.Name + '' + '
' + archived + emailed + '
'; row.Monitor = '' + row.Monitor + ''; + row.Cause = '' + row.Cause + ''; + if ( row.Notes.indexOf('detected:') >= 0 ) { + row.Cause = row.Cause + '
' + row.Notes + '
'; + } else if ( row.Notes != 'Forced Web: ' ) { + row.Cause = row.Cause + '
' + row.Notes + '
'; + } + row.Frames = '' + row.Frames + ''; + row.AlarmFrames = '' + row.AlarmFrames + ''; + row.MaxScore = '' + row.MaxScore + ''; }); return rows; @@ -316,6 +326,16 @@ function initPage() { getEventDetailModal(eid); }); + // Update table links each time after new data is loaded + table.on('post-body.bs.table', function(data) { + // Manage the eventdetail links in the events list + $j(".eDetailLink").click(function(evt) { + evt.preventDefault(); + var eid = $j(this).data('eid'); + getEventDetailModal(eid); + }); + }); + // The table is initially given a hidden style, so now that we are done rendering, show it table.show(); } From 1a779585486bd05e09a39a1bd2dc8c4ed0524e20 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 20 Oct 2020 11:52:18 -0400 Subject: [PATCH 226/230] Make loading the function modal happen on click instead of every page load. --- web/skins/classic/views/js/console.js | 91 ++++++++++++++------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/web/skins/classic/views/js/console.js b/web/skins/classic/views/js/console.js index 7e5e43840..52b7aedc2 100644 --- a/web/skins/classic/views/js/console.js +++ b/web/skins/classic/views/js/console.js @@ -128,45 +128,55 @@ function reloadWindow() { } // Manage the the Function modal and its buttons -function manageFunctionModal() { - $j('.functionLnk').click(function(evt) { - evt.preventDefault(); - if ( !canEditEvents ) { - enoperm(); - return; - } - var mid = evt.currentTarget.getAttribute('data-mid'); - monitor = monitors[mid]; - if ( !monitor ) { - console.error("No monitor found for mid " + mid); - return; - } +function manageFunctionModal(evt) { + evt.preventDefault(); - var function_form = document.getElementById('function_form'); - if ( !function_form ) { - console.error("Unable to find form with id function_form"); - return; - } - function_form.elements['newFunction'].value = monitor.Function; - function_form.elements['newEnabled'].checked = monitor.Enabled == '1'; - function_form.elements['mid'].value = mid; - document.getElementById('function_monitor_name').innerHTML = monitor.Name; + if ( !canEditEvents ) { + enoperm(); + return; + } - $j('#modalFunction').modal('show'); - }); + if ( ! $j('#modalFunction').length ) { + // Load the Function modal on page load + $j.getJSON(thisUrl + '?request=modal&modal=function') + .done(function(data) { + insertModalHtml('modalFunction', data.html); + // Manage the CANCEL modal buttons + $j('.funcCancelBtn').click(function(evt) { + evt.preventDefault(); + $j('#modalFunction').modal('hide'); + }); + // Manage the SAVE modal buttons + $j('.funcSaveBtn').click(function(evt) { + evt.preventDefault(); + $j('#function_form').submit(); + }); - // Manage the CANCEL modal buttons - $j('.funcCancelBtn').click(function(evt) { - evt.preventDefault(); - $j('#modalFunction').modal('hide'); - }); + manageFunctionModal(evt); + }) + .fail(logAjaxFail); + return; + } - // Manage the SAVE modal buttons - $j('.funcSaveBtn').click(function(evt) { - evt.preventDefault(); - $j('#function_form').submit(); - }); -} + var mid = evt.currentTarget.getAttribute('data-mid'); + monitor = monitors[mid]; + if ( !monitor ) { + console.error("No monitor found for mid " + mid); + return; + } + + var function_form = document.getElementById('function_form'); + if ( !function_form ) { + console.error("Unable to find form with id function_form"); + return; + } + function_form.elements['newFunction'].value = monitor.Function; + function_form.elements['newEnabled'].checked = monitor.Enabled == '1'; + function_form.elements['mid'].value = mid; + document.getElementById('function_monitor_name').innerHTML = monitor.Name; + + $j('#modalFunction').modal('show'); +} // end function manageFunctionModal function initPage() { reloadWindow.periodical(consoleRefreshTimeout); @@ -196,15 +206,8 @@ function initPage() { // Setup the thumbnail video animation initThumbAnimation(); - // Load the Function modal on page load - $j.getJSON(thisUrl + '?request=modal&modal=function') - .done(function(data) { - insertModalHtml('modalFunction', data.html); - // Manage the Function modal - manageFunctionModal(); - }) - .fail(logAjaxFail); -} + $j('.functionLnk').click(manageFunctionModal); +} // end function initPage function applySort(event, ui) { var monitor_ids = $j(this).sortable('toArray'); From bb5646baace75536cc25ecac9242c3e9b275df09 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 20 Oct 2020 12:31:06 -0400 Subject: [PATCH 227/230] Load Logout modal content on click instead of every page load --- web/skins/classic/js/skin.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index 595da9788..b33d1bb7d 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -240,7 +240,7 @@ if ( currentView != 'none' && currentView != 'login' ) { $j(document).ready(function() { // Load the Logout and State modals into the dom - $j('#logoutButton').click(getLogoutModal()); + $j('#logoutButton').click(clickLogout); if ( canEditSystem ) $j('#stateModalBtn').click(getStateModal); // Trigger autorefresh of the widget bar stats on the navbar @@ -665,9 +665,18 @@ function getLogoutModal() { $j.getJSON(thisUrl + '?request=modal&modal=logout') .done(function(data) { insertModalHtml('modalLogout', data.html); + manageModalBtns('modalLogout'); + clickLogout(); }) .fail(logAjaxFail); } +function clickLogout() { + if ( ! $j('#modalLogout').length ) { + getLogoutModal(); + return; + } + $j('#modalLogout').modal('show'); +} function getStateModal() { $j.getJSON(thisUrl + '?request=modal&modal=state') @@ -769,13 +778,14 @@ function getModal(id) { } function manageModalBtns(id) { - // Manage the CANCEL modal button + // Manage the CANCEL modal button, note data-dismiss="modal" would work better var cancelBtn = document.getElementById(id+"CancelBtn"); if ( cancelBtn ) { document.getElementById(id+"CancelBtn").addEventListener('click', function onCancelClick(evt) { $j('#'+id).modal('hide'); }); } + // 'data-on-click-this' calls the global function in the attribute value with the element when a click happens. document.querySelectorAll('#'+id+'Modal button[data-on-click]').forEach(function attachOnClick(el) { var fnName = el.getAttribute('data-on-click'); From 41ed267b71aac4f3ef1f87e6f2eb4ff5a63f8ddd Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 20 Oct 2020 12:31:38 -0400 Subject: [PATCH 228/230] move view to the form action so that it is part of get request instead of post --- web/ajax/modals/logout.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/ajax/modals/logout.php b/web/ajax/modals/logout.php index e1c1053c3..a0648a70c 100644 --- a/web/ajax/modals/logout.php +++ b/web/ajax/modals/logout.php @@ -56,6 +56,7 @@ while ( $row = $result->fetch(PDO::FETCH_ASSOC) ) { ZM\Warning('Failed to decode ' . $row['data']); continue; } + ZM\Debug(print_r($_SESSION, true)); if ( isset($_SESSION['last_time']) ) { # This is a dead session continue; @@ -91,12 +92,11 @@ $_SESSION = $current_session;