]>
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, | |
61 | textlen: text.length | |
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; | |
7f9a6567 | 76 | me.running = true; |
65bb3b67 DC |
77 | var view = me.getView(); |
78 | var viewModel = me.getViewModel(); | |
79 | Proxmox.Utils.API2Request({ | |
80 | url: me.getView().url, | |
81 | params: viewModel.get('params'), | |
82 | method: 'GET', | |
83 | success: function(response) { | |
84 | Proxmox.Utils.setErrorMask(me, false); | |
85 | var total = response.result.total; | |
86 | var lines = new Array(); | |
87 | var first = Infinity; | |
88 | ||
89 | Ext.Array.each(response.result.data, function(line) { | |
90 | if (first > line.n) { | |
91 | first = line.n; | |
92 | } | |
93 | lines[line.n - 1] = Ext.htmlEncode(line.t); | |
94 | }); | |
95 | ||
96 | lines.length = total; | |
97 | me.updateView(lines.join('<br>'), first - 1, total); | |
7f9a6567 | 98 | me.running = false; |
65bb3b67 DC |
99 | }, |
100 | failure: function(response) { | |
101 | if (view.failCallback) { | |
102 | view.failCallback(response); | |
103 | } else { | |
104 | var msg = response.htmlStatus; | |
105 | Proxmox.Utils.setErrorMask(me, msg); | |
de2e10b5 | 106 | } |
7f9a6567 | 107 | me.running = false; |
de2e10b5 | 108 | } |
65bb3b67 DC |
109 | }); |
110 | }, | |
111 | ||
112 | onScroll: function(x, y) { | |
113 | var me = this; | |
114 | var view = me.getView(); | |
115 | var viewModel = me.getViewModel(); | |
116 | ||
117 | var lineHeight = view.lineHeight; | |
118 | var line = view.getScrollY()/lineHeight; | |
119 | var start = viewModel.get('params.start'); | |
120 | var limit = viewModel.get('params.limit'); | |
121 | var viewLines = view.getHeight()/lineHeight; | |
122 | ||
123 | var viewStart = Math.max(parseInt(line - 1 - view.viewBuffer, 10), 0); | |
124 | var viewEnd = parseInt(line + viewLines + 1 + view.viewBuffer, 10); | |
125 | ||
126 | if (viewStart < start || viewEnd > (start+limit)) { | |
127 | viewModel.set('params.start', | |
128 | Math.max(parseInt(line - limit/2 + 10, 10), 0)); | |
129 | view.loadTask.delay(200); | |
de2e10b5 | 130 | } |
65bb3b67 | 131 | }, |
de2e10b5 | 132 | |
65bb3b67 DC |
133 | init: function(view) { |
134 | var me = this; | |
de2e10b5 | 135 | |
65bb3b67 DC |
136 | if (!view.url) { |
137 | throw "no url specified"; | |
de2e10b5 | 138 | } |
de2e10b5 | 139 | |
65bb3b67 DC |
140 | var viewModel = this.getViewModel(); |
141 | var since = new Date(); | |
142 | since.setDate(since.getDate() - 3); | |
143 | viewModel.set('until', new Date()); | |
144 | viewModel.set('since', since); | |
145 | viewModel.set('params.limit', view.pageSize); | |
146 | viewModel.set('hide_timespan', !view.log_select_timespan); | |
147 | me.lookup('content').setStyle('line-height', view.lineHeight + 'px'); | |
148 | ||
149 | view.loadTask = new Ext.util.DelayedTask(me.doLoad, me); | |
150 | ||
151 | me.updateParams(); | |
152 | view.task = Ext.TaskManager.start({ | |
153 | run: function() { | |
154 | if (!view.isVisible() || !view.scrollToEnd) { | |
155 | return; | |
156 | } | |
de2e10b5 | 157 | |
65bb3b67 | 158 | if (me.scrollPosBottom() <= 1) { |
7f9a6567 DC |
159 | if (!me.running) { |
160 | view.loadTask.delay(200); | |
161 | } | |
65bb3b67 DC |
162 | } |
163 | }, | |
164 | interval: 1000 | |
165 | }); | |
166 | } | |
de2e10b5 DM |
167 | }, |
168 | ||
65bb3b67 | 169 | onDestroy: function() { |
de2e10b5 | 170 | var me = this; |
65bb3b67 DC |
171 | me.loadTask.cancel(); |
172 | Ext.TaskManager.stop(me.task); | |
de2e10b5 DM |
173 | }, |
174 | ||
65bb3b67 DC |
175 | // for user to initiate a load from outside |
176 | requestUpdate: function() { | |
de2e10b5 | 177 | var me = this; |
65bb3b67 DC |
178 | me.loadTask.delay(200); |
179 | }, | |
de2e10b5 | 180 | |
65bb3b67 DC |
181 | viewModel: { |
182 | data: { | |
183 | until: null, | |
184 | since: null, | |
185 | hide_timespan: false, | |
186 | data: { | |
187 | start: 0, | |
188 | total: 0, | |
189 | textlen: 0 | |
190 | }, | |
191 | params: { | |
192 | start: 0, | |
193 | limit: 500, | |
194 | } | |
de2e10b5 | 195 | } |
65bb3b67 | 196 | }, |
de2e10b5 | 197 | |
65bb3b67 DC |
198 | layout: 'auto', |
199 | bodyPadding: 5, | |
200 | scrollable: { | |
201 | x: 'auto', | |
202 | y: 'auto', | |
203 | listeners: { | |
204 | // we have to have this here, since we cannot listen to events | |
205 | // of the scroller in the viewcontroller (extjs bug?), nor does | |
206 | // the panel have a 'scroll' event' | |
207 | scroll: { | |
208 | fn: function(scroller, x, y) { | |
209 | var controller = this.component.getController(); | |
210 | if (controller) { // on destroy, controller can be gone | |
211 | controller.onScroll(x,y); | |
212 | } | |
213 | }, | |
214 | buffer: 200 | |
215 | }, | |
216 | } | |
217 | }, | |
de2e10b5 | 218 | |
65bb3b67 DC |
219 | tbar: { |
220 | bind: { | |
221 | hidden: '{hide_timespan}' | |
222 | }, | |
223 | items: [ | |
224 | '->', | |
225 | 'Since: ', | |
226 | { | |
227 | xtype: 'datefield', | |
228 | name: 'since_date', | |
229 | reference: 'since', | |
230 | format: 'Y-m-d', | |
231 | bind: { | |
232 | value: '{since}', | |
233 | maxValue: '{until}' | |
de2e10b5 | 234 | } |
de2e10b5 | 235 | }, |
65bb3b67 DC |
236 | 'Until: ', |
237 | { | |
238 | xtype: 'datefield', | |
239 | name: 'until_date', | |
240 | reference: 'until', | |
241 | format: 'Y-m-d', | |
242 | bind: { | |
243 | value: '{until}', | |
244 | minValue: '{since}' | |
de2e10b5 | 245 | } |
65bb3b67 DC |
246 | }, |
247 | { | |
248 | xtype: 'button', | |
249 | text: 'Update', | |
250 | handler: 'updateParams' | |
de2e10b5 | 251 | } |
65bb3b67 DC |
252 | ], |
253 | }, | |
de2e10b5 | 254 | |
65bb3b67 DC |
255 | items: [ |
256 | { | |
257 | xtype: 'box', | |
258 | reference: 'content', | |
259 | style: { | |
260 | font: 'normal 11px tahoma, arial, verdana, sans-serif', | |
261 | 'white-space': 'pre' | |
262 | }, | |
263 | } | |
264 | ] | |
de2e10b5 | 265 | }); |