]>
git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/panel/LogView.js
2 * Display log entries in a panel with scrollbar
3 * The log entries are automatically refreshed via a background task,
4 * with newest entries coming at the bottom
6 Ext
.define('Proxmox.panel.LogView', {
7 extend
: 'Ext.panel.Panel',
8 xtype
: 'proxmoxLogView',
16 // callback for load failure, used for ceph
17 failCallback
: undefined,
20 xclass
: 'Ext.app.ViewController',
22 updateParams: function() {
24 let viewModel
= me
.getViewModel();
26 if (viewModel
.get('hide_timespan') || viewModel
.get('livemode')) {
30 let since
= viewModel
.get('since');
31 let until
= viewModel
.get('until');
34 Ext
.Msg
.alert('Error', 'Since date must be less equal than Until date.');
38 let submitFormat
= viewModel
.get('submitFormat');
40 viewModel
.set('params.since', Ext
.Date
.format(since
, submitFormat
));
41 if (submitFormat
=== 'Y-m-d') {
42 viewModel
.set('params.until', Ext
.Date
.format(until
, submitFormat
) + ' 23:59:59');
44 viewModel
.set('params.until', Ext
.Date
.format(until
, submitFormat
));
47 me
.getView().loadTask
.delay(200);
50 scrollPosBottom: function() {
51 let view
= this.getView();
52 let pos
= view
.getScrollY();
53 let maxPos
= view
.getScrollable().getMaxPosition().y
;
57 updateView: function(lines
, first
, total
) {
59 let view
= me
.getView();
60 let viewModel
= me
.getViewModel();
61 let content
= me
.lookup('content');
62 let data
= viewModel
.get('data');
64 if (first
=== data
.first
&& total
=== data
.total
&& lines
.length
=== data
.lines
) {
65 // before there is any real output, we get 'no output' as a single line, so always
66 // update if we only have one to be sure to catch the first real line of output
68 return; // same content, skip setting and scrolling
71 viewModel
.set('data', {
77 let scrollPos
= me
.scrollPosBottom();
78 let scrollToBottom
= view
.scrollToEnd
&& scrollPos
<= 5;
80 if (!scrollToBottom
) {
81 // so that we have the 'correct' height for the text
85 content
.update(lines
.join('<br>'));
88 let scroller
= view
.getScrollable();
89 scroller
.suspendEvent('scroll');
90 view
.scrollTo(0, Infinity
);
92 scroller
.resumeEvent('scroll');
103 let view
= me
.getView();
104 let viewModel
= me
.getViewModel();
105 Proxmox
.Utils
.API2Request({
106 url
: me
.getView().url
,
107 params
: viewModel
.get('params'),
109 success: function(response
) {
110 if (me
.isDestroyed
) {
113 Proxmox
.Utils
.setErrorMask(me
, false);
114 let total
= response
.result
.total
;
116 let first
= Infinity
;
118 Ext
.Array
.each(response
.result
.data
, function(line
) {
119 if (first
> line
.n
) {
122 lines
[line
.n
- 1] = Ext
.htmlEncode(line
.t
);
125 me
.updateView(lines
, first
- 1, total
);
128 me
.requested
= false;
129 view
.loadTask
.delay(200);
132 failure: function(response
) {
133 if (view
.failCallback
) {
134 view
.failCallback(response
);
136 let msg
= response
.htmlStatus
;
137 Proxmox
.Utils
.setErrorMask(me
, msg
);
141 me
.requested
= false;
142 view
.loadTask
.delay(200);
148 updateStart: function(scrolledToBottom
, targetLine
) {
150 let view
= me
.getView(), viewModel
= me
.getViewModel();
152 let limit
= viewModel
.get('params.limit');
153 let total
= viewModel
.get('data.total');
155 // heuristic: scroll up? -> load more in front; scroll down? -> load more at end
156 let startRatio
= view
.lastTargetLine
&& view
.lastTargetLine
> targetLine
? 2/3 : 1/3;
157 view
.lastTargetLine
= targetLine
;
159 let newStart
= scrolledToBottom
160 ? Math
.trunc(total
- limit
, 10)
161 : Math
.trunc(targetLine
- (startRatio
* limit
) + 10);
163 viewModel
.set('params.start', Math
.max(newStart
, 0));
165 view
.loadTask
.delay(200);
168 onScroll: function(x
, y
) {
170 let view
= me
.getView(), viewModel
= me
.getViewModel();
172 let line
= view
.getScrollY() / view
.lineHeight
;
173 let viewLines
= view
.getHeight() / view
.lineHeight
;
175 let viewStart
= Math
.max(Math
.trunc(line
- 1 - view
.viewBuffer
), 0);
176 let viewEnd
= Math
.trunc(line
+ viewLines
+ 1 + view
.viewBuffer
);
178 let { start
, limit
} = viewModel
.get('params');
180 let margin
= start
< 20 ? 0 : 20;
182 if (viewStart
< start
+ margin
|| viewEnd
> start
+ limit
- margin
) {
183 me
.updateStart(false, line
);
187 onLiveMode: function() {
189 let viewModel
= me
.getViewModel();
190 viewModel
.set('livemode', true);
191 viewModel
.set('params', { start
: 0, limit
: 510 });
193 let view
= me
.getView();
195 view
.scrollToEnd
= true;
196 me
.updateView([], true, false);
199 onTimespan: function() {
201 me
.getViewModel().set('livemode', false);
202 me
.updateView([], false);
203 // Directly apply currently selected values without update
208 init: function(view
) {
212 throw "no url specified";
215 let viewModel
= this.getViewModel();
216 let since
= new Date();
217 since
.setDate(since
.getDate() - 3);
218 viewModel
.set('until', new Date());
219 viewModel
.set('since', since
);
220 viewModel
.set('params.limit', view
.pageSize
);
221 viewModel
.set('hide_timespan', !view
.log_select_timespan
);
222 viewModel
.set('submitFormat', view
.submitFormat
);
223 me
.lookup('content').setStyle('line-height', `${view.lineHeight}px`);
225 view
.loadTask
= new Ext
.util
.DelayedTask(me
.doLoad
, me
);
228 view
.task
= Ext
.TaskManager
.start({
230 if (!view
.isVisible() || !view
.scrollToEnd
) {
233 if (me
.scrollPosBottom() <= 5) {
234 view
.loadTask
.delay(200);
242 onDestroy: function() {
244 me
.loadTask
.cancel();
245 Ext
.TaskManager
.stop(me
.task
);
248 // for user to initiate a load from outside
249 requestUpdate: function() {
251 me
.loadTask
.delay(200);
258 submitFormat
: 'Y-m-d',
260 hide_timespan
: false,
279 // we have to have this here, since we cannot listen to events of the scroller in
280 // the viewcontroller (extjs bug?), nor does the panel have a 'scroll' event'
282 fn: function(scroller
, x
, y
) {
283 let controller
= this.component
.getController();
284 if (controller
) { // on destroy, controller can be gone
285 controller
.onScroll(x
, y
);
295 hidden
: '{hide_timespan}',
300 xtype
: 'segmentedbutton',
303 text
: gettext('Live Mode'),
305 pressed
: '{livemode}',
307 handler
: 'onLiveMode',
310 text
: gettext('Select Timespan'),
312 pressed
: '{!livemode}',
314 handler
: 'onTimespan',
320 autoEl
: { cn
: gettext('Since') + ':' },
322 disabled
: '{livemode}',
326 xtype
: 'proxmoxDateTimeField',
331 disabled
: '{livemode}',
334 submitFormat
: '{submitFormat}',
339 autoEl
: { cn
: gettext('Until') + ':' },
341 disabled
: '{livemode}',
345 xtype
: 'proxmoxDateTimeField',
350 disabled
: '{livemode}',
353 submitFormat
: '{submitFormat}',
359 handler
: 'updateParams',
361 disabled
: '{livemode}',
370 reference
: 'content',
372 font
: 'normal 11px tahoma, arial, verdana, sans-serif',
373 'white-space': 'pre',