source: trunk/web2/addons/job_monarch/js/jobgrid.js @ 583

Last change on this file since 583 was 583, checked in by ramonb, 15 years ago

job_monarch/js/jobgrid.js:

  • add a (delector) filter menu (button)
File size: 20.4 KB
Line 
1var JobsDataStore;
2var JobsColumnModel;
3var JobListingEditorGrid;
4var JobListingWindow;
5var JobProxy;
6var SearchField;
7var filterButton;
8var myfilters = { };
9var myparams = { };
10var mylimit = 15;
11var ClusterImageArgs = { };
12
13var filterfields = [ "jid", "queue", "name", "owner" ];
14
15var filterMenu = new Ext.menu.Menu({
16    id: 'filterMenu',
17    items: [ new Ext.menu.Item({ text: 'Clear all', handler: clearFilters }) ]
18});
19
20var filterButton = new Ext.MenuButton({
21                        id: 'filtermenuknop',
22                        text: 'Filters',
23                        menu: filterMenu
24                });
25
26Ext.namespace('Ext.ux');
27
28Ext.ux.PageSizePlugin = function() {
29    Ext.ux.PageSizePlugin.superclass.constructor.call(this, {
30        store: new Ext.data.SimpleStore({
31            fields: ['text', 'value'],
32            data: [['10', 10], ['15', 15], ['20', 20], ['30', 30], ['50', 50], ['100', 100], ['max', 'max' ]]
33        }),
34        mode: 'local',
35        displayField: 'text',
36        valueField: 'value',
37        editable: false,
38        allowBlank: false,
39        triggerAction: 'all',
40        width: 40
41    });
42};
43
44Ext.extend(Ext.ux.PageSizePlugin, Ext.form.ComboBox, {
45    init: function(paging) {
46        paging.on('render', this.onInitView, this);
47    },
48   
49    onInitView: function(paging) {
50        paging.add('-',
51            this,
52            'jobs per page'
53        );
54        this.setValue(paging.pageSize);
55        this.on('select', this.onPageSizeChanged, paging);
56    },
57   
58    onPageSizeChanged: function(combo) {
59        if ( combo.getValue() == 'max' )
60          mylimit = JobsDataStore.getTotalCount();
61        else
62          mylimit = parseInt(combo.getValue());
63        this.pageSize = mylimit;
64        this.doLoad(0);
65    }
66});
67
68Ext.namespace( 'Ext' );
69
70function clearFilters()
71{
72        if( inMyArrayKeys( myfilters, 'host' ) )
73        {
74                delete myfilters['host'];
75                delete myparams['host'];
76        }
77        if( inMyArrayKeys( myfilters, 'jid' ) )
78        {
79                delete myfilters['jid'];
80                delete myparams['jid'];
81        }
82        if( inMyArrayKeys( myfilters, 'queue' ) )
83        {
84                delete myfilters['queue'];
85                delete myparams['queue'];
86        }
87        if( inMyArrayKeys( myfilters, 'owner' ) )
88        {
89                delete myfilters['owner'];
90                delete myparams['owner'];
91        }
92        if( inMyArrayKeys( myfilters, 'status' ) )
93        {
94                delete myfilters['status'];
95                delete myparams['status'];
96        }
97        reloadJobStore();
98}
99
100function makeArrayURL( somearr )
101{
102  filter_url = '';
103  filter_sep = '';
104
105  for( filtername in somearr )
106  {
107    filter_url = filter_url + filter_sep + filtername + '=' + somearr[filtername];
108    filter_sep = '&';
109  }
110
111  return filter_url;
112}
113
114
115function isset( somevar )
116{
117  try
118  {
119    if( eval( somevar ) ) { }
120  }
121  catch( err )
122  {
123    return false;
124  }
125  return true;
126}
127
128function inMyArray( arr, someval )
129{
130  for( arval in arr )
131  {
132    if( arval == someval )
133    {
134      return true;
135    }
136  }
137  return false;
138}
139
140function ArraySize( arr )
141{
142  count = 0;
143
144  for( arkey in arr )
145  {
146    count = count + 1;
147  }
148
149  return count;
150}
151
152function inMyArrayValues( arr, someval )
153{
154  for( arkey in arr )
155  {
156    if( arr[arkey] == someval )
157    {
158      return true;
159    }
160  }
161  return false;
162}
163
164function inMyArrayKeys( arr, someval )
165{
166  for( arkey in arr )
167  {
168    if( arkey == someval )
169    {
170      return true;
171    }
172  }
173  return false;
174}
175
176function joinMyArray( arr1, arr2 )
177{
178  for( arkey in arr2 )
179  {
180    arr1[arkey] = arr2[arkey];
181  }
182
183  return arr1;
184}
185
186function ClusterImageSelectHost( somehost )
187{
188
189  if( !inMyArrayKeys( myfilters, 'host' ) )
190  {
191    myfilters['host'] = somehost;
192  }
193  else
194  {
195    if( myfilters['host'] == somehost )
196    {
197      delete myfilters['host'];
198      delete myparams['host'];
199    }
200    else
201    {
202      myfilters['host'] = somehost;
203    }
204  }
205
206  reloadClusterImage();
207  reloadJobStore();
208
209  return false;
210}
211
212function reloadJobStore()
213{
214  // Respect any other parameters that may have been set outside filters
215  //
216  myparams = joinMyArray( myparams, myfilters );
217
218  // Can't be sure if there are enough pages for new filter: reset to page 1
219  //
220  myparams = joinMyArray( myparams, { start: 0, limit: mylimit } );
221
222  JobsDataStore.reload( { params: myparams } );
223}
224
225function addListener(element, type, expression, bubbling)
226{
227  bubbling = bubbling || false;
228  if(window.addEventListener)
229  { // Standard
230    element.addEventListener(type, expression, bubbling);
231    return true;
232  } 
233  else if(window.attachEvent) 
234  { // IE
235    element.attachEvent('on' + type, expression);
236    return true;
237  } 
238  else 
239    return false;
240}
241
242function makeFilterString()
243{
244  var filter_str = '';
245
246  for( arkey in myfilters )
247  {
248    filter_str = filter_str + ' > ' + myfilters[arkey];
249  }
250
251  return filter_str;
252}
253
254var ImageLoader = function( id, url )
255{
256  this.url = url;
257  this.image = document.getElementById( id );
258  this.loadEvent = null;
259};
260
261ImageLoader.prototype = 
262{
263  load:function()
264  {
265    var url = this.url;
266    var image = this.image;
267    var loadEvent = this.loadEvent;
268    addListener( this.image, 'load', function(e)
269    {
270      if( loadEvent != null )
271      {
272        loadEvent( url, image );
273      }
274    }, false);
275    this.image.src = this.url;
276  },
277  getImage: function()
278  {
279    return this.image;
280  }
281};
282
283function achorJobListing()
284{
285  JobListingWindow.anchorTo( "ClusterImageWindow", "tr-br", [ 0, 10 ] );
286}
287
288function setClusterImagePosition()
289{
290  ci_x = (window.innerWidth - ClusterImageWindow.getSize()['width'] - 20); 
291  ClusterImageWindow.setPosition( ci_x, 10 );
292}
293
294function deselectFilterMenu( menuItem, event )
295{
296  filterValue = menuItem.text;
297
298  for( arkey in myfilters )
299  {
300    if( myfilters[arkey] == filterValue )
301    {
302      delete myfilters[arkey];
303      delete myparams[arkey];
304    }
305  }
306  reloadJobStore();
307}
308
309function makeFilterMenu()
310{
311  var filterMenu = new Ext.menu.Menu({
312      id: 'filterMenu',
313      items: [ new Ext.menu.Item({ text: 'Clear all', handler: clearFilters }) ]
314  });
315
316  if( ArraySize( myfilters ) > 0 )
317  {
318    filterMenu.addSeparator();
319  }
320
321  for( arkey in myfilters )
322  {
323    filterMenu.add( new Ext.menu.CheckItem({ text: myfilters[arkey], handler: deselectFilterMenu, checked: true }) );
324  }
325
326  if( filterButton )
327  {
328    filterButton.menu = filterMenu;
329  }
330}
331
332function reloadClusterImage()
333{
334  ClusterImageArgs['view'] = 'big-clusterimage';
335
336  filt_url = makeArrayURL( myfilters );
337  imag_url = makeArrayURL( ClusterImageArgs );
338  img_url = './image.php?' + filt_url + '&' + imag_url;
339
340  var newClusterImage = new ImageLoader( 'clusterimage', img_url );
341  newClusterImage.loadEvent = function( url, image ) 
342    {
343      ClusterImageWindow.getBottomToolbar().clearStatus( { useDefaults:true } );
344      setTimeout( "resizeClusterImage()", 250 );
345      setTimeout( "setClusterImagePosition()", 500 );
346      //setTimeout( "achorJobListing()", 1000 );
347    }
348
349  ClusterImageWindow.getBottomToolbar().showBusy();
350
351  filter_str = 'Nodes' + makeFilterString();
352  ClusterImageWindow.setTitle( filter_str );
353
354  newClusterImage.load();
355}
356
357function resizeClusterImage()
358{
359  var ci_height = document.getElementById( "clusterimage" ).height + ClusterImageWindow.getFrameHeight();
360  var ci_width = document.getElementById( "clusterimage" ).width + ClusterImageWindow.getFrameWidth();
361
362  ClusterImageWindow.setSize( ci_width, ci_height );
363}
364
365Ext.apply(Ext.form.VTypes, {
366        num: function(val, field) {
367
368                if (val) {
369                   var strValidChars = "0123456789";
370                   var blnResult = true;
371
372                   if (val.length == 0) return false;
373
374                   //  test strString consists of valid characters listed above
375                   for (i = 0; i < val.length && blnResult == true; i++)
376                      {
377                      strChar = val.charAt(i);
378                      if (strValidChars.indexOf(strChar) == -1)
379                         {
380                         blnResult = false;
381                         }
382                      }
383                   return blnResult;
384
385                }
386                },
387        numText: 'Must be numeric'
388});
389
390function initJobGrid() {
391
392  Ext.QuickTips.init();
393
394  function jobCellClick(grid, rowIndex, columnIndex, e)
395  {
396    var record = grid.getStore().getAt(rowIndex);  // Get the Record
397    var fieldName = grid.getColumnModel().getDataIndex(columnIndex);
398    var data = record.get(fieldName);
399    var view = grid.getView();
400    var cell = view.getCell( rowIndex, columnIndex );
401    var filter_title = false;
402    var fil_dis = 'filter';
403    var fil_ena = 'filterenabled';
404    var filterName = fieldName;
405
406    if( fieldName == 'owner' || fieldName == 'jid' || fieldName == 'status' || fieldName == 'queue' || fieldName == 'nodes')
407    {
408      if( fieldName == 'nodes' )
409      {
410        filterName = 'host';
411        fil_dis = 'nodesfilter';
412        fil_ena = 'nodesfilterenabled';
413      }
414      if( inMyArrayKeys( myfilters, filterName ) )
415      {
416        Ext.fly(cell).removeClass( fil_ena );
417        Ext.fly(cell).addClass( fil_dis );
418
419        // Remove this filter
420        //
421        delete myfilters[filterName];
422        delete myparams[filterName];
423
424        reloadJobStore();
425        //reloadClusterImage();
426      }
427      else
428      {
429        Ext.fly(cell).removeClass( fil_dis );
430        Ext.fly(cell).addClass( fil_ena );
431
432        if( fieldName == 'nodes' )
433        { // Get the first node (master mom) as node filter
434          new_data = data.split( ',' )[0];
435          data = new_data;
436        }
437
438        // Set filter for selected column to selected cell value
439        //
440        myfilters[filterName] = data;
441
442        reloadJobStore();
443        //reloadClusterImage();
444      }
445      JobListingWindow.setTitle( filter_str );
446      filter_title = true;
447      filter_str = myparams.c + ' Jobs Overview' + makeFilterString();
448    }
449  }
450
451  function jobCellRender( value, metadata, record, rowindex, colindex, store )
452  {
453    var fieldName = JobsColumnModel.getColumnById( colindex ).dataIndex;
454    var fil_dis = 'filter';
455    var fil_ena = 'filterenabled';
456    var filterName = fieldName;
457
458    if( fieldName == 'owner' || fieldName == 'jid' || fieldName == 'status' || fieldName == 'queue' || fieldName == 'nodes' )
459    {
460      if( fieldName == 'nodes' )
461      {
462        fil_dis = 'nodesfilter';
463        fil_ena = 'nodesfilterenabled';
464        filterName = 'host';
465      }
466      if( myfilters[filterName] != null )
467      {
468        metadata.css = fil_ena;
469      }
470      else
471      {
472        metadata.css = fil_dis;
473      }
474    }
475    return value;
476  }
477
478  JobProxy = new Ext.data.HttpProxy({
479                url: 'jobstore.php',
480                method: 'POST'
481            });
482
483
484  JobsDataStore = new Ext.data.Store({
485      id: 'JobsDataStore',
486      proxy: JobProxy,
487      baseParams: { task: "GETJOBS" },
488      reader: new Ext.data.JsonReader({
489        root: 'results',
490        totalProperty: 'total',
491        id: 'id'
492      },[
493        {name: 'jid', type: 'int', mapping: 'jid'},
494        {name: 'status', type: 'string', mapping: 'status'},
495        {name: 'owner', type: 'string', mapping: 'owner'},
496        {name: 'queue', type: 'string', mapping: 'queue'},
497        {name: 'name', type: 'string', mapping: 'name'},
498        {name: 'requested_time', type: 'string', mapping: 'requested_time'},
499        {name: 'requested_memory', type: 'string', mapping: 'requested_memory'},
500        {name: 'ppn', type: 'int', mapping: 'ppn'},
501        {name: 'nodect', type: 'int', mapping: 'nodect'},
502        {name: 'nodes', type: 'string', mapping: 'nodes'},
503        {name: 'queued_timestamp', type: 'string', mapping: 'queued_timestamp'},
504        {name: 'start_timestamp', type: 'string', mapping: 'start_timestamp'},
505        {name: 'runningtime', type: 'string', mapping: 'runningtime'}
506      ]),
507      sortInfo: { field: 'jid', direction: "DESC" },
508      remoteSort: true,
509      listeners:
510        { 
511                'beforeload':
512                {
513                        scope: this,
514                        fn: function()
515                        {
516                                if( SearchField )
517                                {
518                                        search_value = SearchField.getEl().dom.value;
519                                        if( search_value == '' )
520                                        {
521                                                delete SearchField.store.baseParams['query'];
522                                                delete myfilters['query'];
523                                                delete myparams['query'];
524                                        }
525                                        else
526                                        {
527                                                myfilters['query']      = search_value;
528                                        }
529
530                                        makeFilterMenu();
531                                        reloadClusterImage();
532
533                                        filter_str = myparams.c + ' Jobs Overview' + makeFilterString();
534                                        JobListingWindow.setTitle( filter_str );
535                                }
536                        }
537                } //,
538                //'load':
539                //{
540                //      scope: this,
541                //      fn: function()
542                //      {
543                //              if( SearchField )
544                //              {
545                //                      search_value = SearchField.getEl().dom.value;
546
547                //                      if( search_value != '' )
548                //                      {
549                //                              myfilters['query']      = search_value;
550                //                      }
551
552                //                      reloadClusterImage();
553
554                //                      filter_str = myparams.c + ' Jobs Overview' + makeFilterString();
555                //                      JobListingWindow.setTitle( filter_str );
556
557                //                      if( search_value != '' )
558                //                      {
559                //                              delete myfilters['query'];
560                //                      }
561                //              }
562                //      }
563                //}
564        }
565    });
566   
567  var CheckJobs = new Ext.grid.CheckboxSelectionModel();
568
569  JobsColumnModel = new Ext.grid.ColumnModel(
570    [ CheckJobs,
571    {
572        header: '#',
573        tooltip: 'Job id',
574        readOnly: true,
575        dataIndex: 'jid',
576        width: 50,
577        hidden: false,
578        renderer: jobCellRender
579      },{
580        header: 'S',
581        tooltip: 'Job status',
582        readOnly: true,
583        dataIndex: 'status',
584        width: 20,
585        hidden: false,
586        renderer: jobCellRender
587      },{
588        header: 'User',
589        tooltip: 'Owner of job',
590        readOnly: true,
591        dataIndex: 'owner',
592        width: 60,
593        hidden: false,
594        renderer: jobCellRender
595      },{
596        header: 'Queue',
597        tooltip: 'In which queue does this job reside',
598        readOnly: true,
599        dataIndex: 'queue',
600        width: 60,
601        hidden: false,
602        renderer: jobCellRender
603      },{
604        header: 'Name',
605        tooltip: 'Name of job',
606        readOnly: true,
607        dataIndex: 'name',
608        width: 100,
609        hidden: false
610      },{
611        header: 'Requested Time',
612        tooltip: 'Amount of requested time (wallclock)',
613        readOnly: true,
614        dataIndex: 'requested_time',
615        width: 100,
616        hidden: false
617      },{
618        header: 'Requested Memory',
619        tooltip: 'Amount of requested memory',
620        readOnly: true,
621        dataIndex: 'requested_memory',
622        width: 100,
623        hidden: true
624      },{
625        header: 'P',
626        tooltip: 'Number of processors per node (PPN)',
627        readOnly: true,
628        dataIndex: 'ppn',
629        width: 25,
630        hidden: false
631      },{
632        header: 'N',
633        tooltip: 'Number of nodes (hosts)',
634        readOnly: true,
635        dataIndex: 'nodect',
636        width: 25,
637        hidden: false
638      },{
639        header: 'Nodes',
640        readOnly: true,
641        dataIndex: 'nodes',
642        width: 100,
643        hidden: false,
644        renderer: jobCellRender
645      },{
646        header: 'Queued',
647        tooltip: 'At what time did this job enter the queue',
648        readOnly: true,
649        dataIndex: 'queued_timestamp',
650        width: 120,
651        hidden: false
652      },{
653        header: 'Started',
654        tooltip: 'At what time did this job enter the running status',
655        readOnly: true,
656        dataIndex: 'start_timestamp',
657        width: 120,
658        hidden: false
659      },{
660        header: 'Runningtime',
661        tooltip: 'How long has this job been in the running status',
662        readOnly: true,
663        dataIndex: 'runningtime',
664        width: 140,
665        hidden: false
666      }]
667    );
668    JobsColumnModel.defaultSortable= true;
669
670  var win;
671
672  MetricsDataStore = new Ext.data.Store({
673      id: 'MetricsDataStore',
674      proxy: JobProxy,
675      autoLoad: false,
676      baseParams: { task: "GETMETRICS" },
677      reader: new Ext.data.JsonReader({
678        root: 'names',
679        totalProperty: 'total',
680        id: 'id'
681      },[{
682        name: 'ID'
683      },{
684        name: 'name'
685        }])
686  });
687
688  SearchField   = new Ext.app.SearchField({
689                                store: JobsDataStore,
690                                params: {start: 0, limit: mylimit},
691                                width: 200
692                    });
693
694  NodesDataStore = new Ext.data.Store({
695      id: 'NodesDataStore',
696      proxy: JobProxy,
697      autoLoad: false,
698      baseParams: { task: "GETNODES" },
699      reader: new Ext.data.JsonReader({
700        root: 'results',
701        totalProperty: 'total',
702        id: 'id'
703      },[
704        {name: 'c', type: 'string', mapping: 'c'},
705        {name: 'h', type: 'string', mapping: 'h'},
706        {name: 'x', type: 'string', mapping: 'x'},
707        {name: 'v', type: 'string', mapping: 'v'},
708        {name: 'l', type: 'string', mapping: 'l'},
709        {name: 'jr', type: 'string', mapping: 'jr'},
710        {name: 'js', type: 'string', mapping: 'js'}
711      ]),
712      listeners: {
713                'beforeload': {
714                        scope: this,
715                        fn: function() {
716                                        var jids;
717
718                                        var row_records = CheckJobs.getSelections();
719
720                                        for(var i=0; i<row_records.length; i++ )
721                                        {
722                                                rsel = row_records[i];
723                                                if( !jids )
724                                                {
725                                                        jids = rsel.get('jid');
726                                                }
727                                                else
728                                                {
729                                                        jids = jids + ',' + rsel.get('jid');
730                                                }
731                                        }
732                                        NodesDataStore.baseParams.jids  = jids;
733                                        NodesDataStore.baseParams.c     = myparams.c;
734                        }
735                }
736        }
737    });
738
739function ShowGraphs( Button, Event ) {
740   
741    var GraphView = new Ext.DataView({
742        itemSelector: 'thumb',
743        style:'overflow:auto',
744        multiSelect: true,
745        store: NodesDataStore,
746        tpl: new Ext.XTemplate(
747            '<tpl for=".">',
748            '<div class="rrd-float"><img src="../../graph.php?z=small&c={c}&h={h}&l={l}&v={v}&x={x}&r=job&jr={jr}&js={js}" border="0"></div>',
749            '</tpl>'
750        )
751    });
752
753    var images = new Ext.Panel({
754        id:'images',
755        //title:'My Images',
756        region:'center',
757        bodyStyle: 'background: transparent',
758        //margins: '2 2 2 0',
759        layout:'fit',
760        items: GraphView
761    });
762
763        if(!win){
764            win = new Ext.Window({
765                        animateTarget: Button,
766                        width       : 500,
767                        height      : 300,
768                        closeAction :'hide',
769                        collapsible: true,
770                        animCollapse: true,
771                        maximizable: true,
772                        title:  'Node graph details',
773                        layout: 'fit',
774                        tbar:   new Ext.form.ComboBox({
775                                        fieldLabel: 'Metric',
776                                        //hiddenName:'ID',
777                                        store: MetricsDataStore,
778                                        valueField:'name',
779                                        displayField:'name',
780                                        typeAhead: true,
781                                        mode: 'remote',
782                                        triggerAction: 'all',
783                                        emptyText:'Select metric',
784                                        selectOnFocus:true,
785                                        xtype: 'combo',
786                                        width:190,
787                                        listeners: {
788                                                select: function(combo, record, index){
789                                                        var metric = record.data.name;
790                                                        // doe iets
791                                                }
792                                        }
793                                       
794                                }),
795                        items:  [ images ]
796                    });
797        }
798        NodesDataStore.load();
799        win.show(Button);
800}
801
802
803  JobListingEditorGrid =  new Ext.grid.EditorGridPanel({
804      id: 'JobListingEditorGrid',
805      store: JobsDataStore,
806      cm: JobsColumnModel,
807      enableColLock:false,
808      clicksToEdit:1,
809      loadMask: true,
810      selModel: new Ext.grid.RowSelectionModel({singleSelect:false}),
811      stripeRows: true,
812      sm: CheckJobs,
813      bbar: new Ext.PagingToolbar({
814                pageSize: 15,
815                store: JobsDataStore,
816                displayInfo: true,
817                displayMsg: 'Displaying jobs {0} - {1} out of {2} jobs total found.',
818                emptyMsg: 'No jobs found to display',
819                plugins: [new Ext.ux.PageSizePlugin()]
820            }),
821      tbar: [ SearchField,
822                new Ext.Button({
823                                text: 'Show graphs',
824                                tooltip: 'Show node graphs for selected jobs',
825                                iconCls: 'option',
826                                listeners: {
827                                        'click': {
828                                                scope: this,
829                                                fn: ShowGraphs
830                                        }
831                                }
832                        }),
833                filterButton ]
834    });
835
836  ClusterImageWindow = new Ext.Window({
837      id: 'ClusterImageWindow',
838      title: 'Nodes',
839      closable: true,
840      collapsible: true,
841      animCollapse: true,
842      width: 1,
843      height: 1,
844      y: 15,
845      plain: true,
846      shadow: true,
847      resizable: false,
848      shadowOffset: 10,
849      layout: 'fit',
850      bbar: new Ext.StatusBar({
851                defaultText: 'Ready.',
852                id: 'basic-statusbar',
853                defaultIconCls: ''
854        })
855    });
856
857  GraphSummaryWindow = new Ext.Window({
858      id: 'GraphSummaryWindow',
859      title: 'Graph Summary',
860      closable: true,
861      collapsible: true,
862      animCollapse: true,
863      width: 500,
864      height: 400,
865      x: 10,
866      y: 10,
867      plain: true,
868      shadow: true,
869      resizable: true,
870      shadowOffset: 10,
871      layout: 'table',
872      layoutConfig: {
873                columns: 2
874        },
875      defaults:{border: false},
876      items: [{
877        id: 'monarchlogo',
878        cls: 'monarch',
879        bodyStyle: 'background: transparent',
880        html: '<A HREF="https://subtrac.sara.nl/oss/jobmonarch/" TARGET="_blank"><IMG SRC="./jobmonarch.gif" ALT="Job Monarch" BORDER="0"></A>'
881        //colspan: 2
882       },{
883        id: 'summarycount'
884       },{
885        id: 'rjqjgraph'
886       },{
887        id: 'pie',
888        colspan: 2
889       }],
890      bbar: new Ext.StatusBar({
891                defaultText: 'Ready.',
892                id: 'basic-statusbar',
893                defaultIconCls: ''
894        })
895    });
896
897  JobListingWindow = new Ext.Window({
898      id: 'JobListingWindow',
899      title: 'Cluster Jobs Overview',
900      closable:true,
901      collapsible: true,
902      animCollapse: true,
903      maximizable: true,
904      y: 375,
905      width:860,
906      height:445,
907      plain:true,
908      shadow: true,
909      shadowOffset: 10,
910      layout: 'fit',
911      items: JobListingEditorGrid
912    });
913
914  JobListingEditorGrid.addListener( 'cellclick', jobCellClick );
915}
Note: See TracBrowser for help on using the repository browser.