mirror of
https://git.proxmox.com/git/pve-manager
synced 2025-06-14 12:35:59 +00:00

when we click on a node/container/vm and quickly click on something else, there might be a race condition, where the store finished loading and we try to change dom elements, which are not there anymore so we change the store.on to me.mon, which deletes the handler when the component is gone in the logview panel we use API2Request, where we cannot do this, so we check if the component is destroyed manually also we change this whenever we change a dom element in a callback Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
205 lines
4.1 KiB
JavaScript
205 lines
4.1 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,
|
|
|
|
autoScroll: true,
|
|
|
|
layout: 'auto',
|
|
|
|
bodyPadding: 5,
|
|
|
|
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.destroyed) { // return if element is not there anymore
|
|
return;
|
|
}
|
|
|
|
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;
|
|
|
|
PVE.Utils.API2Request({
|
|
url: me.url,
|
|
params: {
|
|
start: start,
|
|
limit: me.pageSize
|
|
},
|
|
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";
|
|
}
|
|
|
|
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, {
|
|
items: me.dataCmp,
|
|
listeners: {
|
|
destroy: function() {
|
|
Ext.TaskManager.stop(me.task);
|
|
}
|
|
}
|
|
});
|
|
|
|
me.callParent();
|
|
}
|
|
});
|