]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - panel/LogView.js
aae7440f586cd88f3d6a24bf17e0a986e8a40d9e
[proxmox-widget-toolkit.git] / panel / LogView.js
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',
8 xtype: 'proxmoxLogView',
9
10 pageSize: 500,
11 viewBuffer: 50,
12 lineHeight: 16,
13
14 scrollToEnd: true,
15
16 // callback for load failure, used for ceph
17 failCallback: undefined,
18
19 controller: {
20 xclass: 'Ext.app.ViewController',
21
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 }
30
31 if (since > until) {
32 Ext.Msg.alert('Error', 'Since date must be less equal than Until date.');
33 return;
34 }
35
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 });
63
64 var scrollPos = me.scrollPosBottom();
65
66 content.update(text);
67
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;
76 me.running = true;
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);
98 me.running = false;
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);
106 }
107 me.running = false;
108 }
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);
130 }
131 },
132
133 init: function(view) {
134 var me = this;
135
136 if (!view.url) {
137 throw "no url specified";
138 }
139
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 }
157
158 if (me.scrollPosBottom() <= 1) {
159 if (!me.running) {
160 view.loadTask.delay(200);
161 }
162 }
163 },
164 interval: 1000
165 });
166 }
167 },
168
169 onDestroy: function() {
170 var me = this;
171 me.loadTask.cancel();
172 Ext.TaskManager.stop(me.task);
173 },
174
175 // for user to initiate a load from outside
176 requestUpdate: function() {
177 var me = this;
178 me.loadTask.delay(200);
179 },
180
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 }
195 }
196 },
197
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 },
218
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}'
234 }
235 },
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}'
245 }
246 },
247 {
248 xtype: 'button',
249 text: 'Update',
250 handler: 'updateParams'
251 }
252 ],
253 },
254
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 ]
265 });