move newlog view to log view

This commit is contained in:
Andrew Bauer
2020-10-02 13:26:35 -05:00
parent c5f69b9441
commit 7b5090ceab
6 changed files with 152 additions and 658 deletions

View File

@@ -1,19 +1,3 @@
#logSummary {
font-size:10px;
}
#logSummary tr {
margin: 0;
padding: 0;
}
#logSummary td {
border: 1px solid #7f7fb2;
padding: 0 6px;
font-size: 10px;
line-height: 15px;
}
tr.log-fat td {
background-color:#ffcccc;
font-weight: bold;
@@ -32,20 +16,3 @@ tr.log-dbg td {
font-style: italic;
}
#exportLog label {
vertical-align: middle;
}
#exportLog input[type=radio] {
margin-right: 4px;
vertical-align: middle;
}
#exportError {
display: none;
color: #dc143c;
margin-bottom: 8px;
}
#exportErrorText {
}

View File

@@ -1,18 +0,0 @@
tr.log-fat td {
background-color:#ffcccc;
font-weight: bold;
}
tr.log-err td {
background-color:#ffcccc;
}
tr.log-war td {
background-color: #ffe4b5;
}
tr.log-dbg td {
color: #666666;
font-style: italic;
}

View File

@@ -1,356 +1,105 @@
var logParms = 'view=request&request=log&task=query';
var logReq = new Request.JSON( {url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: logResponse} );
var logTimer = undefined;
var logTable = undefined;
var table = $j('#logTable');
var logCodes = {
'0': 'INF',
'-1': 'WAR',
'-2': 'ERR',
'-3': 'FAT',
'-4': 'PNC',
/*
This is the format of the json object sent by bootstrap-table
var params =
{
"type":"get",
"data":
{
"search":"some search text",
"sort":"DateTime",
"order":"asc",
"offset":0,
"limit":25
"filter":
{
"message":"some advanced search text"
"level":"some more advanced search text"
}
},
"cache":true,
"contentType":"application/json",
"dataType":"json"
};
*/
var minSampleTime = 2000;
var maxSampleTime = 16000;
var minLogTime = 0;
var maxLogTime = 0;
var logCount = 0;
var maxLogFetch = 100;
var filter = {};
var logTimeout = maxSampleTime;
var firstLoad = true;
var initialDisplayLimit = 200;
var sortReversed = false;
var filterFields = ['Component', 'ServerId', 'Pid', 'Level', 'File', 'Line'];
var options = {};
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
// Called by bootstrap-table to retrieve zm log data
function ajaxRequest(params) {
$j.getJSON(thisUrl + '?view=request&request=newlog&task=query', params.data)
.done(function(data) {
//console.log('Ajax parameters: ' + JSON.stringify(params));
// rearrange the result into what bootstrap-table expects
params.success({total: data.total, totalNotFiltered: data.totalNotFiltered, rows: data.rows});
updateHeaderStats(data);
})
.fail(logAjaxFail);
}
function buildFetchParms( parms ) {
var fetchParms = logParms+'&limit='+maxLogFetch;
if ( parms ) {
fetchParms += '&'+parms;
}
Object.each(filter,
function( value, key ) {
fetchParms += '&filter['+key+']='+value;
}
);
return fetchParms;
}
function updateHeaderStats(data) {
var pageNum = table.bootstrapTable('getOptions').pageNumber;
var pageSize = table.bootstrapTable('getOptions').pageSize;
var startRow = ( (pageNum - 1 ) * pageSize ) + 1;
var stopRow = pageNum * pageSize;
var newClass = (data.logstate == 'ok') ? 'text-success' : (data.logstate == 'alert' ? 'text-warning' : ((data.logstate == 'alarm' ? 'text-danger' : '')));
function fetchNextLogs() {
logReq.send( buildFetchParms( 'minTime='+maxLogTime ) );
}
$j('#logState').text(data.logstate);
$j('#logState').removeClass('text-success');
$j('#logState').removeClass('text-warning');
$j('#logState').removeClass('text-danger');
$j('#logState').addClass(newClass);
function fetchPrevLogs() {
logReq.send( buildFetchParms( 'maxTime='+minLogTime ) );
}
function logResponse( respObj ) {
if ( logTimer ) {
logTimer = clearTimeout( logTimer );
}
if ( respObj.result == 'Ok' ) {
if ( respObj.logs.length > 0 ) {
logTimeout = minSampleTime;
logCount += respObj.logs.length;
try {
respObj.logs.each(
function( log ) {
if ( ( !maxLogTime ) || ( log.TimeKey > maxLogTime ) ) {
maxLogTime = log.TimeKey;
}
if ( ( !minLogTime ) || ( log.TimeKey < minLogTime ) ) {
minLogTime = log.TimeKey;
}
var row = logTable.push([
{content: log.DateTime, properties: {style: 'white-space: nowrap'}},
log.Component, log.Server, log.Pid, log.Code,
escapeHtml(log.Message),
escapeHtml(log.File),
log.Line
]);
delete log.Message;
row.tr.store( 'log', log );
if ( log.Level <= -3 ) {
row.tr.addClass( 'log-fat' );
} else if ( log.Level <= -2 ) {
row.tr.addClass( 'log-err' );
} else if ( log.Level <= -1 ) {
row.tr.addClass( 'log-war' );
} else if ( log.Level > 0 ) {
row.tr.addClass( 'log-dbg' );
}
if ( !firstLoad ) {
var color = document.defaultView.getComputedStyle(row.tr, null).getPropertyValue('color');
var colorParts = color.match(/^rgb.*\((\d+),\s*(\d+),\s*(\d+)/);
rowOrigColor = '#' + parseInt(colorParts[1]).toString(16) + parseInt(colorParts[2]).toString(16) + parseInt(colorParts[3]).toString(16);
//new Fx.Tween( row.tr, { duration: 10000, transition: Fx.Transitions.Sine } ).start( 'color', '#6495ED', rowOrigColor );
}
}
);
if ( typeof(respObj.options) == 'object' ) {
$j.each( respObj.options,
function( field ) {
if ( options[field] ) {
options[field] = Object.assign(options[field], respObj.options[field]);
} else {
options[field] = respObj.options[field];
}
}
);
}
updateFilterSelectors();
$('lastUpdate').set('text', respObj.updated);
$('logState').set('text', respObj.state);
$('logState').removeClass('ok');
$('logState').removeClass('alert');
$('logState').removeClass('alarm');
$('logState').addClass(respObj.state);
$('totalLogs').set('text', respObj.total);
$('availLogs').set('text', respObj.available);
$('displayLogs').set('text', logCount);
if ( firstLoad ) {
if ( logCount < displayLimit ) {
fetchPrevLogs();
}
}
logTable.reSort();
} catch ( e ) {
console.error( e );
}
logTimeout /= 2;
if ( logTimeout < minSampleTime ) {
logTimeout = minSampleTime;
}
} else {
firstLoad = false;
logTimeout *= 2;
if ( logTimeout > maxSampleTime ) {
logTimeout = maxSampleTime;
}
} // end logs.length > 0
} // end if result == Ok
logTimer = fetchNextLogs.delay( logTimeout );
}
function refreshLog() {
options = {};
$j('#logTable tbody').empty();
firstLoad = true;
maxLogTime = 0;
minLogTime = 0;
logCount = 0;
logTimeout = maxSampleTime;
displayLimit = initialDisplayLimit;
fetchNextLogs();
}
function expandLog() {
displayLimit += maxLogFetch;
fetchPrevLogs();
}
function clearResponse() {
refreshLog();
}
function clearError() {
}
function clearLog() {
logReq.cancel();
var clearParms = 'view=request&request=log&task=delete';
var clearReq = new Request.JSON({url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: clearResponse});
var tbody = $(logTable).getElement('tbody');
var rows = tbody.getElements('tr');
if ( rows && rows.length ) {
var minTime = rows[0].getElement('td').get('text');
clearParms += "&minTime="+encodeURIComponent(minTime);
var maxTime = rows[rows.length-1].getElement('td').get('text');
clearParms += "&maxTime="+encodeURIComponent(maxTime);
}
var form = $('logForm');
clearReq.send(clearParms+"&"+form.toQueryString());
}
function filterLog() {
filter = {};
filterFields.each(
function( field ) {
var selector = $('filter['+field+']');
if ( !selector ) {
if ( window.console && window.console.log ) {
window.console.log('No selector found for ' + field);
}
return;
}
var value = selector.get('value');
if ( value ) {
filter[field] = value;
}
}
);
refreshLog();
}
function resetLog() {
filter = {};
refreshLog();
}
var exportFormValidator = null;
function exportLog() {
getModal('log_export');
if ( !exportFormValidator ) {
exportFormValidator = new Form.Validator.Inline($('exportForm'), {
useTitles: true,
warningPrefix: '',
errorPrefix: ''
});
} else {
exportFormValidator.reset();
}
}
function exportResponse( response ) {
$('log_exportModal').unspin();
if ( response.result == 'Ok' ) {
window.location.replace( thisUrl+'?view=request&request=log&task=download&key='+response.key+'&format='+response.format );
}
}
function exportFail( request ) {
$('log_exportModal').unspin();
$('exportErrorText').set('text', request.status+' / '+request.statusText);
$('exportError').show();
Error('Export request failed: '+request.status+' / '+request.statusText);
}
function exportRequest() {
var form = $('exportForm');
console.log(form);
$('exportErrorText').set('text', '');
$('exportError').hide();
if ( form.validate() ) {
var exportParms = "view=request&request=log&task=export";
var exportReq = new Request.JSON({url: thisUrl, method: 'post', link: 'cancel', onSuccess: exportResponse, onFailure: exportFail});
var selector = form.querySelectorAll('input[name=selector]:checked');
if ( !selector.length ) {
alert("Please select how to filter logs");
return;
}
var selection = selector[0].get('value');
if ( selection == 'filter' || selection == 'current' ) {
$$('#filters select').each(
function( select ) {
exportParms += "&"+select.get('id')+"="+select.get('value');
}
);
}
if ( selection == 'current' ) {
var tbody = $(logTable).getElement( 'tbody' );
var rows = tbody.getElements( 'tr' );
if ( rows ) {
var minTime = rows[0].getElement('td').get('text');
exportParms += "&minTime="+encodeURIComponent(minTime);
var maxTime = rows[rows.length-1].getElement('td').get('text');
exportParms += "&maxTime="+encodeURIComponent(maxTime);
}
}
exportReq.send(exportParms+"&"+form.toQueryString());
$('log_exportModal').spin();
}
}
function updateFilterSelectors() {
Object.each(options,
function( values, key ) {
var selector = $('filter['+key+']');
if ( !selector ) {
if ( window.console && window.console.log ) {
window.console.log('No selector found for ' + key);
}
return;
}
selector.options.length = 1;
if ( key == 'Level' ) {
Object.each(values,
function( value, label ) {
selector.options[selector.options.length] = new Option(value, label);
}
);
} else if ( key == 'ServerId' ) {
Object.each(values,
function( value, label ) {
selector.options[selector.options.length] = new Option(value, label);
}
);
} else {
Object.each(values,
function( value, label ) {
selector.options[selector.options.length] = new Option(value, label);
}
);
}
if ( filter[key] ) {
selector.set('value', filter[key]);
}
$j(selector).chosen('destroy');
$j(selector).chosen();
}
);
$j('#totalLogs').text(data.total);
$j('#availLogs').text(data.totalNotFiltered);
$j('#lastUpdate').text(data.updated);
$j('#displayLogs').text(startRow + ' to ' + stopRow);
}
function initPage() {
displayLimit = initialDisplayLimit;
for ( var i = 1; i <= 9; i++ ) {
logCodes[''+i] = 'DB'+i;
}
logTable = new HtmlTable( $('logTable'),
{
zebra: true,
sortable: true,
sortReverse: true
var backBtn = $j('#backBtn');
// Init the bootstrap-table with custom icons
table.bootstrapTable({icons: icons});
// Assign inf, err, fat, dbg color classes to the rows in the table
table.on('post-body.bs.table', function(data) {
var lvl_ndx = $j('#logTable tr th').filter(function() {
return $j(this).text().trim() == 'Level';
}).index();
$j('#logTable tr').each(function(ndx, row) {
var row = $j(row);
var level = row.find('td').eq(lvl_ndx).text().trim();
if (( level == 'FAT' ) || ( level == 'PNC' )) {
row.addClass('log-fat');
} else if ( level == 'ERR' ) {
row.addClass('log-err');
} else if ( level == 'WAR' ) {
row.addClass('log-war');
} else if ( level == 'DBG' ) {
row.addClass('log-dbg');
}
);
logTable.addEvent( 'sort', function( tbody, index ) {
var header = tbody.getParent('table').getElement('thead');
var columns = header.getElement('tr').getElements('th');
var column = columns[index];
sortReversed = column.hasClass('table-th-sort-rev');
if ( logCount > displayLimit ) {
var rows = tbody.getElements('tr');
var startIndex;
if ( sortReversed ) {
startIndex = displayLimit;
} else {
startIndex = 0;
}
for ( var i = startIndex; logCount > displayLimit; i++ ) {
rows[i].destroy();
logCount--;
}
$('displayLogs').set('text', logCount);
} // end if loCount > displayLimit
}
);
new Asset.css('css/spinner.css');
fetchNextLogs();
});
});
// Don't enable the back button if there is no previous zm page to go back to
backBtn.prop('disabled', !document.referrer.length);
// Manage the BACK button
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
evt.preventDefault();
window.history.back();
});
// Manage the REFRESH Button
document.getElementById("refreshBtn").addEventListener("click", function onRefreshClick(evt) {
evt.preventDefault();
window.location.reload(true);
});
}
// Kick everything off
window.addEventListener('DOMContentLoaded', initPage);
$j(document).ready(function() {
initPage();
});

View File

@@ -1,105 +0,0 @@
var table = $j('#logTable');
/*
This is the format of the json object sent by bootstrap-table
var params =
{
"type":"get",
"data":
{
"search":"some search text",
"sort":"DateTime",
"order":"asc",
"offset":0,
"limit":25
"filter":
{
"message":"some advanced search text"
"level":"some more advanced search text"
}
},
"cache":true,
"contentType":"application/json",
"dataType":"json"
};
*/
// Called by bootstrap-table to retrieve zm log data
function ajaxRequest(params) {
$j.getJSON(thisUrl + '?view=request&request=newlog&task=query', params.data)
.done(function(data) {
//console.log('Ajax parameters: ' + JSON.stringify(params));
// rearrange the result into what bootstrap-table expects
params.success({total: data.total, totalNotFiltered: data.totalNotFiltered, rows: data.rows});
updateHeaderStats(data);
})
.fail(logAjaxFail);
}
function updateHeaderStats(data) {
var pageNum = table.bootstrapTable('getOptions').pageNumber;
var pageSize = table.bootstrapTable('getOptions').pageSize;
var startRow = ( (pageNum - 1 ) * pageSize ) + 1;
var stopRow = pageNum * pageSize;
var newClass = (data.logstate == 'ok') ? 'text-success' : (data.logstate == 'alert' ? 'text-warning' : ((data.logstate == 'alarm' ? 'text-danger' : '')));
$j('#logState').text(data.logstate);
$j('#logState').removeClass('text-success');
$j('#logState').removeClass('text-warning');
$j('#logState').removeClass('text-danger');
$j('#logState').addClass(newClass);
$j('#totalLogs').text(data.total);
$j('#availLogs').text(data.totalNotFiltered);
$j('#lastUpdate').text(data.updated);
$j('#displayLogs').text(startRow + ' to ' + stopRow);
}
function initPage() {
var backBtn = $j('#backBtn');
// Init the bootstrap-table with custom icons
table.bootstrapTable({icons: icons});
// Assign inf, err, fat, dbg color classes to the rows in the table
table.on('post-body.bs.table', function(data) {
var lvl_ndx = $j('#logTable tr th').filter(function() {
return $j(this).text().trim() == 'Level';
}).index();
$j('#logTable tr').each(function(ndx, row) {
var row = $j(row);
var level = row.find('td').eq(lvl_ndx).text().trim();
if (( level == 'FAT' ) || ( level == 'PNC' )) {
row.addClass('log-fat');
} else if ( level == 'ERR' ) {
row.addClass('log-err');
} else if ( level == 'WAR' ) {
row.addClass('log-war');
} else if ( level == 'DBG' ) {
row.addClass('log-dbg');
}
});
});
// Don't enable the back button if there is no previous zm page to go back to
backBtn.prop('disabled', !document.referrer.length);
// Manage the BACK button
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
evt.preventDefault();
window.history.back();
});
// Manage the REFRESH Button
document.getElementById("refreshBtn").addEventListener("click", function onRefreshClick(evt) {
evt.preventDefault();
window.location.reload(true);
});
}
$j(document).ready(function() {
initPage();
});

