]> git.proxmox.com Git - proxmox-widget-toolkit.git/blame - src/panel/JournalView.js
ui: journalview: fix wrong first load with timespan
[proxmox-widget-toolkit.git] / src / panel / JournalView.js
CommitLineData
a1498508
DC
1/*
2 * Display log entries in a panel with scrollbar
3 * The log entries are automatically refreshed via a background task,
4 * with newest entries comming at the bottom
5 */
6Ext.define('Proxmox.panel.JournalView', {
7 extend: 'Ext.panel.Panel',
8 xtype: 'proxmoxJournalView',
9
10 numEntries: 500,
11 lineHeight: 16,
12
13 scrollToEnd: true,
14
15 controller: {
16 xclass: 'Ext.app.ViewController',
17
18 updateParams: function() {
05a977a2
TL
19 let me = this;
20 let viewModel = me.getViewModel();
21 let since = viewModel.get('since');
22 let until = viewModel.get('until');
a1498508
DC
23
24 since.setHours(0, 0, 0, 0);
25 until.setHours(0, 0, 0, 0);
26 until.setDate(until.getDate()+1);
27
28 me.getView().loadTask.delay(200, undefined, undefined, [
29 false,
30 false,
31 Ext.Date.format(since, "U"),
01031528 32 Ext.Date.format(until, "U"),
a1498508
DC
33 ]);
34 },
35
36 scrollPosBottom: function() {
05a977a2
TL
37 let view = this.getView();
38 let pos = view.getScrollY();
39 let maxPos = view.getScrollable().getMaxPosition().y;
a1498508
DC
40 return maxPos - pos;
41 },
42
43 scrollPosTop: function() {
05a977a2 44 let view = this.getView();
a1498508
DC
45 return view.getScrollY();
46 },
47
48 updateScroll: function(livemode, num, scrollPos, scrollPosTop) {
05a977a2
TL
49 let me = this;
50 let view = me.getView();
a1498508
DC
51
52 if (!livemode) {
53 setTimeout(function() { view.scrollTo(0, 0); }, 10);
aa9607f1 54 } else if (view.scrollToEnd && scrollPos <= 5) {
a1498508 55 setTimeout(function() { view.scrollTo(0, Infinity); }, 10);
05a977a2
TL
56 } else if (!view.scrollToEnd && scrollPosTop < 20 * view.lineHeight) {
57 setTimeout(function() { view.scrollTo(0, (num * view.lineHeight) + scrollPosTop); }, 10);
a1498508
DC
58 }
59 },
60
61 updateView: function(lines, livemode, top) {
05a977a2
TL
62 let me = this;
63 let view = me.getView();
64 let viewmodel = me.getViewModel();
865be88e 65 if (!viewmodel || viewmodel.get('livemode') !== livemode) {
a1498508
DC
66 return; // we switched mode, do not update the content
67 }
05a977a2 68 let contentEl = me.lookup('content');
a1498508
DC
69
70 // save old scrollpositions
05a977a2
TL
71 let scrollPos = me.scrollPosBottom();
72 let scrollPosTop = me.scrollPosTop();
a1498508 73
05a977a2
TL
74 let newend = lines.shift();
75 let newstart = lines.pop();
a1498508 76
05a977a2
TL
77 let num = lines.length;
78 let text = lines.map(Ext.htmlEncode).join('<br>');
a1498508 79
17c320c8
DC
80 let contentChanged = true;
81
a1498508 82 if (!livemode) {
70df8f46
TL
83 if (num) {
84 view.content = text;
85 } else {
86 view.content = 'nothing logged or no timespan selected';
87 }
a1498508
DC
88 } else {
89 // update content
90 if (top && num) {
91 view.content = view.content ? text + '<br>' + view.content : text;
92 } else if (!top && num) {
93 view.content = view.content ? view.content + '<br>' + text : text;
17c320c8
DC
94 } else {
95 contentChanged = false;
a1498508
DC
96 }
97
98 // update cursors
99 if (!top || !view.startcursor) {
100 view.startcursor = newstart;
101 }
102
103 if (top || !view.endcursor) {
104 view.endcursor = newend;
105 }
106 }
107
17c320c8
DC
108 if (contentChanged) {
109 contentEl.update(view.content);
110 }
a1498508
DC
111
112 me.updateScroll(livemode, num, scrollPos, scrollPosTop);
113 },
114
115 doLoad: function(livemode, top, since, until) {
05a977a2 116 let me = this;
a1498508
DC
117 if (me.running) {
118 me.requested = true;
119 return;
120 }
121 me.running = true;
05a977a2
TL
122 let view = me.getView();
123 let params = {
a1498508
DC
124 lastentries: view.numEntries || 500,
125 };
126 if (livemode) {
127 if (!top && view.startcursor) {
128 params = {
01031528 129 startcursor: view.startcursor,
a1498508
DC
130 };
131 } else if (view.endcursor) {
132 params.endcursor = view.endcursor;
133 }
134 } else {
135 params = {
136 since: since,
01031528 137 until: until,
a1498508
DC
138 };
139 }
140 Proxmox.Utils.API2Request({
141 url: view.url,
142 params: params,
01031528 143 waitMsgTarget: !livemode ? view : undefined,
a1498508
DC
144 method: 'GET',
145 success: function(response) {
146 Proxmox.Utils.setErrorMask(me, false);
05a977a2 147 let lines = response.result.data;
a1498508
DC
148 me.updateView(lines, livemode, top);
149 me.running = false;
150 if (me.requested) {
151 me.requested = false;
152 view.loadTask.delay(200);
153 }
154 },
155 failure: function(response) {
05a977a2 156 let msg = response.htmlStatus;
a1498508
DC
157 Proxmox.Utils.setErrorMask(me, msg);
158 me.running = false;
159 if (me.requested) {
160 me.requested = false;
161 view.loadTask.delay(200);
162 }
01031528 163 },
a1498508
DC
164 });
165 },
166
167 onScroll: function(x, y) {
05a977a2
TL
168 let me = this;
169 let view = me.getView();
170 let viewmodel = me.getViewModel();
171 let livemode = viewmodel.get('livemode');
a1498508
DC
172 if (!livemode) {
173 return;
174 }
175
176 if (me.scrollPosTop() < 20*view.lineHeight) {
177 view.scrollToEnd = false;
178 view.loadTask.delay(200, undefined, undefined, [true, true]);
aa9607f1 179 } else if (me.scrollPosBottom() <= 5) {
a1498508
DC
180 view.scrollToEnd = true;
181 }
182 },
183
184 init: function(view) {
05a977a2 185 let me = this;
a1498508
DC
186
187 if (!view.url) {
188 throw "no url specified";
189 }
190
05a977a2
TL
191 let viewmodel = me.getViewModel();
192 let viewModel = this.getViewModel();
193 let since = new Date();
a1498508
DC
194 since.setDate(since.getDate() - 3);
195 viewModel.set('until', new Date());
196 viewModel.set('since', since);
197 me.lookup('content').setStyle('line-height', view.lineHeight + 'px');
198
199 view.loadTask = new Ext.util.DelayedTask(me.doLoad, me, [true, false]);
200
a1498508
DC
201 view.task = Ext.TaskManager.start({
202 run: function() {
203 if (!view.isVisible() || !view.scrollToEnd || !viewmodel.get('livemode')) {
204 return;
205 }
206
aa9607f1 207 if (me.scrollPosBottom() <= 5) {
a1498508
DC
208 view.loadTask.delay(200, undefined, undefined, [true, false]);
209 }
210 },
01031528 211 interval: 1000,
a1498508
DC
212 });
213 },
214
215 onLiveMode: function() {
05a977a2
TL
216 let me = this;
217 let view = me.getView();
a1498508
DC
218 delete view.startcursor;
219 delete view.endcursor;
220 delete view.content;
221 me.getViewModel().set('livemode', true);
222 view.scrollToEnd = true;
223 me.updateView([], true, false);
224 },
225
226 onTimespan: function() {
05a977a2 227 let me = this;
a1498508
DC
228 me.getViewModel().set('livemode', false);
229 me.updateView([], false);
01031528 230 },
a1498508
DC
231 },
232
233 onDestroy: function() {
05a977a2 234 let me = this;
a1498508
DC
235 me.loadTask.cancel();
236 Ext.TaskManager.stop(me.task);
237 delete me.content;
238 },
239
240 // for user to initiate a load from outside
241 requestUpdate: function() {
05a977a2 242 let me = this;
a1498508
DC
243 me.loadTask.delay(200);
244 },
245
246 viewModel: {
247 data: {
248 livemode: true,
249 until: null,
01031528
TL
250 since: null,
251 },
a1498508
DC
252 },
253
254 layout: 'auto',
255 bodyPadding: 5,
256 scrollable: {
257 x: 'auto',
258 y: 'auto',
259 listeners: {
260 // we have to have this here, since we cannot listen to events
261 // of the scroller in the viewcontroller (extjs bug?), nor does
262 // the panel have a 'scroll' event'
263 scroll: {
264 fn: function(scroller, x, y) {
05a977a2 265 let controller = this.component.getController();
a1498508 266 if (controller) { // on destroy, controller can be gone
01031528 267 controller.onScroll(x, y);
a1498508
DC
268 }
269 },
01031528 270 buffer: 200,
a1498508 271 },
01031528 272 },
a1498508
DC
273 },
274
275 tbar: {
276
277 items: [
278 '->',
279 {
280 xtype: 'segmentedbutton',
281 items: [
282 {
283 text: gettext('Live Mode'),
284 bind: {
01031528 285 pressed: '{livemode}',
a1498508
DC
286 },
287 handler: 'onLiveMode',
288 },
289 {
290 text: gettext('Select Timespan'),
291 bind: {
01031528 292 pressed: '{!livemode}',
a1498508
DC
293 },
294 handler: 'onTimespan',
01031528
TL
295 },
296 ],
a1498508 297 },
cd82be49
TL
298 {
299 xtype: 'box',
300 bind: { disabled: '{livemode}' },
01031528 301 autoEl: { cn: gettext('Since') + ':' },
cd82be49 302 },
a1498508
DC
303 {
304 xtype: 'datefield',
a1498508
DC
305 name: 'since_date',
306 reference: 'since',
307 format: 'Y-m-d',
308 bind: {
309 disabled: '{livemode}',
310 value: '{since}',
01031528
TL
311 maxValue: '{until}',
312 },
a1498508 313 },
cd82be49
TL
314 {
315 xtype: 'box',
316 bind: { disabled: '{livemode}' },
01031528 317 autoEl: { cn: gettext('Until') + ':' },
cd82be49 318 },
a1498508
DC
319 {
320 xtype: 'datefield',
a1498508
DC
321 name: 'until_date',
322 reference: 'until',
323 format: 'Y-m-d',
324 bind: {
325 disabled: '{livemode}',
326 value: '{until}',
01031528
TL
327 minValue: '{since}',
328 },
a1498508
DC
329 },
330 {
331 xtype: 'button',
332 text: 'Update',
333 reference: 'updateBtn',
334 handler: 'updateParams',
335 bind: {
01031528
TL
336 disabled: '{livemode}',
337 },
338 },
339 ],
a1498508
DC
340 },
341
342 items: [
343 {
344 xtype: 'box',
345 reference: 'content',
346 style: {
347 font: 'normal 11px tahoma, arial, verdana, sans-serif',
01031528 348 'white-space': 'pre',
a1498508 349 },
01031528
TL
350 },
351 ],
a1498508 352});