]> git.sur5r.net Git - bacula/bacula/blob - gui/bweb/html/bresto.js
Merge in changes from trunk
[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.path='';            // current path (without user location)
53 Ext.brestore.root_path='';       // user location
54
55 Ext.brestore.option_vosb = false;
56 Ext.brestore.option_vafv = false;
57
58
59 function get_node_path(node)
60 {
61    var temp='';
62    for (var p = node; p; p = p.parentNode) {
63        if (p.parentNode) {
64           if (p.text == '/') {
65              temp = p.text + temp;
66           } else {
67           temp = p.text + '/' + temp;
68           }
69        }
70    }
71    return Ext.brestore.root_path + temp;
72 }
73
74
75 function init_params(baseParams)
76 {
77    baseParams['client']= Ext.brestore.client;
78
79    if (Ext.brestore.option_vosb) {         
80       baseParams['jobid'] = Ext.brestore.jobid;
81    } else {
82       baseParams['date'] = Ext.brestore.jobdate;
83    }
84    return baseParams;
85 }
86
87
88 function ext_init()
89 {
90 //////////////////////////////////////////////////////////////:
91     var Tree = Ext.tree;
92     var tree_loader = new Ext.tree.TreeLoader({
93             baseParams:{}, 
94             dataUrl:'/cgi-bin/bweb/bresto.pl'
95         });
96
97     var tree = new Ext.tree.TreePanel('div-tree', {
98         animate:true, 
99         loader: tree_loader,
100         enableDD:true,
101         enableDragDrop: true,
102         containerScroll: true
103     });
104
105     // set the root node
106     var root = new Ext.tree.AsyncTreeNode({
107         text: 'Select a job',
108         draggable:false,
109         id:'source'
110     });
111     tree.setRootNode(root);
112
113     // render the tree
114     tree.render();
115 //    root.expand();
116
117     tree.on('click', function(node, event) { 
118         Ext.brestore.path = get_node_path(node);
119
120         file_store.removeAll();
121         file_versions_store.removeAll();
122         file_store.load({params:init_params({action: 'list_files',
123                                              node:node.id})
124                        });
125         return true;
126     });
127
128     tree.on('beforeload', function(e) {
129         file_store.removeAll();
130         return true;
131     });
132
133
134 ////////////////////////////////////////////////////////////////
135
136   var file_store = new Ext.data.Store({
137         proxy: new Ext.data.HttpProxy({
138             url: '/cgi-bin/bweb/bresto.pl',
139             method: 'GET',
140             params:{}
141         }),
142
143         reader: new Ext.data.ArrayReader({
144         }, Ext.data.Record.create([
145    {name: 'fileid'    },
146    {name: 'filenameid'},
147    {name: 'pathid'    },
148    {name: 'name'      },
149    {name: 'size',     type: 'int'  },
150    {name: 'mtime',    type: 'date', dateFormat: 'Y-m-d h:i:s'}
151         ]))
152    });
153
154    var cm = new Ext.grid.ColumnModel([{
155            id:        'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
156            header:    'File',
157            dataIndex: 'name',
158            width:     100,
159            css:       'white-space:normal;'
160         },{
161            header:    "Size",
162            dataIndex: 'size',
163            renderer:  human_size,
164            width:     50
165         },{
166            header:    "Date",
167            dataIndex: 'mtime',
168            width:     100
169         },{
170            dataIndex: 'pathid',
171            hidden: true
172         },{
173            dataIndex: 'filenameid',
174            hidden: true
175         },{
176            dataIndex: 'fileid',
177            hidden: true
178         }
179         ]);
180
181     // by default columns are sortable
182    cm.defaultSortable = true;
183
184     // create the grid
185    var files_grid = new Ext.grid.Grid('div-files', {
186         ds: file_store,
187         cm: cm,
188         ddGroup : 'TreeDD',
189         enableDrag: true,
190         enableDragDrop: true,
191         selModel: new Ext.grid.RowSelectionModel(),
192         loadMask: true,
193         enableColLock:false
194         
195     });
196
197     // when we reload the view,
198     // we clear the file version box
199     file_store.on('beforeload', function(e) {
200         file_versions_store.removeAll();
201         return true;
202     });
203
204     // TODO: selection only when using dblclick
205     files_grid.selModel.on('rowselect', function(e,i,r) { 
206         Ext.brestore.filename = r.json[3];
207         file_versions_store.load({params:init_params({action: 'list_versions',
208                                                      vafv: Ext.brestore.option_vafv,
209                                                      pathid: r.json[2],
210                                                      filenameid: r.json[1]
211                                                      })
212                                  });
213         return true;
214     });
215     files_grid.render();
216
217 //////////////////////////////////////////////////////////////:
218
219   var file_selection_store = new Ext.data.Store({
220         proxy: new Ext.data.MemoryProxy(),
221
222         reader: new Ext.data.ArrayReader({
223         }, Ext.data.Record.create([
224    {name: 'jobid'     },
225    {name: 'fileid'    },
226    {name: 'filenameid'},
227    {name: 'pathid'    },
228    {name: 'name'      },
229    {name: 'size',     type: 'int'  },
230    {name: 'mtime',    type: 'date', dateFormat: 'Y-m-d h:i:s'}
231         ]))
232    });
233
234    var file_selection_cm = new Ext.grid.ColumnModel([{
235            id:        'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
236            header:    "Name",
237            dataIndex: 'name',
238            width:     250
239         },{
240            header:    "JobId",
241            width:     50,
242            dataIndex: 'jobid'
243         },{
244            header:    "Size",
245            dataIndex: 'size',
246            renderer:  human_size,
247            width:     50
248         },{
249            header:    "Date",
250            dataIndex: 'mtime',
251            width:     100
252         },{
253            dataIndex: 'pathid',
254            hidden: true
255         },{
256            dataIndex: 'filenameid',
257            hidden: true
258         },{
259            dataIndex: 'fileid',
260            hidden: true
261         }
262         ]);
263
264
265     // create the grid
266    var file_selection_grid = new Ext.grid.Grid('div-file-selection', {
267         cm: file_selection_cm,
268         ds: file_selection_store,
269         ddGroup : 'TreeDD',
270         enableDrag: false,
271         enableDrop: true,
272         selModel: new Ext.grid.RowSelectionModel(),
273         loadMask: true,
274         enableColLock:false
275         
276     });
277
278     var file_selection_record = Ext.data.Record.create(
279       {name: 'jobid'},
280       {name: 'fileid'},
281       {name: 'filenameid'},
282       {name: 'pathid'},
283       {name: 'size'},
284       {name: 'mtime'}
285     );
286 // data.selections[0].json[]
287 // data.node.id
288 // http://extjs.com/forum/showthread.php?t=12582&highlight=drag+drop
289     var ddrow = new Ext.dd.DropTarget(file_selection_grid.container, {
290         ddGroup : 'TreeDD',
291         copy:false,
292         notifyDrop : function(dd, e, data){
293            var r;
294            if (data.selections) {
295              if (data.grid.id == 'div-files') {
296                  for(var i=0;i<data.selections.length;i++) {
297                     r = new file_selection_record({
298                       jobid:     Ext.brestore.jobid,
299                       fileid:    data.selections[i].json[0],
300                       filenameid:data.selections[i].json[1],
301                       pathid:    data.selections[i].json[2],
302                       name: Ext.brestore.path + data.selections[i].json[3],
303                       size:      data.selections[i].json[4],
304                       mtime:     data.selections[i].json[5]
305                     });
306                     file_selection_store.add(r)
307                  }
308              }
309
310              if (data.grid.id == 'div-file-versions') {
311                     r = new file_selection_record({
312                       jobid:     data.selections[0].json[3],
313                       fileid:    data.selections[0].json[0],
314                       filenameid:data.selections[0].json[1],
315                       pathid:    data.selections[0].json[2],
316                       name: Ext.brestore.path + Ext.brestore.filename,
317                       size:      data.selections[0].json[7],
318                       mtime:     data.selections[0].json[8]     
319                     });
320                     file_selection_store.add(r)
321              }
322            }
323   
324            if (data.node) {
325               var path= get_node_path(data.node);
326               r = new file_selection_record({
327                       jobid:     Ext.brestore.jobid,
328                       fileid:    0,
329                       filenameid:0,
330                       pathid:    data.node.id,
331                       name:      path,
332                       size:      4096,
333                       mtime:     0
334               });
335               file_selection_store.add(r)
336            }
337   
338            return true;
339     }});
340
341
342    file_selection_grid.on('enddrag', function(dd,e) { 
343         alert(e) ; return true;
344     });
345    file_selection_grid.on('notifyDrop', function(dd,e) { 
346         alert(e) ; return true;
347     });
348    file_selection_grid.render();
349
350 ///////////////////////////////////////////////////////
351
352   var file_versions_store = new Ext.data.Store({
353         proxy: new Ext.data.HttpProxy({
354             url: '/cgi-bin/bweb/bresto.pl',
355             method: 'GET',
356             params:{offset:0, limit:50 }
357         }),
358
359         reader: new Ext.data.ArrayReader({
360         }, Ext.data.Record.create([
361    {name: 'fileid'    },
362    {name: 'filenameid'},
363    {name: 'pathid'    },
364    {name: 'jobid'     },
365    {name: 'volume'    },
366    {name: 'inchanger' },
367    {name: 'md5'       },
368    {name: 'size',     type: 'int'  },
369    {name: 'mtime'} //,    type: 'date', dateFormat: 'Y-m-d h:i:s'}
370         ]))
371    });
372
373    var file_versions_cm = new Ext.grid.ColumnModel([{
374            id:        'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
375            dataIndex: 'name',
376            hidden: true
377         },{
378            header:    "InChanger",
379            dataIndex: 'inchanger',
380            width:     60,
381            renderer:  rd_vol_is_online
382         },{
383            header:    "Volume",
384            dataIndex: 'volume'
385         },{
386            header:    "JobId",
387            width:     50,
388            dataIndex: 'jobid'
389         },{
390            header:    "Size",
391            dataIndex: 'size',
392            renderer:  human_size,
393            width:     50
394         },{
395            header:    "Date",
396            dataIndex: 'mtime',
397            width:     100
398         },{
399            header:    "MD5",
400            dataIndex: 'md5',
401            width:     160
402         },{
403            dataIndex: 'pathid',
404            hidden: true
405         },{
406            dataIndex: 'filenameid',
407            hidden: true
408         },{
409            dataIndex: 'fileid',
410            hidden: true
411         }
412    ]);
413
414     // by default columns are sortable
415    file_versions_cm.defaultSortable = true;
416
417     // create the grid
418    var file_versions_grid = new Ext.grid.Grid('div-file-versions', {
419         ds: file_versions_store,
420         cm: file_versions_cm,
421         ddGroup : 'TreeDD',
422         enableDrag: true,
423         enableDrop: false,
424         selModel: new Ext.grid.RowSelectionModel(),
425         loadMask: true,
426         enableColLock:false
427         
428     });
429
430     file_versions_grid.on('rowdblclick', function(e) { 
431         alert(e) ; file_versions_store.removeAll(); return true;
432     });
433     file_versions_grid.render();
434
435 //////////////////////////////////////////////////////////////:
436
437
438     var client_store = new Ext.data.Store({
439         proxy: new Ext.data.HttpProxy({
440             url: '/cgi-bin/bweb/bresto.pl',
441             method: 'GET',
442             params:{action:'list_client'}
443         }),
444
445         reader: new Ext.data.ArrayReader({
446         }, Ext.data.Record.create([
447            {name: 'name' }
448         ]))
449     });
450
451     var client_combo = new Ext.form.ComboBox({
452         fieldLabel: 'Clients',
453         store: client_store,
454         displayField:'name',
455         typeAhead: true,
456         mode: 'local',
457         triggerAction: 'all',
458         emptyText:'Select a client...',
459         selectOnFocus:true,
460         forceSelection: true,
461         width:135
462     });
463
464     client_combo.on('valid', function(e) { 
465         Ext.brestore.client = e.getValue();
466         job_store.load( {params:{action: 'list_job',
467                                  client:Ext.brestore.client}});
468         return true;
469     });
470
471 //////////////////////////////////////////////////////////////:
472
473     var job_store = new Ext.data.Store({
474         proxy: new Ext.data.HttpProxy({
475             url: '/cgi-bin/bweb/bresto.pl',
476             method: 'GET',
477             params:{offset:0, limit:50 }
478         }),
479
480         reader: new Ext.data.ArrayReader({
481         }, Ext.data.Record.create([
482            {name: 'jobid' },
483            {name: 'date'  },
484            {name: 'jobname' }
485         ]))
486     });
487
488     var job_combo = new Ext.form.ComboBox({
489         fieldLabel: 'Jobs',
490         store: job_store,
491         displayField:'jobname',
492         typeAhead: true,
493         mode: 'local',
494         triggerAction: 'all',
495         emptyText:'Select a job...',
496         selectOnFocus:true,
497         forceSelection: true,
498         width:350
499     });
500
501     job_combo.on('select', function(e,c) {
502         Ext.brestore.jobid = c.json[0];
503         Ext.brestore.jobdate = c.json[1];
504         Ext.brestore.root_path='';
505         root.setText("Root");
506         tree_loader.baseParams = init_params({init:1, action: 'list_dirs'});
507         root.reload();
508     });
509
510 ////////////////////////////////////////////////////////////////
511
512     function sel_option(item, check)
513     {
514         if (item.id == 'id_vosb') {
515            Ext.brestore.option_vosb = check;
516         }
517         if (item.id == 'id_vafv') {
518            Ext.brestore.option_vafv = check;
519         }
520     }
521
522     var menu = new Ext.menu.Menu({
523         id: 'div-main-menu',
524         items: [ 
525            new Ext.menu.CheckItem({
526                 id: 'id_vosb',
527                 text: 'View only selected backup',
528                 checked: Ext.brestore.option_vosb,
529                 checkHandler: sel_option
530             }),
531            new Ext.menu.CheckItem({
532                 id: 'id_vafv',
533                 text: 'View all file versions',
534                 checked: Ext.brestore.option_vafv,
535                 checkHandler: sel_option
536             })
537         ]
538     });
539 ////////////////////////////////////////////////////////////////:
540
541     // create the primary toolbar
542     var tb2 = new Ext.Toolbar('div-tb-sel');
543     tb2.add({
544         id:'save',
545         text:'Save',
546         disabled:true,
547 //        handler:save,
548         cls:'x-btn-text-icon save',
549         tooltip:'Saves all components to the server'
550     },'-', {
551         id:'add',
552         text:'Component',
553 //        handler:addComponent,
554         cls:'x-btn-text-icon add-cmp',
555         tooltip:'Add a new Component to the dependency builder'
556     }, {
557         id:'option',
558         text:'Option',
559         disabled:true,
560 //        handler:addOption,
561         cls:'x-btn-text-icon add-opt',
562         tooltip:'Add a new optional dependency to the selected component'
563     },'-',{
564         id:'remove',
565         text:'Remove',
566         disabled:true,
567 //        handler:removeNode,
568         cls:'x-btn-text-icon remove',
569         tooltip:'Remove the selected item'
570     });
571
572     var where_field = new Ext.form.TextField({
573             fieldLabel: 'Location',
574             name: 'where',
575             width:175,
576             allowBlank:false
577     });
578
579     var tb = new Ext.Toolbar('div-toolbar', [
580         client_combo,
581         job_combo,
582         '-',
583         {
584           id: 'tb_home',
585 //        icon: '/bweb/up.gif',
586           text: 'Change location',
587           cls:'x-btn-text-icon',
588           handler: function() { 
589                 var where = where_field.getValue();
590                 Ext.brestore.root_path=where;
591                 root.setText(where);
592                 tree_loader.baseParams = init_params({ action:'list_dirs', path: where });
593                 root.reload();
594           }
595         },
596         where_field,
597         '-',
598         {
599             cls: 'x-btn-text-icon bmenu', // icon and text class
600             text:'Options',
601             menu: menu  // assign menu by instance
602         },
603         {
604             icon: '/bweb/remove.png', // icons can also be specified inline
605             cls: 'x-btn-icon',
606             text: 'restore',
607             handler: function() { 
608                 var dialog = new Ext.LayoutDialog("div-resto-dlg", { 
609 //                        modal:true,
610                         width:600,
611                         height:400,
612                         shadow:true,
613                         minWidth:300,
614                         minHeight:300,
615                         proxyDrag: true,
616 //                        west: {
617 //                              split:true,
618 //                              initialSize: 150,
619 //                              minSize: 100,
620 //                              maxSize: 250,
621 //                              titlebar: true,
622 //                              collapsible: true,
623 //                              animate: true
624 //                          },
625                         center: {
626                                 autoScroll:true,
627 //                              tabPosition: 'top',
628 //                              closeOnTab: true,
629 //                              alwaysShowTabs: true
630                         }
631                 });
632                 dialog.addKeyListener(27, dialog.hide, dialog);
633                 dialog.addButton('Submit', dialog.hide, dialog);
634                 dialog.addButton('Close', dialog.hide, dialog);
635
636     var fs = new Ext.form.Form({
637         labelAlign: 'right',
638         labelWidth: 80
639     });
640
641     fs.fieldset(
642         {legend:'Restore job'},
643         new Ext.form.ComboBox({
644             fieldLabel: 'Replace',
645             hiddenName:'replace',
646             store: new Ext.data.SimpleStore({
647                  fields: ['replace'],
648                  data : [['always'],['never'],['if newer']]
649             }),
650             displayField:'replace',
651             typeAhead: true,
652             mode: 'local',
653             triggerAction: 'all',
654             emptyText:'never',
655             selectOnFocus:true,
656             width:190
657         }),
658
659         new Ext.form.ComboBox({
660             fieldLabel: 'job',
661             hiddenName:'job',
662             store: client_store,
663             displayField:'name',
664             typeAhead: true,
665             mode: 'local',
666             triggerAction: 'all',
667             emptyText:'Select a job...',
668             selectOnFocus:true,
669             width:190
670         })
671 //      ,
672 //        new Ext.form.TextField({
673 //            fieldLabel: 'Where',
674 //            name: 'where',
675 //            width:190
676 //        }),
677 //
678 //        new Ext.form.ComboBox({
679 //            fieldLabel: 'client',
680 //            hiddenName:'client',
681 //            store: client_store,
682 //            displayField:'name',
683 //            typeAhead: true,
684 //            mode: 'local',
685 //            triggerAction: 'all',
686 //            emptyText:'Select a client...',
687 //            selectOnFocus:true,
688 //            width:190
689 //        }),
690 //        new Ext.form.ComboBox({
691 //            fieldLabel: 'storage',
692 //            hiddenName:'storage',
693 //            store: client_store,
694 //            displayField:'name',
695 //            typeAhead: true,
696 //            mode: 'local',
697 //            triggerAction: 'all',
698 //            emptyText:'Select a storage...',
699 //            selectOnFocus:true,
700 //            width:190
701 //        })
702     );
703
704     fs.render('div-resto-form');
705
706 //      var f = new Ext.form.BasicForm('div-resto-form', {url: '/bweb/test', method: 'GET',
707 //                                                      baseParams: {init: 1}
708 //                                                     }
709 //                                     );
710
711                 var layout = dialog.getLayout();
712                 layout.beginUpdate();
713                 layout.add('center', new Ext.ContentPanel('div-resto-form', {
714                                     autoCreate:true, title: 'Third Tab', closable:true, background:true}));
715                 layout.endUpdate();
716                 dialog.show();
717             }
718         }
719     ]);
720
721 ////////////////////////////////////////////////////////////////
722
723     var layout = new Ext.BorderLayout(document.body, {
724         north: {
725 //            split: true
726         },
727         south: {
728             split: true, initialSize: 300
729         },
730         east: {
731             split: true, initialSize: 550
732         },
733         west: {
734             split: true, initialSize: 300
735         },
736         center: {
737             initialSize: 450
738         }        
739         
740     });
741
742 layout.beginUpdate();
743   layout.add('north', new Ext.ContentPanel('div-toolbar', {
744       fitToFrame: true, autoCreate:true,closable: false 
745   }));
746   layout.add('south', new Ext.ContentPanel('div-file-selection', {
747       toolbar: tb2,resizeEl:'div-file-selection',
748       fitToFrame: true, autoCreate:true,closable: false
749   }));
750   layout.add('east', new Ext.ContentPanel('div-file-versions', {
751       fitToFrame: true, autoCreate:true,closable: false
752   }));
753   layout.add('west', new Ext.ContentPanel('div-tree', {
754       autoScroll:true, fitToFrame: true, 
755       autoCreate:true,closable: false
756   }));
757   layout.add('center', new Ext.ContentPanel('div-files', {
758       autoScroll:true,autoCreate:true,fitToFrame: true
759   }));
760 layout.endUpdate();     
761
762
763 ////////////////////////////////////////////////////////////////
764
765 //    job_store.load();
766     client_store.load({params:{action: 'list_client'}});
767 //    file_store.load({params:{offset:0, limit:50}});
768 //    file_versions_store.load({params:{offset:0, limit:50}});
769 //    file_selection_store.load();
770
771 }
772 Ext.onReady( ext_init );