]>
Commit | Line | Data |
---|---|---|
de2e10b5 DM |
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 | */ | |
6 | Ext.define('Proxmox.panel.LogView', { | |
7 | extend: 'Ext.panel.Panel', | |
65bb3b67 | 8 | xtype: 'proxmoxLogView', |
de2e10b5 DM |
9 | |
10 | pageSize: 500, | |
65bb3b67 | 11 | viewBuffer: 50, |
de2e10b5 DM |
12 | lineHeight: 16, |
13 | ||
de2e10b5 DM |
14 | scrollToEnd: true, |
15 | ||
65bb3b67 DC |
16 | // callback for load failure, used for ceph |
17 | failCallback: undefined, | |
de2e10b5 | 18 | |
65bb3b67 DC |
19 | controller: { |
20 | xclass: 'Ext.app.ViewController', | |
de2e10b5 | 21 | |
65bb3b67 DC |
22 | updateParams: function() { |
23 | var me = this; | |
24 | var viewModel = me.getViewModel(); | |
25 | var since = viewModel.get('since'); | |
26 | var until = viewModel.get('until'); | |
27 | if (viewModel.get('hide_timespan')) { | |
28 | return; | |
29 | } | |
de2e10b5 | 30 | |
65bb3b67 DC |
31 | if (since > until) { |
32 | Ext.Msg.alert('Error', 'Since date must be less equal than Until date.'); | |
33 | return; | |
34 | } | |
de2e10b5 | 35 | |
65bb3b67 DC |
36 | viewModel.set('params.since', Ext.Date.format(since, 'Y-m-d')); |
37 | viewModel.set('params.until', Ext.Date.format(until, 'Y-m-d') + ' 23:59:59'); | |
38 | me.getView().loadTask.delay(200); | |
39 | }, | |
40 | ||
41 | scrollPosBottom: function() { | |
42 | var view = this.getView(); | |
43 | var pos = view.getScrollY(); | |
44 | var maxPos = view.getScrollable().getMaxPosition().y; | |
45 | return maxPos - pos; | |
46 | }, | |
47 | ||
48 | updateView: function(text, first, total) { | |
49 | var me = this; | |
50 | var view = me.getView(); | |
51 | var viewModel = me.getViewModel(); | |
52 | var content = me.lookup('content'); | |
53 | var data = viewModel.get('data'); | |
54 | ||
55 | if (first === data.first && total === data.total && text.length === data.textlen) { | |
56 | return; // same content, skip setting and scrolling | |
57 | } | |
58 | viewModel.set('data', { | |
59 | first: first, | |
60 | total: total, | |
01031528 | 61 | textlen: text.length, |
65bb3b67 | 62 | }); |
de2e10b5 | 63 | |
65bb3b67 | 64 | var scrollPos = me.scrollPosBottom(); |
de2e10b5 | 65 | |
65bb3b67 | 66 | content.update(text); |
de2e10b5 | 67 | |
65bb3b67 DC |
68 | if (view.scrollToEnd && scrollPos <= 0) { |
69 | // we use setTimeout to work around scroll handling on touchscreens | |
70 | setTimeout(function() { view.scrollTo(0, Infinity); }, 10); | |
71 | } | |
72 | }, | |
73 | ||
74 | doLoad: function() { | |
75 | var me = this; | |
72be386c TL |
76 | if (me.running) { |
77 | me.requested = true; | |
78 | return; | |
79 | } | |
7f9a6567 | 80 | me.running = true; |
65bb3b67 DC |
81 | var view = me.getView(); |
82 | var viewModel = me.getViewModel(); | |
83 | Proxmox.Utils.API2Request({ | |
84 | url: me.getView().url, | |
85 | params: viewModel.get('params'), | |
86 | method: 'GET', | |
87 | success: function(response) { | |
88 | Proxmox.Utils.setErrorMask(me, false); | |
89 | var total = response.result.total; | |
90 | var lines = new Array(); | |
91 | var first = Infinity; | |
92 | ||
93 | Ext.Array.each(response.result.data, function(line) { | |
94 | if (first > line.n) { | |
95 | first = line.n; | |
96 | } | |
97 | lines[line.n - 1] = Ext.htmlEncode(line.t); | |
98 | }); | |
99 | ||
100 | lines.length = total; | |
101 | me.updateView(lines.join('<br>'), first - 1, total); | |
7f9a6567 | 102 | me.running = false; |
72be386c TL |
103 | if (me.requested) { |
104 | me.requested = false; | |
105 | view.loadTask.delay(200); | |
106 | } | |
65bb3b67 DC |
107 | }, |
108 | failure: function(response) { | |
109 | if (view.failCallback) { | |
110 | view.failCallback(response); | |
111 | } else { | |
112 | var msg = response.htmlStatus; | |
113 | Proxmox.Utils.setErrorMask(me, msg); | |
de2e10b5 | 114 | } |
7f9a6567 | 115 | me.running = false; |
72be386c TL |
116 | if (me.requested) { |
117 | me.requested = false; | |
118 | view.loadTask.delay(200); | |
119 | } | |
01031528 | 120 | }, |
65bb3b67 DC |
121 | }); |
122 | }, | |
123 | ||
124 | onScroll: function(x, y) { | |
125 | var me = this; | |
126 | var view = me.getView(); | |
127 | var viewModel = me.getViewModel(); | |
128 | ||
129 | var lineHeight = view.lineHeight; | |
130 | var line = view.getScrollY()/lineHeight; | |
131 | var start = viewModel.get('params.start'); | |
132 | var limit = viewModel.get('params.limit'); | |
133 | var viewLines = view.getHeight()/lineHeight; | |
134 | ||
135 | var viewStart = Math.max(parseInt(line - 1 - view.viewBuffer, 10), 0); | |
136 | var viewEnd = parseInt(line + viewLines + 1 + view.viewBuffer, 10); | |
137 | ||
01031528 | 138 | if (viewStart < start || viewEnd > start+limit) { |
65bb3b67 DC |
139 | viewModel.set('params.start', |
140 | Math.max(parseInt(line - limit/2 + 10, 10), 0)); | |
141 | view.loadTask.delay(200); | |
de2e10b5 | 142 | } |
65bb3b67 | 143 | }, |
de2e10b5 | 144 | |
65bb3b67 DC |
145 | init: function(view) { |
146 | var me = this; | |
de2e10b5 | 147 | |
65bb3b67 DC |
148 | if (!view.url) { |
149 | throw "no url specified"; | |
de2e10b5 | 150 | } |
de2e10b5 | 151 | |
65bb3b67 DC |
152 | var viewModel = this.getViewModel(); |
153 | var since = new Date(); | |
154 | since.setDate(since.getDate() - 3); | |
155 | viewModel.set('until', new Date()); | |
156 | viewModel.set('since', since); | |
157 | viewModel.set('params.limit', view.pageSize); | |
158 | viewModel.set('hide_timespan', !view.log_select_timespan); | |
159 | me.lookup('content').setStyle('line-height', view.lineHeight + 'px'); | |
160 | ||
161 | view.loadTask = new Ext.util.DelayedTask(me.doLoad, me); | |
162 | ||
163 | me.updateParams(); | |
164 | view.task = Ext.TaskManager.start({ | |
165 | run: function() { | |
166 | if (!view.isVisible() || !view.scrollToEnd) { | |
167 | return; | |
168 | } | |
de2e10b5 | 169 | |
65bb3b67 | 170 | if (me.scrollPosBottom() <= 1) { |
72be386c | 171 | view.loadTask.delay(200); |
65bb3b67 DC |
172 | } |
173 | }, | |
01031528 | 174 | interval: 1000, |
65bb3b67 | 175 | }); |
01031528 | 176 | }, |
de2e10b5 DM |
177 | }, |
178 | ||
65bb3b67 | 179 | onDestroy: function() { |
de2e10b5 | 180 | var me = this; |
65bb3b67 DC |
181 | me.loadTask.cancel(); |
182 | Ext.TaskManager.stop(me.task); | |
de2e10b5 DM |
183 | }, |
184 | ||
65bb3b67 DC |
185 | // for user to initiate a load from outside |
186 | requestUpdate: function() { | |
de2e10b5 | 187 | var me = this; |
65bb3b67 DC |
188 | me.loadTask.delay(200); |
189 | }, | |
de2e10b5 | 190 | |
65bb3b67 DC |
191 | viewModel: { |
192 | data: { | |
193 | until: null, | |
194 | since: null, | |
195 | hide_timespan: false, | |
196 | data: { | |
197 | start: 0, | |
198 | total: 0, | |
01031528 | 199 | textlen: 0, |
65bb3b67 DC |
200 | }, |
201 | params: { | |
202 | start: 0, | |
203 | limit: 500, | |
01031528 TL |
204 | }, |
205 | }, | |
65bb3b67 | 206 | }, |
de2e10b5 | 207 | |
65bb3b67 DC |
208 | layout: 'auto', |
209 | bodyPadding: 5, | |
210 | scrollable: { | |
211 | x: 'auto', | |
212 | y: 'auto', | |
213 | listeners: { | |
214 | // we have to have this here, since we cannot listen to events | |
215 | // of the scroller in the viewcontroller (extjs bug?), nor does | |
216 | // the panel have a 'scroll' event' | |
217 | scroll: { | |
218 | fn: function(scroller, x, y) { | |
219 | var controller = this.component.getController(); | |
220 | if (controller) { // on destroy, controller can be gone | |
01031528 | 221 | controller.onScroll(x, y); |
65bb3b67 DC |
222 | } |
223 | }, | |
01031528 | 224 | buffer: 200, |
65bb3b67 | 225 | }, |
01031528 | 226 | }, |
65bb3b67 | 227 | }, |
de2e10b5 | 228 | |
65bb3b67 DC |
229 | tbar: { |
230 | bind: { | |
01031528 | 231 | hidden: '{hide_timespan}', |
65bb3b67 DC |
232 | }, |
233 | items: [ | |
234 | '->', | |
235 | 'Since: ', | |
236 | { | |
237 | xtype: 'datefield', | |
238 | name: 'since_date', | |
239 | reference: 'since', | |
240 | format: 'Y-m-d', | |
241 | bind: { | |
242 | value: '{since}', | |
01031528 TL |
243 | maxValue: '{until}', |
244 | }, | |
de2e10b5 | 245 | }, |
65bb3b67 DC |
246 | 'Until: ', |
247 | { | |
248 | xtype: 'datefield', | |
249 | name: 'until_date', | |
250 | reference: 'until', | |
251 | format: 'Y-m-d', | |
252 | bind: { | |
253 | value: '{until}', | |
01031528 TL |
254 | minValue: '{since}', |
255 | }, | |
65bb3b67 DC |
256 | }, |
257 | { | |
258 | xtype: 'button', | |
259 | text: 'Update', | |
01031528 TL |
260 | handler: 'updateParams', |
261 | }, | |
65bb3b67 DC |
262 | ], |
263 | }, | |
de2e10b5 | 264 | |
65bb3b67 DC |
265 | items: [ |
266 | { | |
267 | xtype: 'box', | |
268 | reference: 'content', | |
269 | style: { | |
270 | font: 'normal 11px tahoma, arial, verdana, sans-serif', | |
01031528 | 271 | 'white-space': 'pre', |
65bb3b67 | 272 | }, |
01031528 TL |
273 | }, |
274 | ], | |
de2e10b5 | 275 | }); |