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

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

web2/.../js/jobgrid.js:

  • cleanup
  • added checkbox selection model
  • added show nodes popup button
File size: 13.6 KB
Line 
1var JobsDataStore;
2var JobsColumnModel;
3var JobListingEditorGrid;
4var JobListingWindow;
5var JobProxy;
6var myfilters = { };
7var myparams = { };
8var mylimit = 15;
9var ClusterImageArgs = { };
10
11var filterfields = [ "jid", "queue", "name", "owner" ];
12
13Ext.namespace('Ext.ux');
14
15Ext.ux.PageSizePlugin = function() {
16    Ext.ux.PageSizePlugin.superclass.constructor.call(this, {
17        store: new Ext.data.SimpleStore({
18            fields: ['text', 'value'],
19            data: [['10', 10], ['15', 15], ['20', 20], ['30', 30], ['50', 50], ['100', 100]]
20        }),
21        mode: 'local',
22        displayField: 'text',
23        valueField: 'value',
24        editable: false,
25        allowBlank: false,
26        triggerAction: 'all',
27        width: 40
28    });
29};
30
31Ext.extend(Ext.ux.PageSizePlugin, Ext.form.ComboBox, {
32    init: function(paging) {
33        paging.on('render', this.onInitView, this);
34    },
35   
36    onInitView: function(paging) {
37        paging.add('-',
38            this,
39            'jobs per page'
40        );
41        this.setValue(paging.pageSize);
42        this.on('select', this.onPageSizeChanged, paging);
43    },
44   
45    onPageSizeChanged: function(combo) {
46        mylimit = parseInt(combo.getValue());
47        this.pageSize = mylimit;
48        this.doLoad(0);
49    }
50});
51
52Ext.namespace( 'Ext' );
53
54function makeArrayURL( somearr )
55{
56  filter_url = '';
57  filter_sep = '';
58
59  for( filtername in somearr )
60  {
61    filter_url = filter_url + filter_sep + filtername + '=' + somearr[filtername];
62    filter_sep = '&';
63  }
64
65  return filter_url;
66}
67
68
69function isset( somevar )
70{
71  try
72  {
73    if( eval( somevar ) ) { }
74  }
75  catch( err )
76  {
77    return false;
78  }
79  return true;
80}
81
82function inMyArray( arr, someval )
83{
84  for( arval in arr )
85  {
86    if( arval == someval )
87    {
88      return true;
89    }
90  }
91  return false;
92}
93
94function inMyArrayValues( arr, someval )
95{
96  for( arkey in arr )
97  {
98    if( arr[arkey] == someval )
99    {
100      return true;
101    }
102  }
103  return false;
104}
105
106function inMyArrayKeys( arr, someval )
107{
108  for( arkey in arr )
109  {
110    if( arkey == someval )
111    {
112      return true;
113    }
114  }
115  return false;
116}
117
118function joinMyArray( arr1, arr2 )
119{
120  for( arkey in arr2 )
121  {
122    arr1[arkey] = arr2[arkey];
123  }
124
125  return arr1;
126}
127
128function ClusterImageSelectHost( somehost )
129{
130
131  if( !inMyArrayKeys( myfilters, 'host' ) )
132  {
133    myfilters['host'] = somehost;
134  }
135  else
136  {
137    delete myfilters['host'];
138    delete myparams['host'];
139  }
140
141  reloadClusterImage();
142  reloadJobStore();
143
144  return false;
145}
146
147function reloadJobStore()
148{
149  // Respect any other parameters that may have been set outside filters
150  //
151  myparams = joinMyArray( myparams, myfilters );
152
153  // Can't be sure if there are enough pages for new filter: reset to page 1
154  //
155  myparams = joinMyArray( myparams, { start: 0, limit: mylimit } );
156
157  JobsDataStore.reload( { params: myparams } );
158}
159
160function addListener(element, type, expression, bubbling)
161{
162  bubbling = bubbling || false;
163  if(window.addEventListener)
164  { // Standard
165    element.addEventListener(type, expression, bubbling);
166    return true;
167  } 
168  else if(window.attachEvent) 
169  { // IE
170    element.attachEvent('on' + type, expression);
171    return true;
172  } 
173  else 
174    return false;
175}
176
177var ImageLoader = function( id, url )
178{
179  this.url = url;
180  this.image = document.getElementById( id );
181  this.loadEvent = null;
182};
183
184ImageLoader.prototype = 
185{
186  load:function()
187  {
188    var url = this.url;
189    var image = this.image;
190    var loadEvent = this.loadEvent;
191    addListener( this.image, 'load', function(e)
192    {
193      if( loadEvent != null )
194      {
195        loadEvent( url, image );
196      }
197    }, false);
198    this.image.src = this.url;
199  },
200  getImage: function()
201  {
202    return this.image;
203  }
204};
205
206function achorJobListing()
207{
208  JobListingWindow.anchorTo( "ClusterImageWindow", "tr-br", [ 0, 10 ] );
209}
210
211function setClusterImagePosition()
212{
213  ci_x = (window.innerWidth - ClusterImageWindow.getSize()['width'] - 20); 
214  ClusterImageWindow.setPosition( ci_x, 10 );
215}
216
217function reloadClusterImage()
218{
219  ClusterImageArgs['view'] = 'big-clusterimage';
220
221  filt_url = makeArrayURL( myfilters );
222  imag_url = makeArrayURL( ClusterImageArgs );
223  img_url = './image.php?' + filt_url + '&' + imag_url;
224
225  var newClusterImage = new ImageLoader( 'clusterimage', img_url );
226  newClusterImage.loadEvent = function( url, image ) 
227    {
228      ClusterImageWindow.getBottomToolbar().clearStatus( { useDefaults:true } );
229      setTimeout( "resizeClusterImage()", 250 );
230      setTimeout( "setClusterImagePosition()", 500 );
231      setTimeout( "achorJobListing()", 1000 );
232    }
233
234  ClusterImageWindow.getBottomToolbar().showBusy();
235  newClusterImage.load();
236}
237
238function resizeClusterImage()
239{
240  var ci_height = document.getElementById( "clusterimage" ).height + ClusterImageWindow.getFrameHeight();
241  var ci_width = document.getElementById( "clusterimage" ).width + ClusterImageWindow.getFrameWidth();
242
243  ClusterImageWindow.setSize( ci_width, ci_height );
244}
245
246Ext.apply(Ext.form.VTypes, {
247        num: function(val, field) {
248
249                if (val) {
250                   var strValidChars = "0123456789";
251                   var blnResult = true;
252
253                   if (val.length == 0) return false;
254
255                   //  test strString consists of valid characters listed above
256                   for (i = 0; i < val.length && blnResult == true; i++)
257                      {
258                      strChar = val.charAt(i);
259                      if (strValidChars.indexOf(strChar) == -1)
260                         {
261                         blnResult = false;
262                         }
263                      }
264                   return blnResult;
265
266                }
267                },
268        numText: 'Must be numeric'
269});
270
271function initJobGrid() {
272
273  Ext.QuickTips.init();
274
275  function jobCellClick(grid, rowIndex, columnIndex, e)
276  {
277    var record = grid.getStore().getAt(rowIndex);  // Get the Record
278    var fieldName = grid.getColumnModel().getDataIndex(columnIndex);
279    var data = record.get(fieldName);
280    var view = grid.getView();
281    var cell = view.getCell( rowIndex, columnIndex );
282
283    if( fieldName == 'owner' || fieldName == 'jid' || fieldName == 'status' || fieldName == 'queue' )
284    {
285      if( inMyArrayKeys( myfilters, fieldName ) )
286      {
287        Ext.fly(cell).removeClass( 'filterenabled' );
288        Ext.fly(cell).addClass( 'filter' );
289
290        // Remove this filter
291        //
292        delete myfilters[fieldName];
293        delete myparams[fieldName];
294
295        reloadJobStore();
296        reloadClusterImage();
297      }
298      else
299      {
300        Ext.fly(cell).removeClass( 'filter' );
301        Ext.fly(cell).addClass( 'filterenabled' );
302
303        // Set filter for selected column to selected cell value
304        //
305        myfilters[fieldName] = data;
306
307        reloadJobStore();
308        reloadClusterImage();
309      }
310    }
311  }
312
313  function jobCellRender( value, metadata, record, rowindex, colindex, store )
314  {
315    var fieldName = JobsColumnModel.getColumnById( colindex ).dataIndex;
316
317    if( fieldName == 'owner' || fieldName == 'jid' || fieldName == 'status' || fieldName == 'queue' )
318    {
319      if( myfilters[fieldName] != null )
320      {
321        metadata.css = 'filterenabled';
322      }
323      else
324      {
325        metadata.css = 'filter';
326      }
327    }
328    return value;
329  }
330
331  JobProxy = new Ext.data.HttpProxy({
332                url: 'jobstore.php',
333                method: 'POST'
334            });
335
336  JobsDataStore = new Ext.data.Store({
337      id: 'JobsDataStore',
338      proxy: JobProxy,
339      baseParams: { task: "LISTING" },
340      reader: new Ext.data.JsonReader({
341        root: 'results',
342        totalProperty: 'total',
343        id: 'id'
344      },[
345        {name: 'jid', type: 'int', mapping: 'jid'},
346        {name: 'status', type: 'string', mapping: 'status'},
347        {name: 'owner', type: 'string', mapping: 'owner'},
348        {name: 'queue', type: 'string', mapping: 'queue'},
349        {name: 'name', type: 'string', mapping: 'name'},
350        {name: 'requested_time', type: 'string', mapping: 'requested_time'},
351        {name: 'requested_memory', type: 'string', mapping: 'requested_memory'},
352        {name: 'ppn', type: 'int', mapping: 'ppn'},
353        {name: 'nodect', type: 'int', mapping: 'nodect'},
354        {name: 'nodes', type: 'string', mapping: 'nodes'},
355        {name: 'queued_timestamp', type: 'string', mapping: 'queued_timestamp'},
356        {name: 'start_timestamp', type: 'string', mapping: 'start_timestamp'},
357        {name: 'runningtime', type: 'string', mapping: 'runningtime'}
358      ]),
359      sortInfo: { field: 'jid', direction: "DESC" },
360      remoteSort: true
361    });
362   
363  var CheckJobs = new Ext.grid.CheckboxSelectionModel();
364
365  JobsColumnModel = new Ext.grid.ColumnModel(
366    [ CheckJobs,
367    {
368        header: '#',
369        tooltip: 'Job id',
370        readOnly: true,
371        dataIndex: 'jid',
372        width: 50,
373        hidden: false,
374        renderer: jobCellRender
375      },{
376        header: 'S',
377        tooltip: 'Job status',
378        readOnly: true,
379        dataIndex: 'status',
380        width: 20,
381        hidden: false,
382        renderer: jobCellRender
383      },{
384        header: 'User',
385        tooltip: 'Owner of job',
386        readOnly: true,
387        dataIndex: 'owner',
388        width: 60,
389        hidden: false,
390        renderer: jobCellRender
391      },{
392        header: 'Queue',
393        tooltip: 'In which queue does this job reside',
394        readOnly: true,
395        dataIndex: 'queue',
396        width: 60,
397        hidden: false,
398        renderer: jobCellRender
399      },{
400        header: 'Name',
401        tooltip: 'Name of job',
402        readOnly: true,
403        dataIndex: 'name',
404        width: 100,
405        hidden: false
406      },{
407        header: 'Requested Time',
408        tooltip: 'Amount of requested time (wallclock)',
409        readOnly: true,
410        dataIndex: 'requested_time',
411        width: 100,
412        hidden: false
413      },{
414        header: 'Requested Memory',
415        tooltip: 'Amount of requested memory',
416        readOnly: true,
417        dataIndex: 'requested_memory',
418        width: 100,
419        hidden: true
420      },{
421        header: 'P',
422        tooltip: 'Number of processors per node (PPN)',
423        readOnly: true,
424        dataIndex: 'ppn',
425        width: 25,
426        hidden: false
427      },{
428        header: 'N',
429        tooltip: 'Number of nodes (hosts)',
430        readOnly: true,
431        dataIndex: 'nodect',
432        width: 25,
433        hidden: false
434      },{
435        header: 'Nodes',
436        readOnly: true,
437        dataIndex: 'nodes',
438        width: 100,
439        hidden: true
440      },{
441        header: 'Queued',
442        tooltip: 'At what time did this job enter the queue',
443        readOnly: true,
444        dataIndex: 'queued_timestamp',
445        width: 120,
446        hidden: false
447      },{
448        header: 'Started',
449        tooltip: 'At what time did this job enter the running status',
450        readOnly: true,
451        dataIndex: 'start_timestamp',
452        width: 120,
453        hidden: false
454      },{
455        header: 'Runningtime',
456        tooltip: 'How long has this job been in the running status',
457        readOnly: true,
458        dataIndex: 'runningtime',
459        width: 140,
460        hidden: false
461      }]
462    );
463    JobsColumnModel.defaultSortable= true;
464
465  var win;
466
467  JobListingEditorGrid =  new Ext.grid.EditorGridPanel({
468      id: 'JobListingEditorGrid',
469      store: JobsDataStore,
470      cm: JobsColumnModel,
471      enableColLock:false,
472      clicksToEdit:1,
473      loadMask: true,
474      selModel: new Ext.grid.RowSelectionModel({singleSelect:false}),
475      stripeRows: true,
476      sm: CheckJobs,
477      bbar: new Ext.PagingToolbar({
478                pageSize: 15,
479                store: JobsDataStore,
480                displayInfo: true,
481                displayMsg: 'Displaying jobs {0} - {1} out of {2} jobs total found.',
482                emptyMsg: 'No jobs found to display',
483                plugins: [new Ext.ux.PageSizePlugin()]
484            }),
485      tbar: [ new Ext.app.SearchField({
486                                store: JobsDataStore,
487                                params: {start: 0, limit: mylimit},
488                                width: 200
489                    }),
490                new Ext.Button({
491                                text: 'Show nodes',
492                                tooltip: 'Show nodes for selected jobs',
493                                iconCls: 'option',
494                                listeners: {
495                                        'click': {
496                                                scope: this,
497                                                fn: function() {
498                                                        if(!win){
499                                                                    win = new Ext.Window({
500                                                                        width       : 500,
501                                                                        height      : 300,
502                                                                        closeAction :'hide',
503                                                                    });
504                                                        }
505                                                        win.show( this );
506                                                }
507                                        }
508                                }
509                        })
510      ]
511    });
512
513  ClusterImageWindow = new Ext.Window({
514      id: 'ClusterImageWindow',
515      title: 'Nodes',
516      closable: true,
517      collapsible: true,
518      animCollapse: true,
519      width: 1,
520      height: 1,
521      y: 15,
522      plain: true,
523      shadow: true,
524      resizable: false,
525      shadowOffset: 10,
526      layout: 'fit',
527      bbar: new Ext.StatusBar({
528                defaultText: 'Ready.',
529                id: 'basic-statusbar',
530                defaultIconCls: ''
531        })
532    });
533
534  GraphSummaryWindow = new Ext.Window({
535      id: 'GraphSummaryWindow',
536      title: 'Graph Summary',
537      closable: true,
538      collapsible: true,
539      animCollapse: true,
540      width: 300,
541      height: 500,
542      x: 10,
543      y: 10,
544      plain: true,
545      shadow: true,
546      resizable: true,
547      shadowOffset: 10,
548      layout: 'table',
549      layoutConfig: {
550                columns: 2
551        },
552      defaults:{border: false},
553      items: [{
554        id: 'monarchlogo',
555        cls: 'monarch',
556        bodyStyle: 'background: transparent',
557        html: '<A HREF="https://subtrac.sara.nl/oss/jobmonarch/" TARGET="_blank"><IMG SRC="./jobmonarch.gif" ALT="Job Monarch" BORDER="0"></A>'
558        //colspan: 2
559       },{
560        id: 'summarycount'
561       },{
562        id: 'rjqjgraph'
563       },{
564        id: 'pie',
565        colspan: 2
566       }],
567      bbar: new Ext.StatusBar({
568                defaultText: 'Ready.',
569                id: 'basic-statusbar',
570                defaultIconCls: ''
571        })
572    });
573
574  JobListingWindow = new Ext.Window({
575      id: 'JobListingWindow',
576      title: 'Cluster Jobs Overview',
577      closable:true,
578      collapsible: true,
579      animCollapse: true,
580      maximizable: true,
581      y: 375,
582      width:860,
583      height:427,
584      plain:true,
585      shadow: true,
586      shadowOffset: 10,
587      layout: 'fit',
588      items: JobListingEditorGrid
589    });
590
591  JobListingEditorGrid.addListener( 'cellclick', jobCellClick );
592}
Note: See TracBrowser for help on using the repository browser.