source: trunk/web/addons/job_monarch/js/monarch.js @ 639

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

job_monarch/js/monarch.js:

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