source: trunk/web2/addons/job_monarch/js/monarch.js @ 604

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

job_monarch/jobstore.php,
job_monarch/graph.php,
job_monarch/js/monarch.js:

  • changed node graph to use own graph.php, since Ganglia's graph.php is broken for jobs
  • correctly set/mark jobstart
  • correctly select time period for job ranges
File size: 23.1 KB
Line 
1var JobsDataStore;
2var JobsColumnModel;
3var JobListingEditorGrid;
4var JobListingWindow;
5var JobProxy;
6var SearchField;
7var filterButton;
8var globalWindowCount = 0;
9
10// Extra header to prevent browser caching
11//
12Ext.Ajax.defaultHeaders =
13{
14        'If-Modified-Since':    'Sat, 1 Jan 2005 00:00:00 GMT'
15};
16
17// associative filter array
18//
19var myfilters = { };
20
21// any other datastore params
22//
23var myparams = { };
24
25// (default) paging size
26//
27var mylimit = 15;
28
29var ClusterImageArgs = { };
30
31var filterfields = [ "jid", "queue", "name", "owner" ];
32
33var graphWindowBehaviour = 'tabbed-new-window';
34var previousGraphWindow;
35
36var filterMenu = new Ext.menu.Menu(
37{
38        id:     'filterMenu',
39        items:  [ new Ext.menu.Item({ text: 'Clear all', handler: clearFilters }) ]
40});
41
42var filterButton = new Ext.MenuButton(
43{
44        id:             'filtermenuknop',
45        text:           'Filters',
46        toolip:         'Click to change filter options',
47        disabled:       true,
48        menu:           filterMenu,
49        listeners:
50        {
51                'click':
52                {
53                        scope:  this,
54                        fn:     function( myButton, event )
55                                {       // immediatly show menu when button is clicked
56                                        myButton.menu.show( myButton.getEl() );
57                                }
58                }
59        }
60});
61
62function checkGraphWindowOption( item, checked )
63{
64        graphWindowBehaviour    = item.id;
65}
66
67var graphMenu = new Ext.menu.Menu(
68{
69        id:     'graphMenu',
70        items:
71        [{
72                id:             'new-window',
73                text:           'Each job in new window',
74                checked:        false,
75                group:          'graphwindow',
76                handler:        checkGraphWindowOption
77        },{
78                id:             'tabbed-new-window',
79                text:           'Each job in a seperate tab, in new window',
80                checked:        true,
81                group:          'graphwindow',
82                handler:        checkGraphWindowOption
83        },{
84                id:             'tabbed-prev-window',
85                text:           'Each job in a seperate tab, in last opened window',
86                checked:        false,
87                group:          'graphwindow',
88                handler:        checkGraphWindowOption
89        }]
90});
91
92var showGraphsButton = new Ext.MenuButton(
93{
94        id:             'showgraphbutton',
95        text:           'Show graphs',
96        disabled:       true,
97        menu:           graphMenu,
98        listeners:
99        {
100                'click':
101                {
102                        scope:  this,
103                        fn:     ShowGraphs
104                }
105        }
106});
107
108Ext.namespace('Ext.ux');
109
110Ext.ux.PageSizePlugin = function()
111{
112        Ext.ux.PageSizePlugin.superclass.constructor.call(this,
113        {
114                store:  new Ext.data.SimpleStore(
115                {
116                        fields: ['text', 'value'],
117                        data:   [['10', 10], ['15', 15], ['20', 20], ['30', 30], ['50', 50], ['100', 100], ['max', 'max' ]]
118                }),
119                mode:           'local',
120                displayField:   'text',
121                valueField:     'value',
122                editable:       false,
123                allowBlank:     false,
124                triggerAction:  'all',
125                width:          40
126        });
127};
128
129Ext.extend(Ext.ux.PageSizePlugin, Ext.form.ComboBox,
130{
131        init:                   function(paging)
132                                {
133                                        paging.on('render', this.onInitView, this);
134                                },
135   
136        onInitView:             function(paging)
137                                {
138                                        paging.add('-',
139                                        this,
140                                        'jobs per page'
141                                        );
142                                        this.setValue(paging.pageSize);
143                                        this.on('select', this.onPageSizeChanged, paging);
144                                },
145
146        onPageSizeChanged:      function(combo)
147                                {
148                                        if ( combo.getValue() == 'max' )
149                                        {
150                                                mylimit = JobsDataStore.getTotalCount();
151                                        }
152                                        else
153                                        {
154                                                mylimit = parseInt(combo.getValue());
155                                        }
156                                        this.pageSize = mylimit;
157                                        this.doLoad(0);
158                                }
159});
160
161Ext.namespace( 'Ext' );
162
163function clearFilters()
164{
165        if( inMyArrayKeys( myfilters, 'query' ) )
166        {
167                SearchField.getEl().dom.value = '';
168                delete SearchField.store.baseParams['query'];
169                delete myfilters['query'];
170                delete myparams['query'];
171        }
172        if( inMyArrayKeys( myfilters, 'host' ) )
173        {
174                delete myfilters['host'];
175                delete myparams['host'];
176        }
177        if( inMyArrayKeys( myfilters, 'jid' ) )
178        {
179                delete myfilters['jid'];
180                delete myparams['jid'];
181        }
182        if( inMyArrayKeys( myfilters, 'queue' ) )
183        {
184                delete myfilters['queue'];
185                delete myparams['queue'];
186        }
187        if( inMyArrayKeys( myfilters, 'owner' ) )
188        {
189                delete myfilters['owner'];
190                delete myparams['owner'];
191        }
192        if( inMyArrayKeys( myfilters, 'status' ) )
193        {
194                delete myfilters['status'];
195                delete myparams['status'];
196        }
197        reloadJobStore();
198}
199
200function makeArrayURL( somearr )
201{
202        filter_url = '';
203        filter_sep = '';
204
205        for( filtername in somearr )
206        {
207                filter_url = filter_url + filter_sep + filtername + '=' + somearr[filtername];
208                filter_sep = '&';
209        }
210
211        return filter_url;
212}
213
214
215function isset( somevar )
216{
217        try
218        {
219                if( eval( somevar ) ) { }
220        }
221        catch( err )
222        {
223                return false;
224        }
225        return true;
226}
227
228function inMyArray( arr, someval )
229{
230        for( arval in arr )
231        {
232                if( arval == someval )
233                {
234                        return true;
235                }
236        }
237        return false;
238}
239
240function ArraySize( arr )
241{
242        count = 0;
243
244        for( arkey in arr )
245        {
246                count = count + 1;
247        }
248
249        return count;
250}
251
252function inMyArrayValues( arr, someval )
253{
254        for( arkey in arr )
255        {
256                if( arr[arkey] == someval )
257                {
258                        return true;
259                }
260        }
261        return false;
262}
263
264function inMyArrayKeys( arr, someval )
265{
266        for( arkey in arr )
267        {
268                if( arkey == someval )
269                {
270                        return true;
271                }
272        }
273        return false;
274}
275
276function joinMyArray( arr1, arr2 )
277{
278        for( arkey in arr2 )
279        {
280                arr1[arkey] = arr2[arkey];
281        }
282
283        return arr1;
284}
285
286function ClusterImageSelectHost( somehost )
287{
288        if( !inMyArrayKeys( myfilters, 'host' ) )
289        {
290                myfilters['host'] = somehost;
291        }
292        else
293        {
294                if( myfilters['host'] == somehost )
295                {
296                        delete myfilters['host'];
297                        delete myparams['host'];
298                }
299                else
300                {
301                        myfilters['host'] = somehost;
302                }
303        }
304
305        reloadClusterImage();
306        reloadJobStore();
307
308        // returning false causes a image reload
309        //
310        return false;
311}
312
313function reloadJobStore()
314{
315        // Respect any other parameters that may have been set outside filters
316        //
317        myparams = joinMyArray( myparams, myfilters );
318
319        // Can't be sure if there are enough pages for new filter: reset to page 1
320        //
321        myparams = joinMyArray( myparams, { start: 0, limit: mylimit } );
322
323        JobsDataStore.reload( { params: myparams } );
324}
325
326function addListener(element, type, expression, bubbling)
327{
328        bubbling = bubbling || false;
329
330        if(window.addEventListener)
331        { // Standard
332                element.addEventListener(type, expression, bubbling);
333                return true;
334        } 
335        else if(window.attachEvent) 
336        { // IE
337                element.attachEvent('on' + type, expression);
338                return true;
339        }
340        else 
341        {
342                return false;
343        }
344}
345
346function makeFilterString()
347{
348        var filter_str = '';
349
350        for( arkey in myfilters )
351        {
352                filter_str = filter_str + ' > ' + myfilters[arkey];
353        }
354
355        return filter_str;
356}
357
358var ImageLoader = function( id, url )
359{
360        this.url = url;
361        this.image = document.getElementById( id );
362        this.loadEvent = null;
363};
364
365ImageLoader.prototype = 
366{
367        load:           function()
368                        {
369                                var url         = this.url;
370                                var image       = this.image;
371                                var loadEvent   = this.loadEvent;
372                                addListener( this.image, 'load',
373                                        function(e)
374                                        {
375                                                if( loadEvent != null )
376                                                {
377                                                        loadEvent( url, image );
378                                                }
379                                        }, false);
380                                this.image.src = this.url;
381                        },
382        getImage:       function()
383                        {
384                                return this.image;
385                        }
386};
387
388function achorJobListing()
389{
390        JobListingWindow.anchorTo( "ClusterImageWindow", "tr-br", [ 0, 10 ] );
391}
392
393function setClusterImagePosition()
394{
395        ci_x = (window.innerWidth - ClusterImageWindow.getSize()['width'] - 20); 
396        ClusterImageWindow.setPosition( ci_x, 10 );
397}
398
399function deselectFilterMenu( menuItem, event )
400{
401        filterValue = menuItem.text;
402
403        if( filterValue == SearchField.getEl().dom.value && inMyArrayKeys( myfilters, 'query' ) )
404        {
405                SearchField.getEl().dom.value = '';
406                delete SearchField.store.baseParams['query'];
407        }
408
409        for( arkey in myfilters )
410        {
411                if( myfilters[arkey] == filterValue )
412                {
413                        delete myfilters[arkey];
414                        delete myparams[arkey];
415                }
416        }
417        reloadJobStore();
418}
419
420function makeFilterMenu()
421{
422        var filterMenu = new Ext.menu.Menu(
423        {
424                id:     'filterMenu',
425                items:  [ new Ext.menu.Item({ text: 'Clear all', handler: clearFilters }) ]
426        });
427
428        if( ArraySize( myfilters ) > 0 )
429        {
430                filterMenu.addSeparator();
431        }
432
433        for( arkey in myfilters )
434        {
435                filterMenu.add( new Ext.menu.CheckItem({ text: myfilters[arkey], handler: deselectFilterMenu, checked: true }) );
436        }
437
438        if( filterButton )
439        {
440                filterButton.menu = filterMenu;
441
442                if( ArraySize( myfilters ) > 0 )
443                {
444                        filterButton.enable();
445                }
446                else
447                {
448                        filterButton.disable();
449                }
450        }
451}
452
453function reloadClusterImage()
454{
455        ClusterImageArgs['view']        = 'big-clusterimage';
456
457        filt_url                        = makeArrayURL( myfilters );
458        imag_url                        = makeArrayURL( ClusterImageArgs );
459        img_url                         = './image.php?' + filt_url + '&' + imag_url;
460
461        var newClusterImage             = new ImageLoader( 'clusterimage', img_url );
462        newClusterImage.loadEvent       = function( url, image ) 
463        {
464                ClusterImageWindow.getBottomToolbar().clearStatus( { useDefaults:true } );
465                setTimeout( "resizeClusterImage()", 250 );
466                setTimeout( "setClusterImagePosition()", 500 );
467                //setTimeout( "achorJobListing()", 1000 );
468        }
469
470        ClusterImageWindow.getBottomToolbar().showBusy();
471
472        filter_str = 'Nodes' + makeFilterString();
473        ClusterImageWindow.setTitle( filter_str );
474
475        newClusterImage.load();
476}
477
478function resizeClusterImage()
479{
480        var ci_height   = document.getElementById( "clusterimage" ).height + ClusterImageWindow.getFrameHeight();
481        var ci_width    = document.getElementById( "clusterimage" ).width + ClusterImageWindow.getFrameWidth();
482
483        ClusterImageWindow.setSize( ci_width, ci_height );
484}
485
486Ext.apply(Ext.form.VTypes,
487{
488        num:            function(val, field)
489                        {
490                                if (val) 
491                                {
492                                        var strValidChars = "0123456789";
493                                        var blnResult = true;
494
495                                        if (val.length == 0) return false;
496
497                                        //  test strString consists of valid characters listed above
498                                        for (i = 0; i < val.length && blnResult == true; i++)
499                                        {
500                                                strChar = val.charAt(i);
501                                                if (strValidChars.indexOf(strChar) == -1)
502                                                {
503                                                        blnResult = false;
504                                                }
505                                        }
506                                        return blnResult;
507
508                                }
509                        },
510        numText:        'Must be numeric'
511});
512
513function jobBeforeRowSelect( mySelectionModel, rowIndex, keepExisting, myRecord )
514{
515        if( myRecord.get('status') == 'Q' )
516        {       // return false: dont select row if queued
517                return false;
518        }
519
520        return true;
521}
522
523function jobRowSelect( mySelectionModel, rowIndex, myRecord ) 
524{
525        if( mySelectionModel.hasSelection() )
526        {
527                showGraphsButton.enable();
528
529                return 0;
530        }
531
532        showGraphsButton.disable();
533}
534
535function jobCellClick(grid, rowIndex, columnIndex, e)
536{
537        var record              = grid.getStore().getAt(rowIndex);  // Get the Record
538        var fieldName           = grid.getColumnModel().getDataIndex(columnIndex);
539        var data                = record.get(fieldName);
540        var view                = grid.getView();
541        var cell                = view.getCell( rowIndex, columnIndex );
542        var filter_title        = false;
543        var fil_dis             = 'filter';
544        var fil_ena             = 'filterenabled';
545        var filterName          = fieldName;
546
547        if( fieldName == 'owner' || fieldName == 'jid' || fieldName == 'status' || fieldName == 'queue' || fieldName == 'nodes')
548        {
549                if( fieldName == 'nodes' )
550                {
551                        filterName      = 'host';
552                        fil_dis         = 'nodesfilter';
553                        fil_ena         = 'nodesfilterenabled';
554                }
555                if( inMyArrayKeys( myfilters, filterName ) )
556                {
557                        Ext.fly(cell).removeClass( fil_ena );
558                        Ext.fly(cell).addClass( fil_dis );
559
560                        // Remove this filter
561                        //
562                        delete myfilters[filterName];
563                        delete myparams[filterName];
564
565                        reloadJobStore();
566                        //reloadClusterImage();
567                }
568                else
569                {
570                        Ext.fly(cell).removeClass( fil_dis );
571                        Ext.fly(cell).addClass( fil_ena );
572
573                        if( fieldName == 'nodes' )
574                        { // Get the first node (master mom) as node filter
575                                new_data = data.split( ',' )[0];
576                                data = new_data;
577                        }
578
579                        // Set filter for selected column to selected cell value
580                        //
581                        myfilters[filterName] = data;
582
583                        reloadJobStore();
584                        //reloadClusterImage();
585                }
586                JobListingWindow.setTitle( filter_str );
587
588                filter_title    = true;
589                filter_str      = myparams.c + ' Jobs Overview' + makeFilterString();
590        }
591}
592
593function jobCellRender( value, metadata, record, rowindex, colindex, store )
594{
595        var fieldName   = JobsColumnModel.getColumnById( colindex ).dataIndex;
596        var fil_dis     = 'filter';
597        var fil_ena     = 'filterenabled';
598        var filterName  = fieldName;
599
600        if( fieldName == 'owner' || fieldName == 'jid' || fieldName == 'status' || fieldName == 'queue' || fieldName == 'nodes' )
601        {
602                if( fieldName == 'nodes' )
603                {
604                        fil_dis         = 'nodesfilter';
605                        fil_ena         = 'nodesfilterenabled';
606                        filterName      = 'host';
607                }
608                if( myfilters[filterName] != null )
609                {
610                        metadata.css    = fil_ena;
611                }
612                else
613                {
614                        metadata.css    = fil_dis;
615                }
616        }
617        return value;
618}
619
620var JobProxy = new Ext.data.HttpProxy(
621{
622        url:            'jobstore.php',
623        method:         'POST'
624});
625
626JobsDataStore = new Ext.data.Store(
627{
628        id:             'JobsDataStore',
629        proxy:          JobProxy,
630        baseParams:     { task: "GETJOBS" },
631        reader:
632                new Ext.data.JsonReader(
633                {
634                        root:           'results',
635                        totalProperty:  'total',
636                        id:             'id'
637                },
638                [
639                        {name: 'jid', type: 'int', mapping: 'jid'},
640                        {name: 'status', type: 'string', mapping: 'status'},
641                        {name: 'owner', type: 'string', mapping: 'owner'},
642                        {name: 'queue', type: 'string', mapping: 'queue'},
643                        {name: 'name', type: 'string', mapping: 'name'},
644                        {name: 'requested_time', type: 'string', mapping: 'requested_time'},
645                        {name: 'requested_memory', type: 'string', mapping: 'requested_memory'},
646                        {name: 'ppn', type: 'int', mapping: 'ppn'},
647                        {name: 'nodect', type: 'int', mapping: 'nodect'},
648                        {name: 'nodes', type: 'string', mapping: 'nodes'},
649                        {name: 'queued_timestamp', type: 'string', mapping: 'queued_timestamp'},
650                        {name: 'start_timestamp', type: 'string', mapping: 'start_timestamp'},
651                        {name: 'runningtime', type: 'string', mapping: 'runningtime'}
652                ]),
653        sortInfo: 
654        { 
655                field:          'jid', 
656                direction:      "DESC" 
657        },
658        remoteSort: true,
659        listeners:
660        { 
661                'beforeload':
662                {
663                        scope: this,
664                        fn:
665
666                        function( myStore, myOptions )
667                        {
668                                // Add a (bogus) timestamp, to create a unique url and prevent browser caching
669                                //
670                                myStore.proxy.url       = 'jobstore.php?timestamp=' + new Date().getTime();
671
672                                if( SearchField )
673                                {
674                                        search_value = SearchField.getEl().dom.value;
675                                        if( search_value == '' )
676                                        {
677                                                delete SearchField.store.baseParams['query'];
678                                                delete myfilters['query'];
679                                                delete myparams['query'];
680                                        }
681                                        else
682                                        {
683                                                myfilters['query']      = search_value;
684                                        }
685
686                                        makeFilterMenu();
687                                        reloadClusterImage();
688
689                                        filter_str = myparams.c + ' Jobs Overview' + makeFilterString();
690                                        JobListingWindow.setTitle( filter_str );
691                                }
692                        }
693                }
694        }
695});
696   
697var CheckJobs =
698
699        new Ext.grid.CheckboxSelectionModel(
700        {
701                listeners:
702                {
703                        'beforerowselect':
704                        {
705                                scope:  this,
706                                fn:     jobBeforeRowSelect
707                        },
708                        'rowselect':
709                        {
710                                scope:  this,
711                                fn:     jobRowSelect
712                        },
713                        'rowdeselect':
714                        {
715                                scope:  this,
716                                fn:     jobRowSelect
717                        }
718                },
719        });
720
721JobsColumnModel = new Ext.grid.ColumnModel(
722[
723        CheckJobs,
724        {
725                header:         '#',
726                tooltip:        'Job id',
727                readOnly:       true,
728                dataIndex:      'jid',
729                width:          50,
730                hidden:         false,
731                renderer:       jobCellRender
732        },{
733                header:         'S',
734                tooltip:        'Job status',
735                readOnly:       true,
736                dataIndex:      'status',
737                width:          20,
738                hidden:         false,
739                renderer:       jobCellRender
740        },{
741                header:         'User',
742                tooltip:        'Owner of job',
743                readOnly:       true,
744                dataIndex:      'owner',
745                width:          60,
746                hidden:         false,
747                renderer:       jobCellRender
748        },{
749                header:         'Queue',
750                tooltip:        'In which queue does this job reside',
751                readOnly:       true,
752                dataIndex:      'queue',
753                width:          60,
754                hidden:         false,
755                renderer:       jobCellRender
756        },{
757                header:         'Name',
758                tooltip:        'Name of job',
759                readOnly:       true,
760                dataIndex:      'name',
761                width:          100,
762                hidden:         false
763        },{
764                header:         'Requested Time',
765                tooltip:        'Amount of requested time (wallclock)',
766                readOnly:       true,
767                dataIndex:      'requested_time',
768                width:          100,
769                hidden:         false
770        },{
771                header:         'Requested Memory',
772                tooltip:        'Amount of requested memory',
773                readOnly:       true,
774                dataIndex:      'requested_memory',
775                width:          100,
776                hidden:         true
777        },{
778                header:         'P',
779                tooltip:        'Number of processors per node (PPN)',
780                readOnly:       true,
781                dataIndex:      'ppn',
782                width:          25,
783                hidden:         false
784        },{
785                header:         'N',
786                tooltip:        'Number of nodes (hosts)',
787                readOnly:       true,
788                dataIndex:      'nodect',
789                width:          25,
790                hidden:         false
791        },{
792                header:         'Nodes',
793                readOnly:       true,
794                dataIndex:      'nodes',
795                width:          100,
796                hidden:         false,
797                renderer:       jobCellRender
798        },{
799                header:         'Queued',
800                tooltip:        'At what time did this job enter the queue',
801                readOnly:       true,
802                dataIndex:      'queued_timestamp',
803                width:          120,
804                hidden:         false
805        },{
806                header:         'Started',
807                tooltip:        'At what time did this job enter the running status',
808                readOnly:       true,
809                dataIndex:      'start_timestamp',
810                width:          120,
811                hidden:         false
812        },{
813                header:         'Runningtime',
814                tooltip:        'How long has this job been in the running status',
815                readOnly:       true,
816                dataIndex:      'runningtime',
817                width:          140,
818                hidden:         false
819        }]
820);
821
822JobsColumnModel.defaultSortable = true;
823
824var win;
825
826MetricsDataStore = new Ext.data.Store(
827{
828        id:             'MetricsDataStore',
829        proxy:          JobProxy,
830        autoLoad:       false,
831        // RB: anto cache store timestamp, dan autoload
832        baseParams:     { task: "GETMETRICS" },
833        reader:
834                new Ext.data.JsonReader(
835                {
836                        root: 'names',
837                        totalProperty: 'total',
838                        id: 'id'
839                },
840                [{
841                        name: 'ID'
842                },{
843                        name: 'name'
844                }]
845                )
846});
847
848SearchField     = new Ext.app.SearchField(
849                {
850                        store:  JobsDataStore,
851                        params: {start: 0, limit: mylimit},
852                        width:  200
853                });
854
855function createNodesDataStore( cluster, jid )
856{
857        nodesDataStore =
858
859                new Ext.data.Store(
860                {
861                        //id:           'NodesDataStore',
862                        proxy:          new Ext.data.HttpProxy(
863                        {
864                                url:            'jobstore.php',
865                                method:         'POST'
866                        }),
867                        autoLoad:       true,
868                        baseParams:
869                        {
870                                'task':                 "GETNODES",
871                                'c':                    cluster,
872                                'jid':                  jid
873                        },
874                        reader: new Ext.data.JsonReader(
875                        {
876                                root:           'results',
877                                totalProperty:  'total',
878                                id:             'id'
879                        },[
880                                {name: 'jid', type: 'string', mapping: 'jid'},
881                                {name: 'ga', type: 'string', mapping: 'ga'}
882                        ]),
883                        listeners:
884                        { 
885                                'beforeload':
886                                {
887                                        scope: this,
888                                        fn:
889
890                                        function( myStore, myOptions )
891                                        {
892                                                // Add a (bogus) timestamp, to create a unique url and prevent browser caching
893                                                //
894                                                myStore.proxy.url       = 'jobstore.php?timestamp=' + new Date().getTime();
895                                        }
896                                }
897                        }
898
899                });
900
901        return nodesDataStore;
902}
903
904function createGraphView( store, jid )
905{
906        var graphView =
907       
908                new Ext.DataView(
909                {
910                        id:             jid,   
911                        itemSelector:   'thumb',
912                        title:          jid,
913                        style:          'overflow:auto',
914                        multiSelect:    true,
915                        autoHeight:     true,
916                        autoShow:       true,
917                        //autoScroll:   true,
918                        loadMask:       true,
919                        store:          store,
920                        layout:         'fit',
921                        closable:       true,
922                        tpl:
923                       
924                                new Ext.XTemplate(
925                                        '<tpl for=".">',
926                                        '<div class="rrd-float"><a href="./graph.php?z=large&{ga}" border="0" rel="lightbox[{jid}.{[globalWindowCount]}]"><img src="./graph.php?z=small&{ga}" border="0"></a></div>',
927                                        '</tpl>'
928                                )
929                });
930
931        return graphView;
932}
933
934function createGraphPanel( view )
935{
936        var graphPanel = 
937
938                new Ext.TabPanel(
939                {
940                        id:             'tabPanel',
941                        region:         'center',
942                        bodyStyle:      'background: transparent',
943                        autoShow:       true,
944                        autoHeight:     true,
945                        autoWidth:      true,
946                        autoScroll:     true,
947                        resizeTabs:     true,
948                        minTabWidth:    60,
949                        //tabWidth:     135,
950                        //closeable:    true,
951                        enableTabScroll:true,
952                        resizeTabs:     true,
953                        // RB TODO: range combobox; hour, day, week, etc
954
955                        tbar:
956                        [
957                                new Ext.form.ComboBox(
958                                {
959                                        fieldLabel:     'Metric',
960                                        store:          MetricsDataStore,
961                                        valueField:     'name',
962                                        displayField:   'name',
963                                        typeAhead:      true,
964                                        mode:           'remote',
965                                        triggerAction:  'all',
966                                        emptyText:      'load_one',
967                                        selectOnFocus:  true,
968                                        xtype:          'combo',
969                                        width:          190,
970                                        myview:         view,
971                                        listeners:
972                                        {
973                                                select: 
974                                                               
975                                                function(combo, record, index)
976                                                {
977                                                        var metric = record.data.name;
978                                                        // doe iets
979
980                                                        //this.myview.getStore().baseParams.metricname  = metric;
981                                                        //this.myview.refresh();
982                                                        // RB: misschien zo metric opgeven aan datastore?
983                                                        //items[0].items[0].getStore().baseParams.metric = metric;
984                                                }
985                                        }
986                                })
987                        ]
988                });
989
990        return graphPanel;
991}
992
993function createGraphWindow( panel, Button )
994{
995        graphWindow =
996
997                new Ext.Window(
998                {
999                        animateTarget:  Button,
1000                        width:          500,
1001                        height:         300,
1002                        closeAction:    'hide',
1003                        collapsible:    true,
1004                        animCollapse:   true,
1005                        maximizable:    true,
1006                        //autoScroll:   true,
1007                        //defaults:     {autoScroll:true},
1008                        title:          'Node graph details',
1009                        tbar:           panel,
1010               
1011                        listeners:
1012                        {
1013                                resize:
1014
1015                                function(  myWindow, width, height )
1016                                {
1017                                        var myPanel     = myWindow.items.get( 'tabPanel' );
1018                                        var myView      = myPanel.getActiveTab();
1019
1020                                        myPanel.doLayout();
1021                                        myWindow.doLayout();
1022                                }
1023                        }
1024                });
1025
1026        return graphWindow;
1027}
1028
1029function ShowGraphs( Button, Event ) 
1030{
1031        var row_records         = CheckJobs.getSelections();
1032        var graphJids           = Array();
1033        var windowCount         = 0;
1034        var tabCount            = 0;
1035
1036        for( var i=0; i<row_records.length; i++ )
1037        {
1038                rsel            = row_records[i];
1039                jid             = rsel.get('jid');
1040
1041                if( graphJids[windowCount] == undefined )
1042                {
1043                        graphJids[windowCount]  = Array();
1044                }
1045
1046                graphJids[windowCount][tabCount]        = jid;
1047
1048                if( (i+1) < row_records.length )
1049                {
1050                        if( graphWindowBehaviour == 'new-window' )
1051                        {
1052                                windowCount++;
1053                        }
1054                        else
1055                        {
1056                                tabCount++;
1057                        }
1058                }
1059        }
1060
1061        for( var w=0; w<=windowCount; w++ )
1062        {
1063                if( ( graphWindowBehaviour == 'tabbed-prev-window' ) && ( previousGraphWindow != null ) && ( previousGraphPanel != null ) )
1064                {
1065                        myWindow        = previousGraphWindow;
1066                        myPanel         = previousGraphPanel;
1067                }
1068                else
1069                {
1070                        myPanel         = createGraphPanel();
1071                        myWindow        = createGraphWindow( myPanel, Button );
1072
1073                        myWindow.add( myPanel );
1074
1075                        globalWindowCount++;
1076                }
1077
1078                for( var t=0; t<=tabCount; t++ )
1079                {
1080                        nodeDatastore   = createNodesDataStore( myparams.c, graphJids[w][t] );
1081                        graphView       = createGraphView( nodeDatastore, graphJids[w][t] );
1082
1083                        nodeDatastore.removeAll();
1084
1085                        lastView        = myPanel.add( graphView );
1086
1087                        myPanel.doLayout();
1088                }
1089
1090                myPanel.setActiveTab( lastView );
1091
1092                myWindow.show( Button );
1093                myWindow.doLayout();
1094
1095                previousGraphWindow     = myWindow;
1096                previousGraphPanel      = myPanel;
1097        }
1098}
1099
1100var JobListingEditorGrid =
1101
1102        new Ext.grid.EditorGridPanel(
1103        {
1104                id:             'JobListingEditorGrid',
1105                store:          JobsDataStore,
1106                cm:             JobsColumnModel,
1107                enableColLock:  false,
1108                clicksToEdit:   1,
1109                loadMask:       true,
1110                selModel:       new Ext.grid.RowSelectionModel( { singleSelect: false } ),
1111                stripeRows:     true,
1112                sm:             CheckJobs,
1113                listeners:
1114                {
1115                        'cellclick':
1116                        {
1117                                scope:  this,
1118                                fn:     jobCellClick
1119                        }
1120                },
1121                bbar:
1122       
1123                new Ext.PagingToolbar(
1124                {
1125                        pageSize:       15,
1126                        store:          JobsDataStore,
1127                        displayInfo:    true,
1128                        displayMsg:     'Displaying jobs {0} - {1} out of {2} jobs total found.',
1129                        emptyMsg:       'No jobs found to display',
1130                        plugins:        [ new Ext.ux.PageSizePlugin() ]
1131                }),
1132
1133                tbar: 
1134                [ 
1135                        SearchField,
1136                        showGraphsButton,
1137                        filterButton 
1138                ]
1139        });
1140
1141var ClusterImageWindow =
1142
1143        new Ext.Window(
1144        {
1145                id:             'ClusterImageWindow',
1146                title:          'Nodes',
1147                closable:       true,
1148                collapsible:    true,
1149                animCollapse:   true,
1150                width:          1,
1151                height:         1,
1152                y:              15,
1153                plain:          true,
1154                shadow:         true,
1155                resizable:      false,
1156                shadowOffset:   10,
1157                layout:         'fit',
1158                bbar: 
1159               
1160                        new Ext.StatusBar(
1161                        {
1162                                defaultText:    'Ready.',
1163                                id:             'basic-statusbar',
1164                                defaultIconCls: ''
1165                        })
1166        });
1167
1168var GraphSummaryWindow =
1169
1170        new Ext.Window(
1171        {
1172                id:             'GraphSummaryWindow',
1173                title:          'Graph Summary',
1174                closable:       true,
1175                collapsible:    true,
1176                animCollapse:   true,
1177                width:          500,
1178                height:         400,
1179                x:              10,
1180                y:              10,
1181                plain:          true,
1182                shadow:         true,
1183                resizable:      true,
1184                shadowOffset:   10,
1185                layout:         'table',
1186                layoutConfig: 
1187                {
1188                        columns: 2
1189                },
1190                defaults:       { border: false },
1191                items: 
1192                [
1193                        {
1194                                id:             'monarchlogo',
1195                                cls:            'monarch',
1196                                bodyStyle:      'background: transparent',
1197                                html:           '<A HREF="https://subtrac.sara.nl/oss/jobmonarch/" TARGET="_blank"><IMG SRC="./jobmonarch.gif" ALT="Job Monarch" BORDER="0"></A>'
1198                                //colspan: 2
1199                        },{
1200                                id:             'summarycount'
1201                        },{
1202                                id:             'rjqjgraph'
1203                        },{
1204                                id:             'pie',
1205                                colspan:        2
1206                        }
1207                ],
1208                bbar:
1209               
1210                        new Ext.StatusBar(
1211                        {
1212                                defaultText:    'Ready.',
1213                                id:             'basic-statusbar',
1214                                defaultIconCls: ''
1215                        })
1216        });
1217
1218var JobListingWindow =
1219
1220        new Ext.Window(
1221        {
1222                id:             'JobListingWindow',
1223                title:          'Cluster Jobs Overview',
1224                closable:       true,
1225                collapsible:    true,
1226                animCollapse:   true,
1227                maximizable:    true,
1228                y:              375,
1229                width:          860,
1230                height:         445,
1231                plain:          true,
1232                shadow:         true,
1233                shadowOffset:   10,
1234                layout:         'fit',
1235                items:          JobListingEditorGrid
1236        });
Note: See TracBrowser for help on using the repository browser.