]> git.sur5r.net Git - bacula/bacula/blob - gui/bweb/html/bresto.js
ebl Add time slice selection for job overview
[bacula/bacula] / gui / bweb / html / bresto.js
1
2 //   Bweb - A Bacula web interface
3 //   Bacula® - The Network Backup Solution
4 //
5 //   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
6 //
7 //   The main author of Bweb is Eric Bollengier.
8 //   The main author of Bacula is Kern Sibbald, with contributions from
9 //   many others, a complete list can be found in the file AUTHORS.
10 //
11 //   This program is Free Software; you can redistribute it and/or
12 //   modify it under the terms of version two of the GNU General Public
13 //   License as published by the Free Software Foundation plus additions
14 //   that are listed in the file LICENSE.
15 //
16 //   This program is distributed in the hope that it will be useful, but
17 //   WITHOUT ANY WARRANTY; without even the implied warranty of
18 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 //   General Public License for more details.
20 //
21 //   You should have received a copy of the GNU General Public License
22 //   along with this program; if not, write to the Free Software
23 //   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 //   02110-1301, USA.
25 //
26 //   Bacula® is a registered trademark of John Walker.
27 //   The licensor of Bacula is the Free Software Foundation Europe
28 //   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zurich,
29 //   Switzerland, email:ftf@fsfeurope.org.
30
31 // render if vol is online/offline
32 function rd_vol_is_online(val)
33 {
34    return '<img src="/bweb/inflag' + val + '.png">';
35 }
36
37 // TODO: fichier ou rep
38 function rd_file_or_dir(val)
39 {
40    if (val == 'F') {
41       return '<img src="/bweb/A.png">';
42    } else {
43       return '<img src="/bweb/R.png">';
44    }
45 }
46
47 Ext.namespace('Ext.brestore');
48
49 Ext.brestore.jobid=0;            // selected jobid
50 Ext.brestore.jobdate='';         // selected date
51 Ext.brestore.client='';          // selected client
52 Ext.brestore.rclient='';         // selected client for resto
53 Ext.brestore.storage='';         // selected storage for resto
54 Ext.brestore.path='';            // current path (without user location)
55 Ext.brestore.root_path='';       // user location
56
57 Ext.brestore.option_vosb = false;
58 Ext.brestore.option_vafv = false;
59 Ext.brestore.dlglaunch;
60 Ext.BLANK_IMAGE_URL = '/bweb/ext/resources/images/aero/s.gif';  // 1.1
61
62 function get_node_path(node)
63 {
64    var temp='';
65    for (var p = node; p; p = p.parentNode) {
66        if (p.parentNode) {
67           if (p.text == '/') {
68              temp = p.text + temp;
69           } else {
70           temp = p.text + '/' + temp;
71           }
72        }
73    }
74    return Ext.brestore.root_path + temp;
75 }
76
77
78 function init_params(baseParams)
79 {
80    baseParams['client']= Ext.brestore.client;
81
82    if (Ext.brestore.option_vosb) {         
83       baseParams['jobid'] = Ext.brestore.jobid;
84    } else {
85       baseParams['date'] = Ext.brestore.jobdate;
86    }
87    return baseParams;
88 }
89
90
91 function ext_init()
92 {
93 //////////////////////////////////////////////////////////////:
94     var Tree = Ext.tree;
95     var tree_loader = new Ext.tree.TreeLoader({
96             baseParams:{}, 
97             dataUrl:'/cgi-bin/bweb/bresto.pl'
98         });
99
100     var tree = new Ext.tree.TreePanel('div-tree', {
101         animate:true, 
102         loader: tree_loader,
103         enableDD:true,
104         enableDragDrop: true,
105         containerScroll: true
106     });
107
108     // set the root node
109     var root = new Ext.tree.AsyncTreeNode({
110         text: 'Select a client then a job',
111         draggable:false,
112         id:'source'
113     });
114     tree.setRootNode(root);
115     Ext.brestore.tree = root;
116
117     // render the tree
118     tree.render();
119 //    root.expand();
120
121     tree.on('click', function(node, event) { 
122         Ext.brestore.path = get_node_path(node);
123         where_field.setValue(Ext.brestore.path);
124         file_store.removeAll();
125         file_versions_store.removeAll();
126         file_store.load({params:init_params({action: 'list_files',
127                                              node:node.id})
128                        });
129         return true;
130     });
131
132     tree.on('beforeload', function(e) {
133         file_store.removeAll();
134         return true;
135     });
136
137
138 ////////////////////////////////////////////////////////////////
139
140   var file_store = new Ext.data.Store({
141         proxy: new Ext.data.HttpProxy({
142             url: '/cgi-bin/bweb/bresto.pl',
143             method: 'GET',
144             params:{}
145         }),
146
147         reader: new Ext.data.ArrayReader({
148         }, Ext.data.Record.create([
149    {name: 'fileid'    },
150    {name: 'filenameid'},
151    {name: 'pathid'    },
152    {name: 'jobid'     },
153    {name: 'name'      },
154    {name: 'size',     type: 'int'  },
155    {name: 'mtime',    type: 'date', dateFormat: 'Y-m-d h:i:s'}
156         ]))
157    });
158
159    var cm = new Ext.grid.ColumnModel([{
160            id:        'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
161            header:    'File',
162            dataIndex: 'name',
163            width:     100,
164            css:       'white-space:normal;'
165         },{
166            header:    "Size",
167            dataIndex: 'size',
168            renderer:  human_size,
169            width:     50
170         },{
171            header:    "Date",
172            dataIndex: 'mtime',
173            width:     100
174         },{
175            dataIndex: 'pathid',
176            hidden: true
177         },{
178            dataIndex: 'filenameid',
179            hidden: true
180         },{
181            dataIndex: 'fileid',
182            hidden: true
183         },{
184            dataIndex: 'jobid',
185            hidden: true
186         }
187         ]);
188
189     // by default columns are sortable
190    cm.defaultSortable = true;
191
192     // create the grid
193    var files_grid = new Ext.grid.Grid('div-files', {
194         ds: file_store,
195         cm: cm,
196         ddGroup : 'TreeDD',
197         enableDrag: true,
198         enableDragDrop: true,
199         selModel: new Ext.grid.RowSelectionModel(),
200         loadMask: true,
201         enableColLock:false
202         
203     });
204
205     // when we reload the view,
206     // we clear the file version box
207     file_store.on('beforeload', function(e) {
208         file_versions_store.removeAll();
209         return true;
210     });
211
212     // TODO: selection only when using dblclick
213     files_grid.selModel.on('rowselect', function(e,i,r) { 
214         Ext.brestore.filename = r.json[3];
215         file_versions_store.load({params:init_params({action: 'list_versions',
216                                                      vafv: Ext.brestore.option_vafv,
217                                                      pathid: r.json[2],
218                                                      filenameid: r.json[1]
219                                                      })
220                                  });
221         return true;
222     });
223     files_grid.render();
224
225 //////////////////////////////////////////////////////////////:
226
227   var file_selection_store = new Ext.data.Store({
228         proxy: new Ext.data.MemoryProxy(),
229
230         reader: new Ext.data.ArrayReader({
231         }, Ext.data.Record.create([
232    {name: 'jobid'     },
233    {name: 'fileid'    },
234    {name: 'filenameid'},
235    {name: 'pathid'    },
236    {name: 'name'      },
237    {name: 'size',     type: 'int'  },
238    {name: 'mtime',    type: 'date', dateFormat: 'Y-m-d h:i:s'}
239         ]))
240    });
241
242    var file_selection_cm = new Ext.grid.ColumnModel([{
243            id:        'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
244            header:    "Name",
245            dataIndex: 'name',
246            width:     250
247         },{
248            header:    "JobId",
249            width:     50,
250            dataIndex: 'jobid'
251         },{
252            header:    "Size",
253            dataIndex: 'size',
254            renderer:  human_size,
255            width:     50
256         },{
257            header:    "Date",
258            dataIndex: 'mtime',
259            width:     100
260         },{
261            dataIndex: 'pathid',
262            header: 'PathId'
263 //           hidden: true
264         },{
265            dataIndex: 'filenameid',
266            hidden: true
267         },{
268            dataIndex: 'fileid',
269            header: 'FileId'
270 //           hidden: true
271         }
272         ]);
273
274
275     // create the grid
276    var file_selection_grid = new Ext.grid.Grid('div-file-selection', {
277         cm: file_selection_cm,
278         ds: file_selection_store,
279         ddGroup : 'TreeDD',
280         enableDrag: false,
281         enableDrop: true,
282         selModel: new Ext.grid.RowSelectionModel(),
283         loadMask: true,
284         enableColLock:false
285         
286     });
287
288     var file_selection_record = Ext.data.Record.create(
289       {name: 'jobid'},
290       {name: 'fileid'},
291       {name: 'filenameid'},
292       {name: 'pathid'},
293       {name: 'size'},
294       {name: 'mtime'}
295     );
296 // data.selections[0].json[]
297 // data.node.id
298 // http://extjs.com/forum/showthread.php?t=12582&highlight=drag+drop
299     var ddrow = new Ext.dd.DropTarget(file_selection_grid.container, {
300         ddGroup : 'TreeDD',
301         copy:false,
302         notifyDrop : function(dd, e, data){
303            var r;
304            if (data.selections) {
305              if (data.grid.id == 'div-files') {
306                  for(var i=0;i<data.selections.length;i++) {
307                     r = new file_selection_record({
308                       jobid:     data.selections[0].json[3],
309                       fileid:    data.selections[i].json[0],
310                       filenameid:data.selections[i].json[1],
311                       pathid:    data.selections[i].json[2],
312                       name: Ext.brestore.path + data.selections[i].json[4],
313                       size:      data.selections[i].json[5],
314                       mtime:     data.selections[i].json[6]
315                     });
316                     file_selection_store.add(r)
317                  }
318              }
319
320              if (data.grid.id == 'div-file-versions') {
321                     r = new file_selection_record({
322                       jobid:     data.selections[0].json[3],
323                       fileid:    data.selections[0].json[0],
324                       filenameid:data.selections[0].json[1],
325                       pathid:    data.selections[0].json[2],
326                       name: Ext.brestore.path + Ext.brestore.filename,
327                       size:      data.selections[0].json[7],
328                       mtime:     data.selections[0].json[8]     
329                     });
330                     file_selection_store.add(r)
331              }
332            }
333   
334            if (data.node) {
335               var path= get_node_path(data.node);
336               r = new file_selection_record({
337                       jobid:     data.node.attributes.jobid,
338                       fileid:    0,
339                       filenameid:0,
340                       pathid:    data.node.id,
341                       name:      path,
342                       size:      4096,
343                       mtime:     0
344               });
345               file_selection_store.add(r)
346            }
347   
348            return true;
349     }});
350
351
352    file_selection_grid.on('enddrag', function(dd,e) { 
353         alert(e) ; return true;
354     });
355    file_selection_grid.on('notifyDrop', function(dd,e) { 
356         alert(e) ; return true;
357     });
358    file_selection_grid.render();
359
360 ///////////////////////////////////////////////////////
361
362   var file_versions_store = new Ext.data.Store({
363         proxy: new Ext.data.HttpProxy({
364             url: '/cgi-bin/bweb/bresto.pl',
365             method: 'GET',
366             params:{offset:0, limit:50 }
367         }),
368
369         reader: new Ext.data.ArrayReader({
370         }, Ext.data.Record.create([
371    {name: 'fileid'    },
372    {name: 'filenameid'},
373    {name: 'pathid'    },
374    {name: 'jobid'     },
375    {name: 'volume'    },
376    {name: 'inchanger' },
377    {name: 'md5'       },
378    {name: 'size',     type: 'int'  },
379    {name: 'mtime'} //,    type: 'date', dateFormat: 'Y-m-d h:i:s'}
380         ]))
381    });
382
383    var file_versions_cm = new Ext.grid.ColumnModel([{
384            id:        'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
385            dataIndex: 'name',
386            hidden: true
387         },{
388            header:    "InChanger",
389            dataIndex: 'inchanger',
390            width:     60,
391            renderer:  rd_vol_is_online
392         },{
393            header:    "Volume",
394            dataIndex: 'volume'
395         },{
396            header:    "JobId",
397            width:     50,
398            dataIndex: 'jobid'
399         },{
400            header:    "Size",
401            dataIndex: 'size',
402            renderer:  human_size,
403            width:     50
404         },{
405            header:    "Date",
406            dataIndex: 'mtime',
407            width:     100
408         },{
409            header:    "MD5",
410            dataIndex: 'md5',
411            width:     160
412         },{
413            dataIndex: 'pathid',
414            hidden: true
415         },{
416            dataIndex: 'filenameid',
417            hidden: true
418         },{
419            dataIndex: 'fileid',
420            hidden: true
421         }
422    ]);
423
424     // by default columns are sortable
425    file_versions_cm.defaultSortable = true;
426
427     // create the grid
428    var file_versions_grid = new Ext.grid.Grid('div-file-versions', {
429         ds: file_versions_store,
430         cm: file_versions_cm,
431         ddGroup : 'TreeDD',
432         enableDrag: true,
433         enableDrop: false,
434         selModel: new Ext.grid.RowSelectionModel(),
435         loadMask: true,
436         enableColLock:false
437         
438     });
439
440     file_versions_grid.on('rowdblclick', function(e) { 
441         alert(e) ; file_versions_store.removeAll(); return true;
442     });
443     file_versions_grid.render();
444
445 //////////////////////////////////////////////////////////////:
446
447
448     var client_store = new Ext.data.Store({
449         proxy: new Ext.data.HttpProxy({
450             url: '/cgi-bin/bweb/bresto.pl',
451             method: 'GET',
452             params:{action:'list_client'}
453         }),
454
455         reader: new Ext.data.ArrayReader({
456         }, Ext.data.Record.create([
457            {name: 'name' }
458         ]))
459     });
460
461     var client_combo = new Ext.form.ComboBox({
462         fieldLabel: 'Clients',
463         store: client_store,
464         displayField:'name',
465         typeAhead: true,
466         mode: 'local',
467         triggerAction: 'all',
468         emptyText:'Select a client...',
469         selectOnFocus:true,
470         forceSelection: true,
471         width:135
472     });
473
474     client_combo.on('valid', function(e) { 
475         Ext.brestore.client = e.getValue();
476         Ext.brestore.jobid=0;
477         Ext.brestore.jobdate = '';
478         Ext.brestore.root_path='';
479         job_combo.clearValue();
480         file_store.removeAll();
481         file_versions_store.removeAll();
482         root.collapse(false, false);
483         while(root.firstChild){
484             root.removeChild(root.firstChild);
485         }
486         job_store.load( {params:{action: 'list_job',
487                                  client:Ext.brestore.client}});
488         return true;
489     });
490
491 //////////////////////////////////////////////////////////////:
492
493     var job_store = new Ext.data.Store({
494         proxy: new Ext.data.HttpProxy({
495             url: '/cgi-bin/bweb/bresto.pl',
496             method: 'GET',
497             params:{offset:0, limit:50 }
498         }),
499
500         reader: new Ext.data.ArrayReader({
501         }, Ext.data.Record.create([
502            {name: 'jobid' },
503            {name: 'date'  },
504            {name: 'jobname' }
505         ]))
506     });
507
508     var job_combo = new Ext.form.ComboBox({
509         fieldLabel: 'Jobs',
510         store: job_store,
511         displayField:'jobname',
512         typeAhead: true,
513         mode: 'local',
514         triggerAction: 'all',
515         emptyText:'Select a job...',
516         selectOnFocus:true,
517         forceSelection: true,
518         width:350
519     });
520
521     job_combo.on('select', function(e,c) {
522         Ext.brestore.jobid = c.json[0];
523         Ext.brestore.jobdate = c.json[1];
524         Ext.brestore.root_path='';
525         root.setText("Root");
526         tree_loader.baseParams = init_params({init:1, action: 'list_dirs'});
527         root.reload();
528     });
529
530 ////////////////////////////////////////////////////////////////
531
532     function sel_option(item, check)
533     {
534         if (item.id == 'id_vosb') {
535            Ext.brestore.option_vosb = check;
536         }
537         if (item.id == 'id_vafv') {
538            Ext.brestore.option_vafv = check;
539         }
540     }
541
542     var menu = new Ext.menu.Menu({
543         id: 'div-main-menu',
544         items: [ 
545            new Ext.menu.CheckItem({
546                 id: 'id_vosb',
547                 text: 'View only selected backup',
548                 checked: Ext.brestore.option_vosb,
549                 checkHandler: sel_option
550             }),
551            new Ext.menu.CheckItem({
552                 id: 'id_vafv',
553                 text: 'View all file versions',
554                 checked: Ext.brestore.option_vafv,
555                 checkHandler: sel_option
556             })
557         ]
558     });
559 ////////////////////////////////////////////////////////////////:
560
561     // create the primary toolbar
562     var tb2 = new Ext.Toolbar('div-tb-sel');
563
564     var where_field = new Ext.form.TextField({
565             fieldLabel: 'Location',
566             name: 'where',
567             width:175,
568             allowBlank:false
569     });
570
571     var tb = new Ext.Toolbar('div-toolbar', [
572         client_combo,
573         job_combo,
574         '-',
575         {
576           id: 'tb_home',
577 //        icon: '/bweb/up.gif',
578           text: 'Change location',
579           cls:'x-btn-text-icon',
580           handler: function() { 
581                 var where = where_field.getValue();
582                 Ext.brestore.root_path=where;
583                 root.setText(where);
584                 tree_loader.baseParams = init_params({ action:'list_dirs', path: where });
585                 root.reload();
586           }
587         },
588         where_field,
589         '-',
590         {
591             cls: 'x-btn-text-icon bmenu', // icon and text class
592             text:'Options',
593             menu: menu  // assign menu by instance
594         },
595         {
596             icon: '/bweb/remove.png', // icons can also be specified inline
597             cls: 'x-btn-icon',
598             text: 'restore',
599             handler: function() { 
600                 if (Ext.brestore.dlglaunch) {
601                    Ext.brestore.dlglaunch.show();
602                    return 0;
603                 }
604                 Ext.brestore.dlglaunch = new Ext.LayoutDialog("div-resto-dlg", {
605 //                        modal:true,
606                         width:600,
607                         height:400,
608                         shadow:true,
609                         minWidth:300,
610                         minHeight:300,
611                         proxyDrag: true,
612 //                        west: {
613 //                              split:true,
614 //                              initialSize: 150,
615 //                              minSize: 100,
616 //                              maxSize: 250,
617 //                              titlebar: true,
618 //                              collapsible: true,
619 //                              animate: true
620 //                          },
621                         center: {
622                                 autoScroll:true,
623 //                              tabPosition: 'top',
624 //                              closeOnTab: true,
625 //                              alwaysShowTabs: true
626                         }
627                 });
628
629     var fs = new Ext.form.Form({
630         labelAlign: 'right',
631         labelWidth: 80
632     });
633
634 //    var resto_store = new Ext.data.Store({
635 //        proxy: new Ext.data.HttpProxy({
636 //            url: '/cgi-bin/bweb/bresto.pl',
637 //            method: 'GET',
638 //            params:{action:'list_resto'}
639 //        }),
640 //
641 //        reader: new Ext.data.ArrayReader({
642 //        }, Ext.data.Record.create([
643 //           {name: 'name' }
644 //        ]))
645 //    });
646
647     var rclient_combo = new Ext.form.ComboBox({
648             value: Ext.brestore.client,
649             fieldLabel: 'client',
650             hiddenName:'client',
651             store: client_store,
652             displayField:'name',
653             typeAhead: true,
654             mode: 'local',
655             triggerAction: 'all',
656             emptyText:'Select a client...',
657             selectOnFocus:true,
658             width:190
659         });
660     var where_text = new Ext.form.TextField({
661             fieldLabel: 'Where',
662             name: 'where',
663             value: '/tmp/bacula-restore',
664             width:190
665         });
666     var storage_store = new Ext.data.Store({
667         proxy: new Ext.data.HttpProxy({
668             url: '/cgi-bin/bweb/bresto.pl',
669             method: 'GET',
670             params:{action:'list_storage'}
671         }),
672
673         reader: new Ext.data.ArrayReader({
674         }, Ext.data.Record.create([
675            {name: 'name' }
676         ]))
677     });
678     var storage_combo = new Ext.form.ComboBox({
679             fieldLabel: 'storage',
680             hiddenName:'storage',
681             store: storage_store,
682             displayField:'name',
683             typeAhead: true,
684             mode: 'local',
685             triggerAction: 'all',
686             emptyText:'Select a storage...',
687             selectOnFocus:true,
688             width:190
689         });
690     fs.fieldset(
691         {legend:'Restore job'},
692 //        new Ext.form.ComboBox({
693 //            fieldLabel: 'Replace',
694 //            hiddenName:'replace',
695 //            store: new Ext.data.SimpleStore({
696 //               fields: ['replace'],
697 //               data : [['always'],['never'],['if newer']]
698 //          }),
699 //            displayField:'replace',
700 //            typeAhead: true,
701 //            mode: 'local',
702 //            triggerAction: 'all',
703 //            emptyText:'never',
704 //            selectOnFocus:true,
705 //            width:190
706 //        }),
707 //
708 //        new Ext.form.ComboBox({
709 //            fieldLabel: 'job',
710 //            hiddenName:'job',
711 //            store: resto_store,
712 //            displayField:'name',
713 //            typeAhead: true,
714 //            mode: 'local',
715 //            triggerAction: 'all',
716 //            emptyText:'Select a job...',
717 //            selectOnFocus:true,
718 //            width:190
719 //        }),
720
721         rclient_combo,
722         where_text,
723         storage_combo
724     );
725     storage_store.load({params:{action: 'list_storage'}});
726 //  resto_store.load({params:{action: 'list_resto'}});
727     fs.render('div-resto-form');
728
729 //      var f = new Ext.form.BasicForm('div-resto-form', {url: '/bweb/test', method: 'GET',
730 //                                                      baseParams: {init: 1}
731 //                                                     }
732 //                                     );
733
734     var launch_restore = function() {
735         var items = file_selection_store.data.items;
736         var tab_fileid=new Array();
737         var tab_dirid=new Array();
738         var tab_jobid=new Array();
739         for(var i=0;i<items.length;i++) {
740                 if (items[i].data['fileid']) {
741                         tab_fileid.push(items[i].data['fileid']);
742                 } else {
743                         tab_dirid.push(items[i].data['pathid']);
744                 }
745                 tab_jobid.push(items[i].data['jobid']);
746         }
747         var res = ';fileid=' + tab_fileid.join(";fileid=");
748         var res2 = ';dirid=' + tab_dirid.join(";dirid=");
749         var res3 = ';jobid=' + tab_jobid.join(";jobid=");
750
751         var res4 = ';client=' + rclient_combo.getValue() + ';storage=' + storage_combo.getValue() + ';where=' + where_text.getValue();
752
753         window.location='/cgi-bin/bweb/bresto.pl?action=restore' + res + res2 + res3 + res4;
754     }
755         var dialog = Ext.brestore.dlglaunch;
756         dialog.addKeyListener(27, dialog.hide, dialog);
757         dialog.addButton('Submit', launch_restore);
758         dialog.addButton('Close', dialog.hide, dialog);
759
760         var layout = dialog.getLayout();
761         layout.beginUpdate();
762         layout.add('center', new Ext.ContentPanel('div-resto-form', {
763                                     autoCreate:true, title: 'Third Tab', closable:true, background:true}));
764         layout.endUpdate();
765         dialog.show();
766
767             }
768         }
769     ]);
770
771 ////////////////////////////////////////////////////////////////
772
773     var layout = new Ext.BorderLayout(document.body, {
774         north: {
775 //            split: true
776         },
777         south: {
778             split: true, initialSize: 300
779         },
780         east: {
781             split: true, initialSize: 550
782         },
783         west: {
784             split: true, initialSize: 300
785         },
786         center: {
787             initialSize: 450
788         }        
789         
790     });
791
792 layout.beginUpdate();
793   layout.add('north', new Ext.ContentPanel('div-toolbar', {
794       fitToFrame: true, autoCreate:true,closable: false 
795   }));
796   layout.add('south', new Ext.ContentPanel('div-file-selection', {
797       toolbar: tb2,resizeEl:'div-file-selection',
798       fitToFrame: true, autoCreate:true,closable: false
799   }));
800   layout.add('east', new Ext.ContentPanel('div-file-versions', {
801       fitToFrame: true, autoCreate:true,closable: false
802   }));
803   layout.add('west', new Ext.ContentPanel('div-tree', {
804       autoScroll:true, fitToFrame: true, 
805       autoCreate:true,closable: false
806   }));
807   layout.add('center', new Ext.ContentPanel('div-files', {
808       autoScroll:true,autoCreate:true,fitToFrame: true
809   }));
810 layout.endUpdate();     
811
812
813 ////////////////////////////////////////////////////////////////
814
815 //    job_store.load();
816     client_store.load({params:{action: 'list_client'}});
817 //    file_store.load({params:{offset:0, limit:50}});
818 //    file_versions_store.load({params:{offset:0, limit:50}});
819 //    file_selection_store.load();
820
821 }
822 Ext.onReady( ext_init );