View File

@@ -23,77 +23,69 @@ if ( !canView('System') ) {
return;
}
$focusWindow = true;
xhtmlHeaders(__FILE__, translate('SystemLog'));
?>
<body>
<?php echo getNavBarHTML() ?>
<div id="page">
<div id="header">
<div id="logSummary" class="text-center">
<?php echo translate('State') ?>: <span id="logState"></span>/
<?php echo translate('Total') ?>: <span id="totalLogs"></span>/
<?php echo translate('Available') ?>: <span id="availLogs"></span>/
<?php echo translate('Displaying') ?>: <span id="displayLogs"></span>/
<?php echo translate('Updated') ?>: <span id="lastUpdate"></span>
</div>
<div class="btn-toolbar justify-content-center py-1">
<button type="button" data-on-click="expandLog"><?php echo translate('More') ?></button>
<button type="button" data-on-click="clearLog"><?php echo translate('Clear') ?></button>
<button type="button" data-on-click="refreshLog"><?php echo translate('Refresh') ?></button>
<button type="button" data-on-click="exportLog"><?php echo translate('Export') ?></button>
<button type="reset" data-on-click="resetLog"><?php echo translate('Reset') ?></button>
</div> <!--btn-->
</div> <!--header-->
<div id="content">
<form id="logForm" name="logForm" method="post" action="?">
<input type="hidden" name="view" value="<?php echo $view ?>"/>
<div class="container" id="filters">
<div class="row">
<div class="col">
<label><?php echo translate('Component') ?></label>
<select class="form-control chosen" id="filter[Component]" data-on-change="filterLog"><option value="">-----</option></select>
</div>
<div class="col">
<label><?php echo translate('Server') ?></label>
<select class="form-control chosen" id="filter[ServerId]" data-on-change="filterLog"><option value="">-----</option></select>
</div>
<div class="col">
<label><?php echo translate('Pid') ?></label>
<select class="form-control chosen" id="filter[Pid]" data-on-change="filterLog"><option value="">-----</option></select>
</div>
<div class="col">
<label><?php echo translate('Level') ?></label>
<select class="form-control chosen" id="filter[Level]" data-on-change="filterLog"><option value="">---</option></select>
</div>
<div class="col">
<label><?php echo translate('File') ?></label>
<select class="form-control chosen" id="filter[File]" data-on-change="filterLog"><option value="">------</option></select>
</div>
<div class="col">
<label><?php echo translate('Line') ?></label>
<select class="form-control chosen" id="filter[Line]" data-on-change="filterLog"><option value="">----</option></select>
</div>
</div><!--row-->
</div><!--container-->
<table id="logTable" class="major">
<thead class="thead-highlight">
<tr>
<th><?php echo translate('DateTime') ?></th>
<th class="table-th-nosort"><?php echo translate('Component') ?></th>
<th class="table-th-nosort"><?php echo translate('Server') ?></th>
<th class="table-th-nosort"><?php echo translate('Pid') ?></th>
<th class="table-th-nosort"><?php echo translate('Level') ?></th>
<th class="table-th-nosort"><?php echo translate('Message') ?></th>
<th class="table-th-nosort"><?php echo translate('File') ?></th>
<th class="table-th-nosort"><?php echo translate('Line') ?></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</form>
</div><!--content-->
<div id="page" class="px-3">
<div id="logSummary" class="text-center">
<?php echo translate('State') ?>:&nbsp;<span id="logState"></span>&nbsp;-&nbsp;
<?php echo translate('Total') ?>:&nbsp;<span id="totalLogs"></span>&nbsp;-&nbsp;
<?php echo translate('Available') ?>:&nbsp;<span id="availLogs"></span>&nbsp;-&nbsp;
<?php echo translate('Displaying') ?>:&nbsp;<span id="displayLogs"></span>&nbsp;-&nbsp;
<?php echo translate('Updated') ?>:&nbsp;<span id="lastUpdate"></span>
</div>
<div id="toolbar">
<button id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" disabled><i class="fa fa-arrow-left"></i></button>
<button id="refreshBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Refresh') ?>" ><i class="fa fa-refresh"></i></button>
</div>
<table
id="logTable"
class="table-sm table-borderless"
data-side-pagination="server"
data-ajax="ajaxRequest"
data-pagination="true"
data-page-list="[10, 25, 50, 100, 200, 300, 400, 500]"
data-search="true"
data-advanced-search="true"
data-id-table="advancedTable"
data-cookie="true"
data-cookie-id-table="zmLogsTable"
data-cookie-expire="2y"
data-remember-order="true"
data-show-columns="true"
data-show-export="true"
data-toolbar="#toolbar"
data-show-fullscreen="true"
data-maintain-meta-data="true"
data-mobile-responsive="true"
data-buttons-class="btn btn-normal"
data-show-jump-to="true"
data-auto-refresh="true"
data-auto-refresh-silent="true"
data-show-refresh="true"
data-auto-refresh-interval="5"
>
<thead class="thead-highlight">
<tr>
<th data-sortable="true" data-field="DateTime"><?php echo translate('DateTime') ?></th>
<th data-sortable="true" data-field="Component"><?php echo translate('Component') ?></th>
<th data-sortable="false" data-field="Server"><?php echo translate('Server') ?></th>
<th data-sortable="true" data-field="Pid"><?php echo translate('Pid') ?></th>
<th data-sortable="true" data-field="Code"><?php echo translate('Level') ?></th>
<th data-sortable="true" data-field="Message"><?php echo translate('Message') ?></th>
<th data-sortable="true" data-field="File"><?php echo translate('File') ?></th>
<th data-sortable="true" data-field="Line"><?php echo translate('Line') ?></th>
</tr>
</thead>
<tbody>
<!-- Row data populated via Ajax -->
</tbody>
</table>
</div><!--page-->
<?php xhtmlFooter() ?>

