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

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

web2/addons/job_monarch/js/jobgrid.js:

  • added changeable page size
File size: 13.3 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        this.pageSize = parseInt(combo.getValue());
47        mylimit = parseInt(combo.getValue());
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: 30 } );
156  //mylimit = JobListingEditorGrid.bbar.pageSize;
157  myparams = joinMyArray( myparams, { start: 0, limit: mylimit } );
158
159  JobsDataStore.reload( { params: myparams } );
160}
161
162function addListener(element, type, expression, bubbling)
163{
164  bubbling = bubbling || false;
165  if(window.addEventListener)
166  { // Standard
167    element.addEventListener(type, expression, bubbling);
168    return true;
169  } 
170  else if(window.attachEvent) 
171  { // IE
172    element.attachEvent('on' + type, expression);
173    return true;
174  } 
175  else 
176    return false;
177}
178
179var ImageLoader = function( id, url )
180{
181  this.url = url;
182  this.image = document.getElementById( id );
183  this.loadEvent = null;
184};
185
186ImageLoader.prototype = 
187{
188  load:function()
189  {
190    var url = this.url;
191    var image = this.image;
192    var loadEvent = this.loadEvent;
193    addListener( this.image, 'load', function(e)
194    {
195      if( loadEvent != null )
196      {
197        loadEvent( url, image );
198      }
199    }, false);
200    this.image.src = this.url;
201  },
202  getImage: function()
203  {
204    return this.image;
205  }
206};
207
208function achorJobListing()
209{
210  JobListingWindow.anchorTo( "ClusterImageWindow", "tr-br", [ 0, 10 ] );
211}
212
213function setClusterImagePosition()
214{
215  ci_x = (window.innerWidth - ClusterImageWindow.getSize()['width'] - 20); 
216  ClusterImageWindow.setPosition( ci_x, 10 );
217}
218
219function reloadClusterImage()
220{
221  ClusterImageArgs['view'] = 'big-clusterimage';
222
223  filt_url = makeArrayURL( myfilters );
224  imag_url = makeArrayURL( ClusterImageArgs );
225  img_url = './image.php?' + filt_url + '&' + imag_url;
226
227  var newClusterImage = new ImageLoader( 'clusterimage', img_url );
228  newClusterImage.loadEvent = function( url, image ) 
229    {
230      ClusterImageWindow.getBottomToolbar().clearStatus( { useDefaults:true } );
231      setTimeout( "resizeClusterImage()", 250 );
232      setTimeout( "setClusterImagePosition()", 500 );
233      setTimeout( "achorJobListing()", 1000 );
234    }
235
236  ClusterImageWindow.getBottomToolbar().showBusy();
237  newClusterImage.load();
238}
239
240function resizeClusterImage()
241{
242  var ci_height = document.getElementById( "clusterimage" ).height + ClusterImageWindow.getFrameHeight();
243  var ci_width = document.getElementById( "clusterimage" ).width + ClusterImageWindow.getFrameWidth();
244
245  ClusterImageWindow.setSize( ci_width, ci_height );
246}
247
248Ext.apply(Ext.form.VTypes, {
249        num: function(val, field) {
250
251                if (val) {
252                   var strValidChars = "0123456789";
253                   var blnResult = true;
254
255                   if (val.length == 0) return false;
256
257                   //  test strString consists of valid characters listed above
258                   for (i = 0; i < val.length && blnResult == true; i++)
259                      {
260                      strChar = val.charAt(i);
261                      if (strValidChars.indexOf(strChar) == -1)
262                         {
263                         blnResult = false;
264                         }
265                      }
266                   return blnResult;
267
268                }
269                },
270        numText: 'Must be numeric'
271});
272
273function initJobGrid() {
274
275  Ext.QuickTips.init();
276  Ext.form.Field.prototype.msgTarget = 'side';
277
278  function jobCellClick(grid, rowIndex, columnIndex, e)
279  {
280    var record = grid.getStore().getAt(rowIndex);  // Get the Record
281    var fieldName = grid.getColumnModel().getDataIndex(columnIndex);
282    var data = record.get(fieldName);
283    var view = grid.getView();
284    var cell = view.getCell( rowIndex, columnIndex );
285
286    if( fieldName == 'owner' || fieldName == 'jid' || fieldName == 'status' || fieldName == 'queue' )
287    {
288      if( inMyArrayKeys( myfilters, fieldName ) )
289      {
290        Ext.fly(cell).removeClass( 'filterenabled' );
291        Ext.fly(cell).addClass( 'filter' );
292
293        // Remove this filter
294        //
295        delete myfilters[fieldName];
296        delete myparams[fieldName];
297
298        reloadJobStore();
299        reloadClusterImage();
300      }
301      else
302      {
303        Ext.fly(cell).removeClass( 'filter' );
304        Ext.fly(cell).addClass( 'filterenabled' );
305
306        // Set filter for selected column to selected cell value
307        //
308        myfilters[fieldName] = data;
309
310        reloadJobStore();
311        reloadClusterImage();
312      }
313    }
314  }
315
316  function jobCellRender( value, metadata, record, rowindex, colindex, store )
317  {
318    var fieldName = JobsColumnModel.getColumnById( colindex ).dataIndex;
319
320    if( fieldName == 'owner' || fieldName == 'jid' || fieldName == 'status' || fieldName == 'queue' )
321    {
322      if( myfilters[fieldName] != null )
323      {
324        metadata.css = 'filterenabled';
325      }
326      else
327      {
328        metadata.css = 'filter';
329      }
330    }
331    return value;
332  }
333
334  JobProxy = new Ext.data.HttpProxy({
335                url: 'jobstore.php',
336                method: 'POST'
337            });
338
339  JobsDataStore = new Ext.data.Store({
340      id: 'JobsDataStore',
341      proxy: JobProxy,
342      baseParams: { task: "LISTING" },
343      reader: new Ext.data.JsonReader({
344        root: 'results',
345        totalProperty: 'total',
346        id: 'id'
347      },[
348        {name: 'jid', type: 'int', mapping: 'jid'},
349        {name: 'status', type: 'string', mapping: 'status'},
350        {name: 'owner', type: 'string', mapping: 'owner'},
351        {name: 'queue', type: 'string', mapping: 'queue'},
352        {name: 'name', type: 'string', mapping: 'name'},
353        {name: 'requested_time', type: 'string', mapping: 'requested_time'},
354        {name: 'requested_memory', type: 'string', mapping: 'requested_memory'},
355        {name: 'ppn', type: 'int', mapping: 'ppn'},
356        {name: 'nodect', type: 'int', mapping: 'nodect'},
357        {name: 'nodes', type: 'string', mapping: 'nodes'},
358        {name: 'queued_timestamp', type: 'string', mapping: 'queued_timestamp'},
359        {name: 'start_timestamp', type: 'string', mapping: 'start_timestamp'},
360        {name: 'runningtime', type: 'string', mapping: 'runningtime'}
361      ]),
362      sortInfo: { field: 'jid', direction: "DESC" },
363      remoteSort: true
364    });
365   
366  JobsColumnModel = new Ext.grid.ColumnModel(
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  JobListingEditorGrid =  new Ext.grid.EditorGridPanel({
466      id: 'JobListingEditorGrid',
467      store: JobsDataStore,
468      cm: JobsColumnModel,
469      enableColLock:false,
470      clicksToEdit:1,
471      loadMask: true,
472      selModel: new Ext.grid.RowSelectionModel({singleSelect:false}),
473      stripeRows: true,
474      bbar: new Ext.PagingToolbar({
475                pageSize: 15,
476                store: JobsDataStore,
477                displayInfo: true,
478                displayMsg: 'Displaying jobs {0} - {1} out of {2} jobs total found.',
479                emptyMsg: 'No jobs found to display',
480                plugins: [new Ext.ux.PageSizePlugin()]
481            }),
482      tbar: [ new Ext.app.SearchField({
483                                store: JobsDataStore,
484                                params: {start: 0, limit: mylimit},
485                                width: 200
486                    })
487      ]
488    });
489
490  ClusterImageWindow = new Ext.Window({
491      id: 'ClusterImageWindow',
492      title: 'Nodes',
493      closable: true,
494      collapsible: true,
495      animCollapse: true,
496      width: 1,
497      height: 1,
498      y: 15,
499      plain: true,
500      shadow: true,
501      resizable: false,
502      shadowOffset: 10,
503      layout: 'fit',
504      bbar: new Ext.StatusBar({
505                defaultText: 'Ready.',
506                id: 'basic-statusbar',
507                defaultIconCls: '',
508        })
509
510    });
511
512  GraphSummaryWindow = new Ext.Window({
513      id: 'GraphSummaryWindow',
514      title: 'Graph Summary',
515      closable: true,
516      collapsible: true,
517      animCollapse: true,
518      width: 300,
519      height: 500,
520      x: 10,
521      y: 10,
522      plain: true,
523      shadow: true,
524      resizable: true,
525      shadowOffset: 10,
526      layout: 'table',
527      layoutConfig: {
528                columns: 2
529        },
530      defaults:{border: false},
531      items: [{
532        id: 'monarchlogo',
533        cls: 'monarch',
534        bodyStyle: 'background: transparent',
535        html: '<A HREF="https://subtrac.sara.nl/oss/jobmonarch/" TARGET="_blank"><IMG SRC="./jobmonarch.gif" ALT="Job Monarch" BORDER="0"></A>'
536        //colspan: 2
537       },{
538        id: 'summarycount'
539       },{
540        id: 'rjqjgraph'
541       },{
542        id: 'pie',
543        colspan: 2
544       }],
545      bbar: new Ext.StatusBar({
546                defaultText: 'Ready.',
547                id: 'basic-statusbar',
548                defaultIconCls: ''
549        })
550    });
551
552  JobListingWindow = new Ext.Window({
553      id: 'JobListingWindow',
554      title: 'Cluster Jobs Overview',
555      closable:true,
556      collapsible: true,
557      animCollapse: true,
558      maximizable: true,
559      y: 375,
560      width:860,
561      height:500,
562      plain:true,
563      shadow: true,
564      shadowOffset: 10,
565      layout: 'fit',
566      items: JobListingEditorGrid
567    });
568
569  JobListingEditorGrid.addListener( 'cellclick', jobCellClick );
570}
Note: See TracBrowser for help on using the repository browser.