]> git.proxmox.com Git - proxmox-widget-toolkit.git/blobdiff - panel/LogView.js
rework panel/LogView
[proxmox-widget-toolkit.git] / panel / LogView.js
index 05a90a30911c68e6d82785d3ab464a77e2924b67..fe8d274f4a6f0559a092ba24b7171eb5ee0584c7 100644 (file)
  */
 Ext.define('Proxmox.panel.LogView', {
     extend: 'Ext.panel.Panel',
-
-    alias: ['widget.proxmoxLogView'],
+    xtype: 'proxmoxLogView',
 
     pageSize: 500,
-
+    viewBuffer: 50,
     lineHeight: 16,
 
-    viewInfo: undefined,
-
     scrollToEnd: true,
 
-    autoScroll: true,
-
-    layout: 'auto',
-
-    bodyPadding: 5,
-
-    getMaxDown: function(scrollToEnd) {
-        var me = this;
-
-       var target = me.getTargetEl();
-       var dom = target.dom;
-       if (scrollToEnd) {
-           dom.scrollTop = dom.scrollHeight - dom.clientHeight;
-       }
-
-       var maxDown = dom.scrollHeight - dom.clientHeight -
-           dom.scrollTop;
-
-       return maxDown;
-    },
-
-    updateView: function(start, end, total, text) {
-        var me = this;
-
-       if (me.destroyed) { // return if element is not there anymore
-           return;
-       }
-
-       var el = me.dataCmp.el;
-
-       if (me.viewInfo && me.viewInfo.start === start &&
-           me.viewInfo.end === end && me.viewInfo.total === total &&
-           me.viewInfo.textLength === text.length) {
-           return; // same content
-       }
+    // callback for load failure, used for ceph
+    failCallback: undefined,
 
-       var maxDown = me.getMaxDown();
-       var scrollToEnd = (maxDown <= 0) && me.scrollToEnd;
+    controller: {
+       xclass: 'Ext.app.ViewController',
 
-       el.setStyle('padding-top', (start*me.lineHeight).toString() + 'px');
-       el.update(text);
-       me.dataCmp.setHeight(total*me.lineHeight);
-
-       if (scrollToEnd) {
-           me.getMaxDown(true);
-       }
+       updateParams: function() {
+           var me = this;
+           var viewModel = me.getViewModel();
+           var since = viewModel.get('since');
+           var until = viewModel.get('until');
+           if (viewModel.get('hide_timespan')) {
+               return;
+           }
 
-       me.viewInfo = {
-           start: start,
-           end: end,
-           total: total,
-           textLength:  text.length
-       };
-    },
+           if (since > until) {
+               Ext.Msg.alert('Error', 'Since date must be less equal than Until date.');
+               return;
+           }
 
-    doAttemptLoad: function(start) {
-        var me = this;
+           viewModel.set('params.since', Ext.Date.format(since, 'Y-m-d'));
+           viewModel.set('params.until', Ext.Date.format(until, 'Y-m-d') + ' 23:59:59');
+           me.getView().loadTask.delay(200);
+       },
+
+       scrollPosBottom: function() {
+           var view = this.getView();
+           var pos = view.getScrollY();
+           var maxPos = view.getScrollable().getMaxPosition().y;
+           return maxPos - pos;
+       },
+
+       updateView: function(text, first, total) {
+           var me = this;
+           var view = me.getView();
+           var viewModel = me.getViewModel();
+           var content = me.lookup('content');
+           var data = viewModel.get('data');
+
+           if (first === data.first && total === data.total && text.length === data.textlen) {
+               return; // same content, skip setting and scrolling
+           }
+           viewModel.set('data', {
+               first: first,
+               total: total,
+               textlen: text.length
+           });
 
-       var req_params = {
-           start: start,
-           limit: me.pageSize
-       };
+           var scrollPos = me.scrollPosBottom();
 
-       if (me.log_select_timespan) {
-           // always show log until the end of the selected day
-           req_params.until = Ext.Date.format(me.until_date, 'Y-m-d') + ' 23:59:59';
-           req_params.since = Ext.Date.format(me.since_date, 'Y-m-d');
-       }
+           content.update(text);
 
-       Proxmox.Utils.API2Request({
-           url: me.url,
-           params: req_params,
-           method: 'GET',
-           success: function(response) {
-               Proxmox.Utils.setErrorMask(me, false);
-               var list = response.result.data;
-               var total = response.result.total;
-               var first = 0, last = 0;
-               var text = '';
-               Ext.Array.each(list, function(item) {
-                   if (!first|| item.n < first) {
-                       first = item.n;
-                   }
-                   if (!last || item.n > last) {
-                       last = item.n;
+           if (view.scrollToEnd && scrollPos <= 0) {
+               // we use setTimeout to work around scroll handling on touchscreens
+               setTimeout(function() { view.scrollTo(0, Infinity); }, 10);
+           }
+       },
+
+       doLoad: function() {
+           var me = this;
+           var view = me.getView();
+           var viewModel = me.getViewModel();
+           Proxmox.Utils.API2Request({
+               url: me.getView().url,
+               params: viewModel.get('params'),
+               method: 'GET',
+               success: function(response) {
+                   Proxmox.Utils.setErrorMask(me, false);
+                   var total = response.result.total;
+                   var lines = new Array();
+                   var first = Infinity;
+
+                   Ext.Array.each(response.result.data, function(line) {
+                       if (first > line.n) {
+                           first = line.n;
+                       }
+                       lines[line.n - 1] = Ext.htmlEncode(line.t);
+                   });
+
+                   lines.length = total;
+                   me.updateView(lines.join('<br>'), first - 1, total);
+               },
+               failure: function(response) {
+                   if (view.failCallback) {
+                       view.failCallback(response);
+                   } else {
+                       var msg = response.htmlStatus;
+                       Proxmox.Utils.setErrorMask(me, msg);
                    }
-                   text = text + Ext.htmlEncode(item.t) + "<br>";
-               });
-
-               if (first && last && total) {
-                   me.updateView(first -1 , last -1, total, text);
-               } else {
-                   me.updateView(0, 0, 0, '');
                }
-           },
-           failure: function(response) {
-               var msg = response.htmlStatus;
-               Proxmox.Utils.setErrorMask(me, msg);
+           });
+       },
+
+       onScroll: function(x, y) {
+           var me = this;
+           var view = me.getView();
+           var viewModel = me.getViewModel();
+
+           var lineHeight = view.lineHeight;
+           var line = view.getScrollY()/lineHeight;
+           var start = viewModel.get('params.start');
+           var limit = viewModel.get('params.limit');
+           var viewLines = view.getHeight()/lineHeight;
+
+           var viewStart = Math.max(parseInt(line - 1 - view.viewBuffer, 10), 0);
+           var viewEnd = parseInt(line + viewLines + 1 + view.viewBuffer, 10);
+
+           if (viewStart < start || viewEnd > (start+limit)) {
+               viewModel.set('params.start',
+                   Math.max(parseInt(line - limit/2 + 10, 10), 0));
+               view.loadTask.delay(200);
            }
-       });
-    },
+       },
 
-    attemptLoad: function(start) {
-        var me = this;
-        if (!me.loadTask) {
-            me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
-        }
-        me.loadTask.delay(200, me.doAttemptLoad, me, [start]);
-    },
+       init: function(view) {
+           var me = this;
 
-    requestUpdate: function(top, force) {
-       var me = this;
-
-       if (top === undefined) {
-           var target = me.getTargetEl();
-           top = target.dom.scrollTop;
-       }
-
-       var viewStart = parseInt((top / me.lineHeight) - 1, 10);
-       if (viewStart < 0) {
-           viewStart = 0;
-       }
-       var viewEnd = parseInt(((top + me.getHeight())/ me.lineHeight) + 1, 10);
-       var info = me.viewInfo;
-
-       if (info && !force) {
-           if (viewStart >= info.start && viewEnd <= info.end) {
-               return;
+           if (!view.url) {
+               throw "no url specified";
            }
-       }
 
-       var line = parseInt((top / me.lineHeight) - (me.pageSize / 2) + 10, 10);
-       if (line < 0) {
-           line = 0;
-       }
+           var viewModel = this.getViewModel();
+           var since = new Date();
+           since.setDate(since.getDate() - 3);
+           viewModel.set('until', new Date());
+           viewModel.set('since', since);
+           viewModel.set('params.limit', view.pageSize);
+           viewModel.set('hide_timespan', !view.log_select_timespan);
+           me.lookup('content').setStyle('line-height', view.lineHeight + 'px');
+
+           view.loadTask = new Ext.util.DelayedTask(me.doLoad, me);
+
+           me.updateParams();
+           view.task = Ext.TaskManager.start({
+               run: function() {
+                   if (!view.isVisible() || !view.scrollToEnd) {
+                       return;
+                   }
 
-       me.attemptLoad(line);
+                   if (me.scrollPosBottom() <= 1) {
+                       view.loadTask.delay(200);
+                   }
+               },
+               interval: 1000
+           });
+       }
     },
 
-    afterRender: function() {
+    onDestroy: function() {
        var me = this;
-
-        me.callParent(arguments);
-
-       Ext.Function.defer(function() {
-           var target = me.getTargetEl();
-           target.on('scroll',  function(e) {
-               me.requestUpdate();
-           });
-           me.requestUpdate(0);
-       }, 20);
+       me.loadTask.cancel();
+       Ext.TaskManager.stop(me.task);
     },
 
-    initComponent : function() {
-       /*jslint confusion: true */
-
+    // for user to initiate a load from outside
+    requestUpdate: function() {
        var me = this;
+       me.loadTask.delay(200);
+    },
 
-       if (!me.url) {
-           throw "no url specified";
+    viewModel: {
+       data: {
+           until: null,
+           since: null,
+           hide_timespan: false,
+           data: {
+               start: 0,
+               total: 0,
+               textlen: 0
+           },
+           params: {
+               start: 0,
+               limit: 500,
+           }
        }
+    },
 
-       // show logs from today back to 3 days ago per default
-       me.until_date = new Date();
-       me.since_date = new Date();
-       me.since_date.setDate(me.until_date.getDate() - 3);
-
-       me.dataCmp = Ext.create('Ext.Component', {
-           style: 'font:normal 11px tahoma, arial, verdana, sans-serif;' +
-               'line-height: ' + me.lineHeight.toString() + 'px; white-space: pre;'
-       });
-
-       me.task = Ext.TaskManager.start({
-           run: function() {
-               if (!me.isVisible() || !me.scrollToEnd || !me.viewInfo) {
-                   return;
-               }
+    layout: 'auto',
+    bodyPadding: 5,
+    scrollable: {
+       x: 'auto',
+       y: 'auto',
+       listeners: {
+           // we have to have this here, since we cannot listen to events
+           // of the scroller in the viewcontroller (extjs bug?), nor does
+           // the panel have a 'scroll' event'
+           scroll: {
+               fn: function(scroller, x, y) {
+                   var controller = this.component.getController();
+                   if (controller) { // on destroy, controller can be gone
+                       controller.onScroll(x,y);
+                   }
+               },
+               buffer: 200
+           },
+       }
+    },
 
-               var maxDown = me.getMaxDown();
-               if (maxDown > 0) {
-                   return;
+    tbar: {
+       bind: {
+           hidden: '{hide_timespan}'
+       },
+       items: [
+           '->',
+           'Since: ',
+           {
+               xtype: 'datefield',
+               name: 'since_date',
+               reference: 'since',
+               format: 'Y-m-d',
+               bind: {
+                   value: '{since}',
+                   maxValue: '{until}'
                }
-
-               me.requestUpdate(undefined, true);
            },
-           interval: 1000
-       });
-
-       Ext.apply(me, {
-           items: me.dataCmp,
-           listeners: {
-               destroy: function() {
-                   Ext.TaskManager.stop(me.task);
+           'Until: ',
+           {
+               xtype: 'datefield',
+               name: 'until_date',
+               reference: 'until',
+               format: 'Y-m-d',
+               bind: {
+                   value: '{until}',
+                   minValue: '{since}'
                }
+           },
+           {
+               xtype: 'button',
+               text: 'Update',
+               handler: 'updateParams'
            }
-       });
-
-       if (me.log_select_timespan) {
-           me.tbar = ['->','Since: ',
-                      {
-                          xtype: 'datefield',
-                          maxValue: me.until_date,
-                          value: me.since_date,
-                          name: 'since_date',
-                          format: 'Y-m-d',
-                          listeners: {
-                              select: function(field, date) {
-                                  me.since_date_selected = date;
-                                  var until_field = field.up().down('field[name=until_date]');
-                                  if (date > until_field.getValue()) {
-                                      until_field.setValue(date);
-                                  }
-                              }
-                          }
-                      },
-                      'Until: ',
-                      {
-                          xtype: 'datefield',
-                          maxValue: me.until_date,
-                          value: me.until_date,
-                          name: 'until_date',
-                          format: 'Y-m-d',
-                          listeners: {
-                              select: function(field, date) {
-                                  var since_field = field.up().down('field[name=since_date]');
-                                  if (date < since_field.getValue()) {
-                                      since_field.setValue(date);
-                                  }
-                              }
-                          }
-                      },
-                      {
-                          xtype: 'button',
-                          text: 'Update',
-                          handler: function() {
-                              var until_field = me.down('field[name=until_date]');
-                              var since_field = me.down('field[name=since_date]');
-                              if (until_field.getValue() < since_field.getValue()) {
-                                  Ext.Msg.alert('Error',
-                                                'Since date must be less equal than Until date.');
-                                  until_field.setValue(me.until_date);
-                                  since_field.setValue(me.since_date);
-                              } else {
-                                  me.until_date = until_field.getValue();
-                                  me.since_date = since_field.getValue();
-                                  me.requestUpdate();
-                              }
-                          }
-                      }
-                     ];
-       }
-
+       ],
+    },
 
-       me.callParent();
-    }
+    items: [
+       {
+           xtype: 'box',
+           reference: 'content',
+           style: {
+               font: 'normal 11px tahoma, arial, verdana, sans-serif',
+               'white-space': 'pre'
+           },
+       }
+    ]
 });