View File

@@ -1,91 +0,0 @@
<?php
//
// ZoneMinder web log view file, $Date: 2010-02-23 09:10:36 +0000 (Tue, 23 Feb 2010) $, $Revision: 3030 $
// Copyright (C) 2001-2008 Philip Coombes
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canView('System') ) {
$view = 'error';
return;
}
xhtmlHeaders(__FILE__, translate('SystemLog'));
?>
<body>
<?php echo getNavBarHTML() ?>
<div id="page" class="px-3">
<div id="logSummary" class="text-center">
<?php echo translate('State') ?>:&nbsp;<span id="logState"></span>&nbsp;-&nbsp;
<?php echo translate('Total') ?>:&nbsp;<span id="totalLogs"></span>&nbsp;-&nbsp;
<?php echo translate('Available') ?>:&nbsp;<span id="availLogs"></span>&nbsp;-&nbsp;
<?php echo translate('Displaying') ?>:&nbsp;<span id="displayLogs"></span>&nbsp;-&nbsp;
<?php echo translate('Updated') ?>:&nbsp;<span id="lastUpdate"></span>
</div>
<div id="toolbar">
<button id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" disabled><i class="fa fa-arrow-left"></i></button>
<button id="refreshBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Refresh') ?>" ><i class="fa fa-refresh"></i></button>
</div>
<table
id="logTable"
class="table-sm table-borderless"
data-side-pagination="server"
data-ajax="ajaxRequest"
data-pagination="true"
data-page-list="[10, 25, 50, 100, 200, 300, 400, 500]"
data-search="true"
data-advanced-search="true"
data-id-table="advancedTable"
data-cookie="true"
data-cookie-id-table="zmLogsTable"
data-cookie-expire="2y"
data-remember-order="true"
data-show-columns="true"
data-show-export="true"
data-toolbar="#toolbar"
data-show-fullscreen="true"
data-maintain-meta-data="true"
data-mobile-responsive="true"
data-buttons-class="btn btn-normal"
data-show-jump-to="true"
data-auto-refresh="true"
data-auto-refresh-silent="true"
data-show-refresh="true"
data-auto-refresh-interval="5"
>
<thead class="thead-highlight">
<tr>
<th data-sortable="true" data-field="DateTime"><?php echo translate('DateTime') ?></th>
<th data-sortable="true" data-field="Component"><?php echo translate('Component') ?></th>
<th data-sortable="false" data-field="Server"><?php echo translate('Server') ?></th>
<th data-sortable="true" data-field="Pid"><?php echo translate('Pid') ?></th>
<th data-sortable="true" data-field="Code"><?php echo translate('Level') ?></th>
<th data-sortable="true" data-field="Message"><?php echo translate('Message') ?></th>
<th data-sortable="true" data-field="File"><?php echo translate('File') ?></th>
<th data-sortable="true" data-field="Line"><?php echo translate('Line') ?></th>
</tr>
</thead>
<tbody>
<!-- Row data populated via Ajax -->
</tbody>
</table>
</div><!--page-->
<?php xhtmlFooter() ?>