pve-manager/www/manager/panel/LogView.js
Thomas Lamprecht 59e6da2d44 web-syslog: add date span selection
This allows the user to only show logs from a specific date span.
For that two date picker and a 'Update' button were added to the
header bar.

For the until date we assume always 23:59:59 o'clock, as witouth
a specific time journalctl assumes 00:00 which would result in an
empty log if we only wanted to look at todays log.

As the LogView is shared with others (e.g. ceph log) use an boolean
variable to set if we want to show those date pickers)

Fixes timeout when the user has a long uptime and or persistent logs
2016-03-02 06:25:33 +01:00

283 lines
6.4 KiB
JavaScript

/*
* Display log entries in a panel with scrollbar
* The log entries are automatically refreshed via a background task,
* with newest entries comming at the bottom
*/
Ext.define('PVE.panel.LogView', {
extend: 'Ext.panel.Panel',
alias: ['widget.pveLogView'],
pageSize: 500,
lineHeight: 16,
viewInfo: undefined,
scrollToEnd: true,
getMaxDown: function(scrollToEnd) {
var me = this;
var target = me.getTargetEl();
var dom = target.dom;
if (scrollToEnd) {
dom.scrollTop = dom.scrollHeight - dom.clientHeight;
}
var maxDown = dom.scrollHeight - dom.clientHeight -
dom.scrollTop;
return maxDown;
},
updateView: function(start, end, total, text) {
var me = this;
var el = me.dataCmp.el;
if (me.viewInfo && me.viewInfo.start === start &&
me.viewInfo.end === end && me.viewInfo.total === total &&
me.viewInfo.textLength === text.length) {
return; // same content
}
var maxDown = me.getMaxDown();
var scrollToEnd = (maxDown <= 0) && me.scrollToEnd;
el.setStyle('padding-top', start*me.lineHeight + 'px');
el.update(text);
me.dataCmp.setHeight(total*me.lineHeight);
if (scrollToEnd) {
me.getMaxDown(true);
}
me.viewInfo = {
start: start,
end: end,
total: total,
textLength: text.length
};
},
doAttemptLoad: function(start) {
var me = this;
var req_params = {
start: start,
limit: me.pageSize
};
if (me.log_select_timespan) {
// always show log until the end of the selected day
req_params.until = Ext.Date.format(me.until_date, 'Y-m-d') + ' 23:59:59';
req_params.since = Ext.Date.format(me.since_date, 'Y-m-d');
}
PVE.Utils.API2Request({
url: me.url,
params: req_params,
method: 'GET',
success: function(response) {
PVE.Utils.setErrorMask(me, false);
var list = response.result.data;
var total = response.result.total;
var first = 0, last = 0;
var text = '';
Ext.Array.each(list, function(item) {
if (!first|| item.n < first) {
first = item.n;
}
if (!last || item.n > last) {
last = item.n;
}
text = text + Ext.htmlEncode(item.t) + "<br>";
});
if (first && last && total) {
me.updateView(first -1 , last -1, total, text);
} else {
me.updateView(0, 0, 0, '');
}
},
failure: function(response) {
var msg = response.htmlStatus;
PVE.Utils.setErrorMask(me, msg);
}
});
},
attemptLoad: function(start) {
var me = this;
if (!me.loadTask) {
me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
}
me.loadTask.delay(200, me.doAttemptLoad, me, [start]);
},
requestUpdate: function(top, force) {
var me = this;
if (top === undefined) {
var target = me.getTargetEl();
top = target.dom.scrollTop;
}
var viewStart = parseInt((top / me.lineHeight) - 1, 10);
if (viewStart < 0) {
viewStart = 0;
}
var viewEnd = parseInt(((top + me.getHeight())/ me.lineHeight) + 1, 10);
var info = me.viewInfo;
if (info && !force) {
if (viewStart >= info.start && viewEnd <= info.end) {
return;
}
}
var line = parseInt((top / me.lineHeight) - (me.pageSize / 2) + 10, 10);
if (line < 0) {
line = 0;
}
me.attemptLoad(line);
},
afterRender: function() {
var me = this;
me.callParent(arguments);
Ext.Function.defer(function() {
var target = me.getTargetEl();
target.on('scroll', function(e) {
me.requestUpdate();
});
me.requestUpdate(0);
}, 20);
},
initComponent : function() {
/*jslint confusion: true */
var me = this;
if (!me.url) {
throw "no url specified";
}
// show logs from today back to 3 days ago per default
me.until_date = new Date();
me.since_date = new Date();
me.since_date.setDate(me.until_date.getDate() - 3);
me.dataCmp = Ext.create('Ext.Component', {
style: 'font:normal 11px tahoma, arial, verdana, sans-serif;' +
'line-height: ' + me.lineHeight.toString() + 'px; white-space: pre;'
});
me.task = Ext.TaskManager.start({
run: function() {
if (!me.isVisible() || !me.scrollToEnd || !me.viewInfo) {
return;
}
var maxDown = me.getMaxDown();
if (maxDown > 0) {
return;
}
me.requestUpdate(undefined, true);
},
interval: 1000
});
Ext.apply(me, {
autoScroll: true,
layout: 'auto',
items: me.dataCmp,
bodyStyle: 'padding: 5px;',
listeners: {
show: function() {
var target = me.getTargetEl();
if (target && target.dom) {
target.dom.scrollTop = me.savedScrollTop;
}
},
beforehide: function() {
// Hack: chrome reset scrollTop to 0, so we save/restore
var target = me.getTargetEl();
if (target && target.dom) {
me.savedScrollTop = target.dom.scrollTop;
}
},
destroy: function() {
Ext.TaskManager.stop(me.task);
}
}
});
if (me.log_select_timespan) {
me.tbar = ['->','Since: ',
{
xtype: 'datefield',
maxValue: me.until_date,
value: me.since_date,
name: 'since_date',
format: 'Y-m-d',
listeners: {
select: function(field, date) {
me.since_date_selected = date;
var until_field = field.up().down('field[name=until_date]');
if (date > until_field.getValue()) {
until_field.setValue(date);
}
}
}
},
'Until: ',
{
xtype: 'datefield',
maxValue: me.until_date,
value: me.until_date,
name: 'until_date',
format: 'Y-m-d',
listeners: {
select: function(field, date) {
var since_field = field.up().down('field[name=since_date]');
if (date < since_field.getValue()) {
since_field.setValue(date);
}
}
}
},
{
xtype: 'button',
text: 'Update',
handler: function() {
var until_field = me.down('field[name=until_date]');
var since_field = me.down('field[name=since_date]');
if (until_field.getValue() < since_field.getValue()) {
Ext.Msg.alert('Error',
'Since date must be less equal than Until date.');
until_field.setValue(me.until_date);
since_field.setValue(me.since_date);
} else {
me.until_date = until_field.getValue();
me.since_date = since_field.getValue();
me.requestUpdate();
}
}
}
];
}
me.callParent();
}
});