2 // Bweb - A Bacula web interface
3 // Bacula® - The Network Backup Solution
5 // Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
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.
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.
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.
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
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.
31 // render if vol is online/offline
32 function rd_vol_is_online(val)
34 return '<img src="/bweb/inflag' + val + '.png">';
37 // TODO: fichier ou rep
38 function rd_file_or_dir(val)
41 return '<img src="/bweb/A.png">';
43 return '<img src="/bweb/R.png">';
47 Ext.namespace('Ext.brestore');
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
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
62 function get_node_path(node)
65 for (var p = node; p; p = p.parentNode) {
70 temp = p.text + '/' + temp;
74 return Ext.brestore.root_path + temp;
78 function init_params(baseParams)
80 baseParams['client']= Ext.brestore.client;
82 if (Ext.brestore.option_vosb) {
83 baseParams['jobid'] = Ext.brestore.jobid;
85 baseParams['date'] = Ext.brestore.jobdate;
93 //////////////////////////////////////////////////////////////:
95 var tree_loader = new Ext.tree.TreeLoader({
97 dataUrl:'/cgi-bin/bweb/bresto.pl'
100 var tree = new Ext.tree.TreePanel('div-tree', {
104 enableDragDrop: true,
105 containerScroll: true
109 var root = new Ext.tree.AsyncTreeNode({
110 text: 'Select a job',
114 tree.setRootNode(root);
115 Ext.brestore.tree = root;
121 tree.on('click', function(node, event) {
122 Ext.brestore.path = get_node_path(node);
124 file_store.removeAll();
125 file_versions_store.removeAll();
126 file_store.load({params:init_params({action: 'list_files',
132 tree.on('beforeload', function(e) {
133 file_store.removeAll();
138 ////////////////////////////////////////////////////////////////
140 var file_store = new Ext.data.Store({
141 proxy: new Ext.data.HttpProxy({
142 url: '/cgi-bin/bweb/bresto.pl',
147 reader: new Ext.data.ArrayReader({
148 }, Ext.data.Record.create([
150 {name: 'filenameid'},
154 {name: 'size', type: 'int' },
155 {name: 'mtime', type: 'date', dateFormat: 'Y-m-d h:i:s'}
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 })
164 css: 'white-space:normal;'
168 renderer: human_size,
178 dataIndex: 'filenameid',
189 // by default columns are sortable
190 cm.defaultSortable = true;
193 var files_grid = new Ext.grid.Grid('div-files', {
198 enableDragDrop: true,
199 selModel: new Ext.grid.RowSelectionModel(),
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();
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,
218 filenameid: r.json[1]
225 //////////////////////////////////////////////////////////////:
227 var file_selection_store = new Ext.data.Store({
228 proxy: new Ext.data.MemoryProxy(),
230 reader: new Ext.data.ArrayReader({
231 }, Ext.data.Record.create([
234 {name: 'filenameid'},
237 {name: 'size', type: 'int' },
238 {name: 'mtime', type: 'date', dateFormat: 'Y-m-d h:i:s'}
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 })
254 renderer: human_size,
265 dataIndex: 'filenameid',
276 var file_selection_grid = new Ext.grid.Grid('div-file-selection', {
277 cm: file_selection_cm,
278 ds: file_selection_store,
282 selModel: new Ext.grid.RowSelectionModel(),
288 var file_selection_record = Ext.data.Record.create(
291 {name: 'filenameid'},
296 // data.selections[0].json[]
298 // http://extjs.com/forum/showthread.php?t=12582&highlight=drag+drop
299 var ddrow = new Ext.dd.DropTarget(file_selection_grid.container, {
302 notifyDrop : function(dd, e, data){
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]
316 file_selection_store.add(r)
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]
330 file_selection_store.add(r)
335 var path= get_node_path(data.node);
336 r = new file_selection_record({
337 jobid: data.node.attributes.jobid,
340 pathid: data.node.id,
345 file_selection_store.add(r)
352 file_selection_grid.on('enddrag', function(dd,e) {
353 alert(e) ; return true;
355 file_selection_grid.on('notifyDrop', function(dd,e) {
356 alert(e) ; return true;
358 file_selection_grid.render();
360 ///////////////////////////////////////////////////////
362 var file_versions_store = new Ext.data.Store({
363 proxy: new Ext.data.HttpProxy({
364 url: '/cgi-bin/bweb/bresto.pl',
366 params:{offset:0, limit:50 }
369 reader: new Ext.data.ArrayReader({
370 }, Ext.data.Record.create([
372 {name: 'filenameid'},
376 {name: 'inchanger' },
378 {name: 'size', type: 'int' },
379 {name: 'mtime'} //, type: 'date', dateFormat: 'Y-m-d h:i:s'}
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 })
389 dataIndex: 'inchanger',
391 renderer: rd_vol_is_online
402 renderer: human_size,
416 dataIndex: 'filenameid',
424 // by default columns are sortable
425 file_versions_cm.defaultSortable = true;
428 var file_versions_grid = new Ext.grid.Grid('div-file-versions', {
429 ds: file_versions_store,
430 cm: file_versions_cm,
434 selModel: new Ext.grid.RowSelectionModel(),
440 file_versions_grid.on('rowdblclick', function(e) {
441 alert(e) ; file_versions_store.removeAll(); return true;
443 file_versions_grid.render();
445 //////////////////////////////////////////////////////////////:
448 var client_store = new Ext.data.Store({
449 proxy: new Ext.data.HttpProxy({
450 url: '/cgi-bin/bweb/bresto.pl',
452 params:{action:'list_client'}
455 reader: new Ext.data.ArrayReader({
456 }, Ext.data.Record.create([
461 var client_combo = new Ext.form.ComboBox({
462 fieldLabel: 'Clients',
467 triggerAction: 'all',
468 emptyText:'Select a client...',
470 forceSelection: true,
474 client_combo.on('valid', function(e) {
475 Ext.brestore.client = e.getValue();
476 job_store.load( {params:{action: 'list_job',
477 client:Ext.brestore.client}});
481 //////////////////////////////////////////////////////////////:
483 var job_store = new Ext.data.Store({
484 proxy: new Ext.data.HttpProxy({
485 url: '/cgi-bin/bweb/bresto.pl',
487 params:{offset:0, limit:50 }
490 reader: new Ext.data.ArrayReader({
491 }, Ext.data.Record.create([
498 var job_combo = new Ext.form.ComboBox({
501 displayField:'jobname',
504 triggerAction: 'all',
505 emptyText:'Select a job...',
507 forceSelection: true,
511 job_combo.on('select', function(e,c) {
512 Ext.brestore.jobid = c.json[0];
513 Ext.brestore.jobdate = c.json[1];
514 Ext.brestore.root_path='';
515 root.setText("Root");
516 tree_loader.baseParams = init_params({init:1, action: 'list_dirs'});
520 ////////////////////////////////////////////////////////////////
522 function sel_option(item, check)
524 if (item.id == 'id_vosb') {
525 Ext.brestore.option_vosb = check;
527 if (item.id == 'id_vafv') {
528 Ext.brestore.option_vafv = check;
532 var menu = new Ext.menu.Menu({
535 new Ext.menu.CheckItem({
537 text: 'View only selected backup',
538 checked: Ext.brestore.option_vosb,
539 checkHandler: sel_option
541 new Ext.menu.CheckItem({
543 text: 'View all file versions',
544 checked: Ext.brestore.option_vafv,
545 checkHandler: sel_option
549 ////////////////////////////////////////////////////////////////:
551 // create the primary toolbar
552 var tb2 = new Ext.Toolbar('div-tb-sel');
554 var where_field = new Ext.form.TextField({
555 fieldLabel: 'Location',
561 var tb = new Ext.Toolbar('div-toolbar', [
567 // icon: '/bweb/up.gif',
568 text: 'Change location',
569 cls:'x-btn-text-icon',
570 handler: function() {
571 var where = where_field.getValue();
572 Ext.brestore.root_path=where;
574 tree_loader.baseParams = init_params({ action:'list_dirs', path: where });
581 cls: 'x-btn-text-icon bmenu', // icon and text class
583 menu: menu // assign menu by instance
586 icon: '/bweb/remove.png', // icons can also be specified inline
589 handler: function() {
590 if (Ext.brestore.dlglaunch) {
591 Ext.brestore.dlglaunch.show();
594 Ext.brestore.dlglaunch = new Ext.LayoutDialog("div-resto-dlg", {
608 // collapsible: true,
613 // tabPosition: 'top',
615 // alwaysShowTabs: true
619 var fs = new Ext.form.Form({
624 // var resto_store = new Ext.data.Store({
625 // proxy: new Ext.data.HttpProxy({
626 // url: '/cgi-bin/bweb/bresto.pl',
628 // params:{action:'list_resto'}
631 // reader: new Ext.data.ArrayReader({
632 // }, Ext.data.Record.create([
637 var rclient_combo = new Ext.form.ComboBox({
638 value: Ext.brestore.client,
639 fieldLabel: 'client',
645 triggerAction: 'all',
646 emptyText:'Select a client...',
650 var where_text = new Ext.form.TextField({
653 value: '/tmp/bacula-restore',
656 var storage_store = new Ext.data.Store({
657 proxy: new Ext.data.HttpProxy({
658 url: '/cgi-bin/bweb/bresto.pl',
660 params:{action:'list_storage'}
663 reader: new Ext.data.ArrayReader({
664 }, Ext.data.Record.create([
668 var storage_combo = new Ext.form.ComboBox({
669 fieldLabel: 'storage',
670 hiddenName:'storage',
671 store: storage_store,
675 triggerAction: 'all',
676 emptyText:'Select a storage...',
681 {legend:'Restore job'},
682 // new Ext.form.ComboBox({
683 // fieldLabel: 'Replace',
684 // hiddenName:'replace',
685 // store: new Ext.data.SimpleStore({
686 // fields: ['replace'],
687 // data : [['always'],['never'],['if newer']]
689 // displayField:'replace',
692 // triggerAction: 'all',
693 // emptyText:'never',
694 // selectOnFocus:true,
698 // new Ext.form.ComboBox({
699 // fieldLabel: 'job',
701 // store: resto_store,
702 // displayField:'name',
705 // triggerAction: 'all',
706 // emptyText:'Select a job...',
707 // selectOnFocus:true,
715 storage_store.load({params:{action: 'list_storage'}});
716 // resto_store.load({params:{action: 'list_resto'}});
717 fs.render('div-resto-form');
719 // var f = new Ext.form.BasicForm('div-resto-form', {url: '/bweb/test', method: 'GET',
720 // baseParams: {init: 1}
724 var launch_restore = function() {
725 var items = file_selection_store.data.items;
726 var tab_fileid=new Array();
727 var tab_dirid=new Array();
728 var tab_jobid=new Array();
729 for(var i=0;i<items.length;i++) {
730 if (items[i].data['fileid']) {
731 tab_fileid.push(items[i].data['fileid']);
733 tab_dirid.push(items[i].data['pathid']);
735 tab_jobid.push(items[i].data['jobid']);
737 var res = ';fileid=' + tab_fileid.join(";fileid=");
738 var res2 = ';dirid=' + tab_dirid.join(";dirid=");
739 var res3 = ';jobid=' + tab_jobid.join(";jobid=");
741 var res4 = ';client=' + rclient_combo.getValue() + ';storage=' + storage_combo.getValue() + ';where=' + where_text.getValue();
743 window.location='/cgi-bin/bweb/bresto.pl?action=restore' + res + res2 + res3 + res4;
745 var dialog = Ext.brestore.dlglaunch;
746 dialog.addKeyListener(27, dialog.hide, dialog);
747 dialog.addButton('Submit', launch_restore);
748 dialog.addButton('Close', dialog.hide, dialog);
750 var layout = dialog.getLayout();
751 layout.beginUpdate();
752 layout.add('center', new Ext.ContentPanel('div-resto-form', {
753 autoCreate:true, title: 'Third Tab', closable:true, background:true}));
761 ////////////////////////////////////////////////////////////////
763 var layout = new Ext.BorderLayout(document.body, {
768 split: true, initialSize: 300
771 split: true, initialSize: 550
774 split: true, initialSize: 300
782 layout.beginUpdate();
783 layout.add('north', new Ext.ContentPanel('div-toolbar', {
784 fitToFrame: true, autoCreate:true,closable: false
786 layout.add('south', new Ext.ContentPanel('div-file-selection', {
787 toolbar: tb2,resizeEl:'div-file-selection',
788 fitToFrame: true, autoCreate:true,closable: false
790 layout.add('east', new Ext.ContentPanel('div-file-versions', {
791 fitToFrame: true, autoCreate:true,closable: false
793 layout.add('west', new Ext.ContentPanel('div-tree', {
794 autoScroll:true, fitToFrame: true,
795 autoCreate:true,closable: false
797 layout.add('center', new Ext.ContentPanel('div-files', {
798 autoScroll:true,autoCreate:true,fitToFrame: true
803 ////////////////////////////////////////////////////////////////
806 client_store.load({params:{action: 'list_client'}});
807 // file_store.load({params:{offset:0, limit:50}});
808 // file_versions_store.load({params:{offset:0, limit:50}});
809 // file_selection_store.load();
812 Ext.onReady( ext_init );